Skip to content

Instantly share code, notes, and snippets.

@terrillmoore
Last active January 22, 2017 04:13
Show Gist options
  • Select an option

  • Save terrillmoore/c95fe22fc3d6713c0d94d2e3dc59dbb3 to your computer and use it in GitHub Desktop.

Select an option

Save terrillmoore/c95fe22fc3d6713c0d94d2e3dc59dbb3 to your computer and use it in GitHub Desktop.
Keil RTXv5 (API v2) MCB18xx / LPC18xx RTX-Blinky + UART example

Convert RTX-Blinky from RTXv4 to RTXv5, and add UART Example

There is no example for using a UART in conjunction with RTXv5 as of this writing. This gist presents an adapted example that was tested in conjunction with Keil V5, RTX APIv2 and the Blinky example.

Create the project

Create the RTX_Blinky project in a spare directory using the "Pack Installer" button.

  1. Press the pack installer buttong.
  2. In the left panel, select Boards and select MCB1800>Devices>LPC1857.
  3. In the right panel, select Examples, and then "CMSIS-RTOS Blinky (MCB1800)". Press the [Copy] button.
  4. Select someplace to put the files. The Keil IDE will create subdirectories from this directory. Avoid using an existing location!
  5. Build, download, and verify that Blinky is working.

This project uses RTX V4 (APIv1). We need to convert it to RTX V5 (APIv2).

Follow the Keil instructions to convert the project

Follow the Level 1 Migration instructions steps 1 through 8 to convert the project. (Step 9 is covered in the next section.)

Convert Blinky.c to support RTX

As the instructions for step 9 are not very clear, here's a pre-converted file.

  1. You must patch the Blinky.c initialization code. Replace the main() function by the following.

void app_main(void *arg) { // later, we'll enable this #if 0 extern ARM_DRIVER_USART Driver_USART3;

if (! uart_test_create_thread(&Driver_USART3))
	__breakpoint(0);

#endif

LED_Initialize(); /* Initialize the LEDs */ tid_phaseA = osThreadCreate(osThread(phaseA), NULL); tid_phaseB = osThreadCreate(osThread(phaseB), NULL); tid_phaseC = osThreadCreate(osThread(phaseC), NULL); tid_phaseD = osThreadCreate(osThread(phaseD), NULL); tid_clock = osThreadCreate(osThread(clock), NULL);

osSignalSet(tid_phaseA, 0x0001); /* set signal to phaseA thread */

osDelay(osWaitForever); while(1); }

// main() is not running as part of a thread. int main (void) { // the RTX conversion instructions talk about Init_Hardware(); but // this is actually not somthing that is part of CMSIS or RTX. For the // MCB1800, we don't need an Init_Hardware() function.

// Init_Hardware();
SystemCoreClockUpdate();
osKernelInitialize();
osThreadNew(app_main, NULL, NULL);
if (osKernelGetState() == osKernelReady)
	osKernelStart();

