Lab 2: Writing a Task Objectives: In this lab, you will be taken through the process of writing a task for a µC/OS-III application.. You’ll write a new task that outputs messages to the
Trang 1DevCon 2012 9L05I: Getting Started with Micriµm’s µC/OS-III Kernel
Lab Guide The hands-on portion of this class consists of four coding exercises These exercises embody the concepts covered in the lecture portion of the class In order to complete the exercises, you’ll need to follow the step-by-step instructions provided in this lab guide
Lab 1: Becoming Familiar with µC/OS-III
Objectives: This exercise, which involves building and running a µC/OS-III-based application, will introduce you to the tools and source code that you will use throughout the class
Procedure:
1 The hardware platform for the class is the YRDKRX63N board You should now connect your board to your PC using the provided USB cable The YRDKRX63N has two USB
connectors; you should use the one labeled J-LINK USB.
2 You will build each of this class’s exercises using Renesas’s e2studio To open this IDE, you can either double-click its desktop shortcut or select All Programs>Renesas>Renesas E2Studio from your PC’s Start menu.
3 Before the e2studio IDE opens, you may see a dialog prompting you to select a workspace You should select the location shown below If you do not see the dialog, you can change the workspace within the IDE, as detailed in the next step.)
C:\Workspace\9L05I_Micrium_uC-OSIII
4 If you were able to use the dialog described in the previous step to select your workspace, then the four projects shown in the screenshot on the next page
(uCOSIII_Lab_1, uCOSIII_Lab_2, uCOSIII_Lab_3, and uCOSIII_Lab_4) should appear in
e2studio’s Project Explorer when the IDE begins running If you did not specify a
workspace in the dialog and the projects are not present, then you should switch
workspaces by selecting Switch Workspace>Other… from the File menu You should
then enter the workspace location provided in step 3
Trang 25 uCOSIII_Lab_1 is the project that has been created for this lab As the screen shot on
the subsequent page indicates, this project consists of a number of files and folders The project’s C source and header files, including those that make up µC/OS-III, are
contained in the src folder You should now build the code that the project’s files
contain You can initiate the build process by right-clicking the project’s name and
selecting Build Project from the resulting menu.
Four projects
Trang 36 The project should build without any errors or warnings (The Console window at the
bottom of the IDE normally provides the status of each build operation.) If the build does complete successfully, then you should begin initiating a debug session by
selecting Debug As>Debug Configurations… from the menu that appears when you
right-click the project’s name e2studio should then present you with the Debug Configurations dialog.
7 The left-hand side of Debug Configurations contains a tree for organizing different collections of debug settings You should expand the tree’s Renesas GDB Hardware Debugging entry and then select uCOSIII_Lab_1, as shown in the screen shot on the next page of this document To start your session, you should click the Debug button
located at the bottom of the dialog
Trang 48 After you click Debug, e2studio will display the below Confirm Perspective Switch
dialog, informing you that “this kind of launch is configured to open the Renesas Debug
perspective.” You should simply click this dialog’s Yes button.
Trang 59 The buttons that can be used to control debugging in e2studio are shown below For
your debugging session, you should simply click the Resume button twice After the
second click, the circular array of LEDs on your YRDKRX63N board should begin lighting This behavior can be taken as an indication that the µC/OS-III-based application code is running successfully
Lab 2: Writing a Task
Objectives: In this lab, you will be taken through the process of writing a task for a µC/OS-III application You’ll begin your work with application code that manipulates the YRDKRX63N’s LEDs, much like what you saw in the first lab You’ll write a new task that outputs messages to the board’s graphical LCD, and you’ll add this task to the existing application In the process, you’ll gain experience with µC/OS-III’s task creation routine, OSTaskCreate() You’ll also have an opportunity to work with the kernel’s time-management services
Procedure:
1 uCOSIII_Lab_2 is the project provided for this lab You should now expand the listing for
this project in the Project Explorer Subsequently, you should expand the src folder and
then the App folder.
2 You will be manipulating two files in this lab, app.c and app_cfg.h, both of which reside
in the App folder You should open app_cfg.h now, by simply double-clicking its name in
the Project Explorer.
3 Two lines of code that you should now add to app_cfg.h are shown below The first line
is a definition for a task priority app_cfg.h, already defines one such priority,
APP_TASK_START_PRIO, and you can place the new definition directly below this one The second line of code defines a stack size, and this line can likewise be placed
below app_cfg.h’s existing stack-size definition,APP_TASK_START_STK_SIZE
Resume
Trang 64 After adding the priority and stack-size definitions to app_cfg.h, you should save this file
by selecting Save from the File menu You should then open app.c.
5 The first two lines of code for you to add to app.c are shown below This code declares
a task control block (TCB) and a stack, both of which will be needed by your new task
Within app.c, you should place the two new lines below the comment block reading
LOCAL VARIABLES
static CPU_STK AppTaskLCDStk[APP_TASK_LCD_STK_SIZE];
6 A prototype for your new task is provided below You should now add this prototype to
app.c, placing it beneath theFUNCTION PROTOTYPESheader
static void AppTaskLCD (void *p_arg);
7 The below function will serve as your task You should append this function to the end
of app.c now The code that the function contains writes messages to the YRDKRX62N
board’s LCD by calling BSP_GraphLCD_StringPos() To control the amount of time that each message is displayed, the code invokes the µC/OS-III delay function OSTimeDlyHMSM(), which is, essentially, a request for the kernel to run another task for a specified period of time
static void AppTaskLCD (void *p_arg)
{
OS_ERR err;
while (DEF_TRUE) {
BSP_GraphLCD_Clear();
BSP_GraphLCD_StringPos(3, 5, "DevCon");
BSP_GraphLCD_StringPos(4, 6, "2012");
OSTimeDlyHMSM(0, 0, 5, 0,
OS_OPT_TIME_HMSM_STRICT, &err);
BSP_GraphLCD_Clear();
BSP_GraphLCD_StringPos(3, 4, "Micrium");
BSP_GraphLCD_StringPos(4, 3, "uC/OS-III");
OSTimeDlyHMSM(0, 0, 5, 0,
OS_OPT_TIME_HMSM_STRICT, &err);
Trang 78 A C function does not, of course, become a task just by being declared Application code must actually notify µC/OS-III that the function is to be treated as a task OSTaskCreate() can be used for this purpose You should now add the below OSTaskCreate() call to app.c The best location for the call is in
AppTaskStart(), just above the infinite loop
OSTaskCreate((OS_TCB *)&AppTaskLCDTCB,
(CPU_CHAR *)"LCD Task", (OS_TASK_PTR ) AppTaskLCD, (void *) 0,
(OS_PRIO ) APP_TASK_LCD_PRIO, (CPU_STK *)&AppTaskLCDStk[0], (CPU_STK_SIZE) APP_TASK_LCD_STK_SIZE / 10u, (CPU_STK_SIZE) APP_TASK_LCD_STK_SIZE,
(OS_MSG_QTY ) 0u, (OS_TICK ) 0u, (void *) 0, (OS_OPT )(OS_OPT_TASK_STK_CHK |
OS_OPT_TASK_STK_CLR), (OS_ERR *)&err);
9. Once you’ve added your OSTaskCreate() call to app.c, you should save this file.
You should then attempt to build and run your code, following the procedure given in Lab 1 When you’ve completed this procedure, you can look for your board’s LEDs to begin lighting Additionally, you can check for messages on the board’s LCD “DevCon” and “2012” should appear on the display first and should be followed by “Micrium” and
“uC/OS-III” Each of pair of messages should be visible for five seconds before the pattern begins repeating itself
Lab 3: Interrupt Handlers
Objective: To complete this exercise, you’ll need to add both a task and an interrupt service routine (ISR) to an existing application The ISR will read values from the 12-bit analog-to-digital converter that the microcontroller on the YRDKRX63N incorporates These values will ultimately be output to the board’s LCD by the task As you implement this functionality, you’ll gain insight into how ISRs can be used in multitask applications
Trang 81 The project provided for this lab is uCOSIII_Lab_3 You should now open this project’s
copy of app_cfg.h.
2 In this lab, as in the previous one, you will be writing a task You should now add
definitions for your task’s priority and stack size to app_cfg.h You can use the
definitions shown below
3 Once you’ve completed the above additions, you should save app_cfg.h You should then open app.c and add the below variable declarations to this file The declarations
are for a TCB, a stack, and a 16-bit variable that your task will use to store analog-to-digital values You can place the declarations below the comment block readingLOCAL VARIABLES
static CPU_INT16U AppADCVal;
4. You should prototype your task as shown below You can place your prototype under theFUNCTION PROTOTYPEScomment block in app.c.
static void AppTaskLCD (void *p_arg);
5 The code that will make up your task is provided on the following page Like the task that you wrote in Lab 2, this code uses calls to BSP_GraphLCD_StringPos() to output messages to the YRDKRX63N board’s LCD The variable, AppADCVal, that the code repeatedly writes to the display via these calls, will, in the finished code, be updated by your ISR You will write this routine in subsequent steps For now, you
should add the below code to app.c, placing it at the end of the file.
Trang 9static void AppTaskLCD (void *p_arg)
{
CPU_CHAR adc_str[5];
OS_ERR err;
BSP_ADCInit();
BSP_GraphLCD_StringPos(3, 1, "ADC Value:");
while (DEF_TRUE) {
Str_FmtNbr_Int32U(AppADCVal, 4, 10, ' ', DEF_NO,
DEF_YES, adc_str);
BSP_GraphLCD_StringPos(4, 4, adc_str);
OSTimeDlyHMSM(0u, 0u, 0u, 50u,
OS_OPT_TIME_HMSM_STRICT, &err);
}
}
6. TheOSTaskCreate()call for your new task is provided below You should insert this
call into app.c’s declaration ofAppTaskStart(), just above the infinite loop
OSTaskCreate((OS_TCB *)&AppTaskLCDTCB,
(CPU_CHAR *)"LCD Task", (OS_TASK_PTR ) AppTaskLCD, (void *) 0,
(OS_PRIO ) APP_TASK_LCD_PRIO, (CPU_STK *)&AppTaskLCDStk[0], (CPU_STK_SIZE) APP_TASK_LCD_STK_SIZE / 10u, (CPU_STK_SIZE) APP_TASK_LCD_STK_SIZE,
(OS_MSG_QTY ) 0u, (OS_TICK ) 0u, (void *) 0, (OS_OPT )(OS_OPT_TASK_STK_CHK |
OS_OPT_TASK_STK_CLR), (OS_ERR *)&err);
Trang 107. The ISR that your finished code will use to process analog-to-digital converter interrupts
is shown below This function reads a new value from the converter and places that value intoAppADCVal You should add the ISR to app.c now You can append it to the
end of the file
void AppADCRead (void)
{
AppADCVal = S12AD.ADDR2;
}
8 Once you’ve written the ISR, you can save app.c You should then expand the BSP subfolder of src and open one of the files comprising this subfolder: bsp_adc_a.s, the
contents of which were written so as to be called by the code located at the
analog-to-digital converter’s interrupt vector You should insert the below code into bsp_adc_a.s,
just below the line of assembly language that executes the macro OS_ISR_ENTER
The new code will cause the function that you added to app.c in the previous step to be
invoked after every analog-to-digital converter interrupt
MOV.L #_AppADCRead, R5
JSR R5
9 You should save bsp_adc_a.s after making the above change You can then attempt to
build and run your code If you successfully completed each of the above steps, the code should cause your YRDKRX63N’s LEDs to light It should also result in an analog-to-digital-conversion value appearing on the board’s display You should be able to change this value by turning the potentiometer located at the bottom of the board
Lab 4: Task Synchronization
Objective: In this lab, you’ll again be writing an ISR and a task, both of which will behave somewhat similarly to their counterparts in the previous lab Your ISR for this lab, however, will not place analog-to-digital conversion values in a variable Instead, it will signal your task using
a semaphore The task will then read the values itself and display them As you write the task and the ISR, you’ll gain familiarity with µC/OS-III’s semaphore API
Trang 111 You’ll use project uCOSIII_Lab_4 for this lab You should now open this project’s copy of
app_cfg.h
2 The below definitions are for your task’s priority and stack size You should add these
definitions to app_cfg.h now.
3 After saving app_cfg.h, you should add the below code to app.c This code comprises
stack and TCB declarations similar to those that you’ve seen before, along with a new declaration for a semaphore The semaphore will be used by your task and ISR for
signaling You can place the semaphore, TCB, and stack declarations below app.c’s
LOCAL VARIABLES comment block
static CPU_STK AppTaskLCDStk[APP_TASK_LCD_STK_SIZE];
4. The below prototype is for your task You should add this prototype to app.c now You
can place the prototype below theFUNCTION PROTOTYPEScomment block
static void AppTaskLCD (void *p_arg);
5. Your task’s code is provided on the next page This code uses a call to µC/OS-III’s OSSemPend()function to wait for a signal from the analog-to-digital converter’s ISR (You will be writing the ISR soon.) After receiving the signal, the code reads a new value from the converter and displays that value, using BSP_GraphLCD_StringPos()
You should append the code to the end of app.c now.
Trang 12static void AppTaskLCD (void *p_arg)
{
CPU_INT16U adc_val;
CPU_CHAR adc_str[5];
OS_ERR err;
BSP_ADCInit();
BSP_GraphLCD_StringPos(3, 1, "ADC Value:");
while (DEF_TRUE) {
OSSemPend(&AppSemADC, 0, OS_OPT_PEND_BLOCKING, 0,
&err);
adc_val = S12AD.ADDR2;
Str_FmtNbr_Int32U(adc_val, 4, 10, ' ', DEF_NO,
DEF_YES, adc_str);
BSP_GraphLCD_StringPos(4, 4, adc_str);
}
}
6 Like previous tasks you’ve written, the one for this lab necessitates an OSTaskCreate() call Additionally, the semaphore that the task uses requires an OSSemCreate() call Both of these function calls are provided below You should
now add the calls to app.c, inserting them into AppTaskStart(), just above the infinite loop
OSSemCreate(&AppSemADC, "ADC Sem", 0, &err);
OSTaskCreate((OS_TCB *)&AppTaskLCDTCB,
(CPU_CHAR *)"LCD Task", (OS_TASK_PTR ) AppTaskLCD, (void *) 0,
(OS_PRIO ) APP_TASK_LCD_PRIO, (CPU_STK *)&AppTaskLCDStk[0], (CPU_STK_SIZE) APP_TASK_LCD_STK_SIZE / 10u, (CPU_STK_SIZE) APP_TASK_LCD_STK_SIZE,
(OS_MSG_QTY ) 0u, (OS_TICK ) 0u, (void *) 0, (OS_OPT )(OS_OPT_TASK_STK_CHK |
OS_OPT_TASK_STK_CLR),