School of Computing Sciences CMPE3D02/SMD02 Embedded Systems Laboratory Sheet 5: 1.0 Introduction MDK-ARM: Introduction to RL-RTX RL-RTX is the real-time operating system (RTOS) component of the ARM Real- Time Library (RL-ARM). RL-RTX provides a framework to manage several jobs (tasks) on a single CPU that supports task priorities, context switching, and messaging. 2.0 Objective To introduce RL-RTX and configure a simple RTX application program. 3.0 Procedure 1. Create a new project named /RTX_ex1/RTX_ex1.uvproj. In the Target tab of the Options for Target select the Operating system: RTX Kernel and tick the option Use MicroLIB. 2. Copy the following files and include them in your project: a. RTX_Conf_CM.c b. system_stm32f10x_cl.c These can be found in a number of places e.g. (C:\Keil\ARM\Boards\Keil\MCBSTM32C\RTX_Blinky) 3. Consider the following scenario: A microcontroller must continuously execute two activities (tasks). Activity 1 must begin 50 ms after activity 2 completes and activity 2 must begin 20 ms after activity 1 completes; as shown in the following diagram: Task 1 Task 2 20 ms 50 ms
4. The code for the two activities can be defined as two separate functions (task1 and task2). Declare the two functions as tasks using the keyword task (defined in RTL.H) which indicates a RTX task. The main() function simply initialises the timers and calls RTX function Pass the function name of the first task as the parameter to the os_sys_init function. int main (void) { SystemInit(); /* initialize clocks */ os_sys_init (task1); /* Initialize RTX and start task1 */ 5. Consider the function task1() (Appendix A). Each task has a unique idnumber; task1 first assigns its own id_number and then creates task2, assigning its id-number. Since task1 must repeat indefinitely the task1 s code is placed in an infinite loop. Task 1 doesn t do any useful work (for now) it simply uses an Event Flag to send a signal to (wake up) task 2 and wait for task 2 to signal it has completed. Then it must wait for 50 ms before it can perform the activity again. The os_dly_wait() function with argument 5 provides the delay. RTX uses timer 0 to provide system timing; if you take a look at the configuration file RTX_Config_CM.c and select the Configuration Wizard tab then you ll see the Tick value is set to 10 ms. The os_evt_wait_or function is used to make task1 wait for completion of task2, and the os_evt_set function sends the signal to task2. This example uses bit 2 (position 3) of the event flags to inform the other task when it completes. 6. Modify the code to toggle a LED (i.e. task 1 switches the LED ON and task 2 switches it OFF). Change the os_dly_wait parameter so that the led is ON for 1 sec. and OFF for 0.5 sec. 7. The debugger can be used to display general information about system resources (i.e. Debug -> OS Support). First check that the operating system (RTX Kernel) has been selected in the Target tab of the Project Options dialog and then run the code in the debugger. Active Tasks: shows currently active tasks and their status. System: shows the system information for the application.
8. The event viewer can be used (while debugging) to display a real-time execution trace for your code. Before you can use this feature (with ULINK2) you must enable serial wire trace. To Enable the Trace Port Interface create the file called conf_stm32f10_swo.ini shown in Appendix B and save it in your project folder [2]. Set Options for Target -> Debug as shown (entering the name of the initialization file). In the Settings dialog (Debug tab) select the Serial Wire Interface.
In the Trace tab select Enable Trace Now invoke the debugger, execute the code, and select the Event Viewer. 9. The project RTX_Blinky supplied by Keil has more tasks and gives a more interesting trace.
Note: The RTX example projects in C:\Keil\ARM\Boards\Keil\MCBSTM32C deal with more challenging scenarios. Try these before attempting assignment 2. 4.0 References 1. Keil Software, Getting Started: Building Applications with RL-ARM, Keil Software, 2010. 2. ULINK2 User s Guide, http://www.keil.com/support/man/docs/ulink2/ulink2_stm32f10xxx_swt.ht m (last accessed 18.11.13).
Appendix A * RL-ARM - RTX *---------------------------------------------------------------------------- * Name: RTX_EX1.C * Purpose: Your First RTX example program *---------------------------------------------------------------------------- * This code is part of the RealView Run-Time Library. * Copyright (c) 2004-2010 KEIL - An ARM Company. All rights reserved. #include <RTL.h> /* RTX kernel functions & defines */ #include <stm32f10x_cl.h> /* id1, id2 will contain task identifications at run-time */ OS_TID id1, id2; /* Forward reference */ task void task1 (void); task void task2 (void); * Task 1: RTX Kernel starts this task with os_sys_init (task1) task void task1 (void) { /* Obtain own system task identification number */ id1 = os_tsk_self (); /* Assign system identification number of task2 to id2 */ id2 = os_tsk_create (task2, 1); for (;;) { /* do-this */ /* Indicate to task2 completion of do-this */ os_evt_set (0x0004, id2); /* Wait for completion of do-that (0xffff means no time-out)*/ os_evt_wait_or (0x0004, 0xffff); /* Wait now for 50 ms */ os_dly_wait (5); * Task 2: RTX Kernel starts this task with os_tsk_create (task2, 1) task void task2 (void) { for (;;) { /* Wait for completion of do-this (0xffff means no time-out) */ os_evt_wait_or (0x0004, 0xffff); /* do-that */ /* Pause for 20 ms until signaling event to task1 */ os_dly_wait (2); /* Indicate to task1 completion of do-that */ os_evt_set (0x0004, id1); * Main: Initialize and start RTX Kernel int main (void) { SystemInit(); /* initialize clocks */ os_sys_init (task1); start task1 */ /* Initialize RTX and * end of file
Appendix B - /* Code to Enable Serial wire Trace on ULINK2 /* See http://www.keil.com/support/man/docs/ulink2/ulink2_stm32f10xxx_swt.htm /*---------------------------------------------------------------------------/* - ** Define the function to enable the trace port * FUNC void EnableTPIU(void) { _WDWORD(0xE0042004, 0x00000020); // Set asynchronous communication via DBGMCU_CR - ** Invoke the function at debugger startup * EnableTPIU();