while(1);

} ``` 2. Edit the System Configuration settings in RTX_Config.h using the Keil Configuration Wizard. I set the memory pool size to 8192 bytes. I left the other settings at their defaults. 3. Compile and download. Blinky should work properly

Add Uart function

The example UART application at the CMSIS-Driver V2.04 page uses V1 APIs, and also doesn't work for me.

  1. Please see uart_test.c and uart_test.h elsewhere in this gist. Download them and put them in the same folder as Blinky.c.
  2. Add uart_test.c to the project and recompile. Verify that everything is clean. If you like, download and verify that nothing is broken (nothing yet has changed).
  3. Make sure J13 and J16 are set to bring the output of UART3 to the DB9 on the MCB18xx board.
  4. Connect a USB-to-Serial adapter to the female DB9. Depending on what kind of adapter you're using, you may have to remove the jack screws on your board.
  5. Connect the USB-to-Serial adapter to a suitable host PC. Open a terminal emulation program like Tera Term, and connect to the serial port. Make sure the settings are 115200, 8 bits, no parity, 1 stop bit.
  6. Edit Blinky.c and change the following lines from:
    // later, we'll enable this
    #if 0
     extern ARM_DRIVER_USART Driver_USART3;
     
     if (! uart_test_create_thread(&Driver_USART3))
     	__breakpoint(0);
    #endif
    to
     // set up serial thread
     extern ARM_DRIVER_USART Driver_USART3;
     
     if (! uart_test_create_thread(&Driver_USART3))
     	__breakpoint(0);
  7. At the front of Blinky.c, after the #include "Board_LED.h", add the following line:
    #include "uart_test.h"
  8. Build and download
  9. On the terminal, you should see:
    
    Press enter...
    
    
    Each time you press enter, the program will print:
    
    Hello, world!
    
    

Things to note

  1. I had to change the buffer for the input character from a char to a static char; otherwise RTX would call osError() complaining about a corrupt stack. I did not find a root cause; I made the change based on narrowing down the crash, and guessing.
  2. As mentioned previously, the RTX documentation talks about needing an Init_Hardware() routine. That's not needed on the MCB1800, and I could find no reference code.
#include "usart_test.h"
#include "cmsis_os2.h" /* ARM::CMSIS:RTOS:Keil RTX */
#include <stdio.h>
#include <string.h>
static void myUART_Thread(void *argument);
static osThreadId_t tid_myUART_Thread;
/* USART Driver */
static void myUSART_callback(uint32_t event)
{
uint32_t mask;
mask = ARM_USART_EVENT_RECEIVE_COMPLETE |
ARM_USART_EVENT_TRANSFER_COMPLETE |
ARM_USART_EVENT_SEND_COMPLETE |
ARM_USART_EVENT_TX_COMPLETE ;
if (event & mask) {
/* Success: Wakeup Thread */
osThreadFlagsSet(tid_myUART_Thread, 0x01);
}
if (event & ARM_USART_EVENT_RX_TIMEOUT) {
__breakpoint(0); /* Error: Call debugger or replace with custom error handling */
}
if (event & (ARM_USART_EVENT_RX_OVERFLOW | ARM_USART_EVENT_TX_UNDERFLOW)) {
__breakpoint(0); /* Error: Call debugger or replace with custom error handling */
}
}
/* CMSIS-RTOS Thread - UART command thread */
static void myUART_Thread(void* arg)
{
ARM_DRIVER_USART * const USARTdrv = arg;
static char cmd;
#ifdef DEBUG
ARM_DRIVER_VERSION version;
ARM_USART_CAPABILITIES drv_capabilities;
version = USARTdrv->GetVersion();
if (version.api < 0x200) /* requires at minimum API version 2.00 or higher */
{ /* error handling */
return;
}
drv_capabilities = USARTdrv->GetCapabilities();
if (drv_capabilities.event_tx_complete == 0)
{ /* error handling */
return;
}
#endif
/*Initialize the USART driver */
USARTdrv->Initialize(myUSART_callback);
/*Power up the USART peripheral */
USARTdrv->PowerControl(ARM_POWER_FULL);
/*Configure the USART to 4800 Bits/sec */
USARTdrv->Control(ARM_USART_MODE_ASYNCHRONOUS |
ARM_USART_DATA_BITS_8 |
ARM_USART_PARITY_NONE |
ARM_USART_STOP_BITS_1 |
ARM_USART_FLOW_CONTROL_NONE, 115200);
/* Enable Receiver and Transmitter lines */
USARTdrv->Control (ARM_USART_CONTROL_TX, 1);
USARTdrv->Control (ARM_USART_CONTROL_RX, 1);
static const char InitMsg[] = "\r\nPress enter...\r\n";
static const char HelloMsg[] = "\r\nHello, world!\r\n";
USARTdrv->Send(InitMsg, sizeof(InitMsg));
osThreadFlagsWait(0x01, NULL, osWaitForever); // clear the flag on wakeup
while (1)
{
USARTdrv->Receive(&cmd, 1); /* Get byte from UART */
osThreadFlagsWait(0x01, NULL, osWaitForever);
if (cmd == 13) /* CR, send greeting */
{
USARTdrv->Send(HelloMsg, sizeof(HelloMsg));
osThreadFlagsWait(0x01, NULL, osWaitForever);
}
}
}
/* create the UART test thread */
bool
uart_test_create_thread(
ARM_DRIVER_USART *pUsart
)
{
osThreadAttr_t attr =
{
.name = "UART_test",
.attr_bits = osThreadDetached,
.cb_mem = NULL,
.cb_size = 0,
.stack_mem = NULL,
.stack_size = 256,
.priority = osPriorityBelowNormal7,
};
tid_myUART_Thread = osThreadNew(
myUART_Thread,
/* argument */ (void *) pUsart,
/* attributes */ &attr
);
return tid_myUART_Thread != NULL;
}
#ifndef _UART_TEST_H_
# define _UART_TEST_H_ /* prevent multiple includes */
#include "Driver_USART.h"
bool
uart_test_create_thread(
ARM_DRIVER_USART *pUsart
);
#endif /* _UART_TEST_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment