LabVIEW Embedded for ARM Porting Guide - Chapter 4: Porting the RTX Real-Time Kernel

Publish Date: Apr 11, 2008 | 14 Ratings | 1.29 out of 5 |  PDF

Overview

The 32-bit RISC ARM processor architecture developed by ARM Limited is widely used across many embedded designs due to its low price, low power consumption, and wide variety of peripherals for many of the major silicon vendors. Today, the ARM family accounts for more than 75 percent of all 32-bit RISC CPUs. You can use the NI LabVIEW Embedded Module for ARM Microcontrollers for programming ARM microcontrollers with the RTX embedded operating system.

This document offers a general outline for targeting LabVIEW code to any custom ARM target. It is the fourth document in a five-part series that demonstrates the steps you need to take to port LabVIEW code to the Phytec LPC3180 ARM9 microcontroller. For additional information, read these chapters:

Chapter 1: Introduction

Chapter 2: Integration of LabVIEW and Keil Toolchains

Chapter 3: Implementing Elemental I/O

Chapter 5: Integrating the Real-Time Agent

Table of Contents

  1. Porting the RTX Real-Time Kernel
  2. Objective
  3. Hardware Resources Required
  4. Creating a New Project
  5. Setting Options for Target
  6. Add the Files Required by RTX to Your Project
  7. Modify the RTX_Config.c and Startup.s File for Your Appllication
  8. Create the Application Source Files
  9. Load the Secondary Bootloader
  10. Build the Target
  11. Download the Program to Flash Memory
  12. Start the Debugger and Verify That the RTX Program Behaves Correctly
  13. Modify the Startup.s for RTX
  14. Modify RTX_Config.c

1. Porting the RTX Real-Time Kernel

The RTX Real-Time Kernel is an easy-to-use real-time executive for microcontrollers that provides a real-time operating system (RTOS) for ARM7, ARM9, and Cortex-M3 devices. The RTOS handles any common tasks such as scheduling, maintenance, and timing issues so that they are invisible to the end user. The RTX Real-Time Kernel is a powerful RTOS that works with a wide variety of ARM derivatives. To port LabVIEW to a new ARM derivative, the target must be capable of running RTX. For a list of RTX-compatible devices, see Devices Supported by the RL-ARM Real-Time Library. To learn more about RTX, see the RL-ARM User’s Guide.

Back to Top

2. Objective

The objective of this chapter is to demonstrate how to port the RTX Real-Time Kernel to the LPC3180. Once the proper configuration files are generated, a simple program using various OS task functions that can blink the onboard LEDs is programmed to the target and used to verify proper operation of the OS.

Back to Top

3. Hardware Resources Required

When selecting an ARM target, keep in mind the hardware requirements for RTX. To run the RTX Real-Time Kernel, the following hardware resources are required and, consequently, reserved by the RTOS from an ARM device:

  • Peripheral Timer for generating periodic ticks. It is better to use a peripheral timer with an auto-reload function. RTX also supports timers with manual timer (or counter) reload. However, this can generate jitter and inaccuracy in the long run. The RTX Real-Time Kernel needs a count-up timer. If the timer used is a count-down timer, you need to convert the timer value.
  • Timer Interrupts to interrupt the execution of a task and to start the system task scheduler os_clock_demon().
  • Forced Interrupts to force a timer interrupt when isr_ functions are used. If an isr_ function is called, the kernel forces the timer interrupt immediately after the interrupt ends. The forced timer interrupt activates the task scheduler. If a task that has a higher priority than the currently running task becomes ready, a task switch must occur.

Back to Top

4. Creating a New Project

  • Start the Keil μVision environment.
  • Open the Project menu and select New μVision Project….
  • In the Create New Project window, select a new directory for your project, enter a name for your project, and click Save.

  • Select the NXP LPC3180 in the CPU vendor database list and click OK.

 

  • When the prompt to Copy Philips LPC3000 Startup Code to the Project Folder and Add File to Project? Appears, click Yes.

  • To configure the target, click on the  icon in the build toolbar or right-click on the target, Target 1, in the Project Workspace window and select Manage Components.

  • In the Project Components tab, double-click on Target 1. Change the name of the target to LPC3180 Ext Memory. The Keil μVision environment allows multiple targets within a single project. Therefore, it is important to label your targets with descriptive names. For example, if you were to create a target within this project that is set up to run only in internal memory, a name like LPC3180 Int Memory helps you distinguish the proper target for execution.

  • Double-click on Source Group 1 in the Groups window and change the name of the group to Startup Code.

  • Add more groups by selecting the New(Insert) icon  in the Groups window. Name the new groups System Calls and Source Code.

  • Click OK. This brings you back to the Project Workspace window.

Back to Top

5. Setting Options for Target

  • Be aware that the following settings are specific to the LPC3180. For other targets, consult your hardware manual to determine the appropriate settings.
  • Configure the project to use the RTX Real-Time Kernel by selecting the Options for Target icon  on the build toolbar or right-clicking on the LPC3180 Ext Memory target in the Project Workspace window and select Options for the Target “LPC3180 Ext Memory.”
  • In the Target tab, be sure that Xtal is set to 13.0 MHz, and Read/Only Memory Areas off-chip ROM1 and Read/Write Memory Areas off-chip RAM1 are checked. Set the Memory Areas Start and Size as shown below.
  • Set the Code Generation for Thumb-Mode, make sure Cross-Module Optimization is checked, and make sure Use MicroLIB is NOT checked.

  • Make sure to select RTX Kernel for the Operating system.

Configure the Output Options

  • In the Output tab, make sure the Create Executable and Browse Information options are checked. Set the Name of Executable to Blinky.

  • Click on the Select Folder for Objects button and browse to your project directory.
  • Click on the Create a new folder  button and name the folder Ext_SDRAM. Double-click the Ext_SDRAM folder to open it and click OK.

Configure the Listing Options

With the options on the Listing tab, you can configure which files are generated upon a successful compile and which information they include.

  • In the Listing tab, leave the default settings.
  • Click on the Select Folder for Listings button.
  • Browse to the Ext_SDRAM folder you created in the previous step.
  • Click OK.

Configure the User, C/C++, and Linker Options

  • In the User, C/C++, and Linker tabs, leave the default settings.

Configure the Asm Options

  • Depending on the memory area you wish to run your programs from (internal or external RAM, internal or external flash memory, and so on), you need to enter certain SET symbols under Options»Asm»Define. The various SET symbols are defined in the documentation at the top of the startup file.
  • Change to the Asm tab. In the Conditional assembly control SymbolsDefine”field, type RAM_INTVEC, REMAP. When set, the startup code copies exception vectors from on-chip flash memory to on-chip RAM, and from on-chip RAM to address 0.

Configure the Debug Options

  • In the Debug tab, select the use ULINK ARM Debugger option.

  • Configure the ARM Target Driver Setup by clicking the Settingsbutton. The ARM Target Driver Setup settings should be as follows with Max JTAG Clock set to RTCK and all Debug options checked (Cache Options, Download Options, and Misc Options):

  • Click OK to return to the Options for Target window.
  • Be sure that Load Application at Startup, under the ULINK ARM Debugger setting, is NOT checked. Loading the application code and the go till main function are executed by the Ext_RAM.inifile (see below).
  • Copy the Ext_RAM.ini file from the \Keil\ARM\Boards\Phytec\LPC3180\Blinky directory to your project directory.
  • Add the correct Initialization File by clicking the browse button and select the Ext_RAM.ini file youjust copied into your project directory.
  • The Debug tab should appear as follows:

Configure the Utilities Option

  • In the Utilities tab, configure the Target Driver for Flash Programming by first selecting the ULINK ARM Debugger and then clicking the Settings button.
  • Select the Add button. In the new window, select the LPC3180 NAND Flash SP and click Add to return to the previous window.
  • Configure the remaining Flash Download Setup options as follows and click OK.

  • Copy the Clock.ini file from the \Keil\ARM\Boards\Phytec\LPC3180\Blinky directory to your project directory.
  • Back on the Utilities tab, add the correct initialization file by clicking the Browse button and select the Clock.ini file that you copied to your project directory in the previous step.
  • The Utilities tab should appear as follows:

Back to Top

6. Add the Files Required by RTX to Your Project

  • Copy the appropriate RTX_Config.c configuration file for your target device from the \Keil\ARM\Startup\ directory to your project directory. For the LPC3180, a complete RTX_Config.c file has been provided in the LPC3180.zip file. RTX_Config.c contains all of the configurations necessary to customize the RTX kernel to a specific target. If the file does not exist for your target, see the section on creating a custom RTX_Config.c file.
  • Copy the retarget.c file found in the \Keil\ARM\Boards\Phytec\LPC3180\Blinky directory to your project directory. The main purpose of this file is to avoid the use of semihosting software interrupts. Semihosting is a mechanism for ARM targets to communicate input/output requests from application code to a host computer running a debugger, and you must disable it when using the RTX Real-Time Kernel.
  • Right-click on System Calls in the Project Workspace and select Add Files to Group “System Calls.” Locate the RTX_Config.c file in your project directory and click Add. Next, locate the retarget.c file in your project directory and click Add. Once you have added these two files, click on Close to return to the Project Workspace.

Back to Top

7. Modify the RTX_Config.c and Startup.s File for Your Appllication

  • Now you must configure the RTX Real-Time Kernel for your application needs by making the required changes in the RTX_Config.c and Startup.s file. See the sections below for more details.

Back to Top

8. Create the Application Source Files

  • Copy the provided Blinky.c source file in the Chapter 4 folder from the LPC3180.zip file to the project directory. In the Project Workspace, right-click on the Source Group folder and select Add Files to Group “Source Files.” Select the Blinky.c file in your project directory and click OK. For more information on the use of RTX-specific functions in this example program, see the RL-ARM User’s Guide.

Back to Top

9. Load the Secondary Bootloader

To help you better understand the need for a secondary boot loader on the LPC3180, a concise explanation of the boot process is presented below. After a reset, the LPC3180 executes the on-chip bootstrap software located in the on-chip boot ROM. This software is responsible for reading code out of NAND flash memory, loading it in internal SRAM, and executing it. Because the SRAM is limited to 64 kB on the LPC3180, it is not possible to execute code out of internal RAM that exceeds 64 kB in size. Furthermore, despite the presence of 64 kB of IRAM in the LPC3180, the bootstrap software copies only 15.5 kB from the NAND flash memory into IRAM for execution.

To get around this limitation, you must execute code from external SDRAM, which is much larger in size than internal SRAM.

To execute code out of SDRAM, you must follow three basic steps:

  1. Initialize the SDRAM interface
  2. Copy the code from NAND flash memory into SDRAM
  3. Transfer the execution to SDRAM

The LPC3180 bootstrap software is not capable of initializing SDRAM, copying code from NAND flash memory to SDRAM, and executing it. For this reason, you need a secondary boot loader on the LPC3180 target. The secondary boot loader must be located in block 0 of the NAND flash memory from which the LPC3180 bootstrap software loads into IRAM and executes. This secondary boot loader then initializes the SDRAM, copies application code from NAND flash memory into SDRAM, and transfers execution to SDRAM.

  • Open a second instance of the μVision 3 environment. Open the Bootloader project by selecting the menu item Project»Open Project and browse to the \Keil\ARM\Boards\Phytec\LPC3180\Bootloader directory and select Bootloader.Uv2.

  • Download the code into NAND flash memory by selecting either the Download to Flash Memory icon  on the build toolbar or Flash»Download in the main menu bar.
  • You can view the individual steps of the flash download procedure at the bottom of the μVision 3 Output Window - Build tab.
  • Wait until the programming is complete. This is indicated by the “Verify OK” message. The download utility performs a reset and the code executes without further user interaction.

Back to Top

10. Build the Target

  • Build the target by selecting either the Build Target icon  on the build toolbar or the Project»Build target on the main menu bar.
  • If any source file of the project contains any errors, they are shown in the Output Window - Build tab. Use the editor to correct the error(s) in the source code, save the file, and repeat the build.
  • If there are no errors, the code is ready to be downloaded to flash memory.

Back to Top

11. Download the Program to Flash Memory

  • Download the code into flash memory by selecting either the Download to Flash Memory icon  on the build toolbar or Flash»Download in the main menu bar.
  • You can view the individual steps of the flash download procedure at the bottom of the μVision 3 Output Window - Build tab.
  • Wait until the programming is complete. This is indicated by the“Verify OK” message.

Back to Top

12. Start the Debugger and Verify That the RTX Program Behaves Correctly

  • Click on the debugger icon  on the μVision 3 toolbar.
  • Click on the Run icon , and the program runs.
  • If you have configured RTX successfully, the execution of the program flashes the LEDs (D400, D401, D402, and D403) on the Carrier Board.

Back to Top

13. Modify the Startup.s for RTX

The Startup.s file contains functions that are executed directly after a CPU reset. It provides various functions such as stack, memory, and clock initialization, as well as functions for mapping exception vectors.

Modify the Device Startup File to Enable the SWI_Handler Function

  • Comment out the following line from the startup file:
    • SWI_Handler    B    SWI_Handler

  • Add the following line to the startup file:
    • IMPORT    SWI_Handler

This change prevents the code from sitting in a loop when an SWI interrupt occurs. Importing the appropriate SWI_Handler allows the right function to run when an SWI interrupt occurs. This is required when using the RTX Real-Time Kernel.

Modify the Device Startup File to Export the IRQ Interrupt Handler

  • Comment out the following line from the startup file:
    • IRQ_Handler     B       IRQ_Handler

  • Add the following line to the startup file:
    • IMPORT     IRQ_Handler

The LPC3180 does not feature a vectored interrupt controller but a master interrupt controller and two secondary interrupt controllers. You can route all interrupts on the LPC3180 to the general IRQ interrupt handler; therefore, the IRQ handler must be provided to determine in software which interrupt to handle. This function is implemented in RTX_Config.c. A default interrupt handler is generated by the default startup file; therefore, the preceding changes enable an external IRQ interrupt handler.

Modify the Device Startup File to Configure Proper Dynamic Size Calculations via the Scatter Loading Function

  • The following lines determine the size of the code loaded into SDRAM for execution:
    • IMPORT  ||Image$$ER_IROM1$$RO$$Length||

    • IMPORT  ||Image$$RW_IRAM1$$RW$$Length||

    • DCD     ||Image$$ER_IROM1$$RO$$Length||+\

    •         ||Image$$RW_IRAM1$$RW$$Length||

  • Because the target will load to external RAM and ROM, modify the code above to the following:
    • IMPORT  ||Image$$ER_ROM1$$RO$$Length||

    • IMPORT  ||Image$$RW_RAM1$$RW$$Length||

    • DCD     ||Image$$ER_ROM1$$RO$$Length||+\

    •         ||Image$$RW_RAM1$$RW$$Length|| 

The scatter loading functions in the Keil tools provide the size of the compiled application binary. When loading memory from flash, the secondary boot loader uses this size information to determine how much code to load into SDRAM for execution.

Modify the Device Startup File to Increase the Heap Size

  • The following line determines the size of the heap:
    • Heap_Size       EQU     0x00000000

  • Change the value of Heap_Size to 0x00002000:
    • Heap_Size       EQU     0x00002000

Back to Top

14. Modify RTX_Config.c

To use RTX in an embedded application, you must configure an RTX_Config.c file for your target. The RTX_Config.c file provides all of the macros and definitions required for configuring and customizing RTX. RTX_Config.c is configured differently for each different ARM device. If an RTX_Config.c file has already been created for your target, you can find it in the \Keil\ARM\Startup directory. If this file has not been created, you must create your own.

Copy an Existing RTX_Config.c File to Your Project Directory

  • Locate an existing RTX_Config.c file in the \Keil\ARM\Startup\ directory for a target that is as similar to your target as possible. In the case of the LPC3180, use the RTX_Config.c file for the Philips LPC21xx.

Add the Header File for Your Target

  • Modify the following line at the beginning of the file to include the appropriate header file:
    • #include <LPC21xx.H>

  • To the following:
    • #include <LPC318x.H>

Customize the RTX Configuration Settings

Modify the following definitions to customize the RTX Real-Time Kernel features so that they are appropriate for your target. For more detailed information about each setting, see the RL-ARM User’s Guide.

  • #define OS_TASKCNT     10
    • This value is overwritten by LabVIEW. For testing purposes, to ensure enough tasks are available, set this value to 10.
  • #define OS_PRIVCNT     0
    • This value is overwritten by LabVIEW. The default value of 0 is fine.
  • #define OS_STKSIZE     100
    • This value is dependent on the amount of memory available on your target. Set this value as low as possible. If stack overflows occur, increase this value.
  • #define OS_STKCHECK    1
    • Enable stack overflow checking.
  • #define OS_TIMERCNT    0
    • Disable user timers.
  • #define OS_TIMER       0
    • Select the timer that you are using as the system timer tick. In this case, timer 0 is defined as the LPC3180 HSTimer.
  • #define OS_CLOCK       13000000
    • This is the frequency of the system timer clock.
  • #define OS_TICK        1000
    • Set this value to 1000 so that a timer tick interrupt fires every millisecond.
  • #define OS_ROBIN       1
    • Enable round-robin task switching.
  • #define OS_ROBINTOUT   5
    • Defines how long a task executes before a task switch.

Customize the RTX Configuration Macros

Modify the following macros to configure the system timer tick so that they are appropriate for your target. For more information about each macro, see the RL-ARM User’s Guide. For the LPC3180, the HSTimer is used as the system timer; thus, it is defined as Timer 0.

  • OS_TIM_
    • This macro defines the mask for the interrupt bit used by the interrupt controller. For the LPC3180, bit 5 is used as the flag for the HSTimer.
  • OS_TRV
    • This macro specifies the timer reload value for the peripheral timer. The peripheral timer counts up to a reload value, overflows to 0, and generates a tick interrupt. You should calculate the reload value to generate the desired interval length (for example 10 ms).
    • Define this macro as: ((((1ULL*OS_CLOCK*OS_TICK))/1000000ULL)-1ULL)
  • OS_TVAL
    • This macro is used to read the current timer value for a count-up timer. The RTX Real-Time Kernel uses it to check whether a timer interrupt is a periodic timer interrupt or a software-forced interrupt. Define this macro as the address of the register that holds the timer count value.
  • OS_TOVF
    • This macro specifies a timer overflow flag. The RTX Real-Time Kernel uses it with the OS_TVAL macro to differentiate between the periodic timer interrupts and forced timer interrupts. If the peripheral timer you use does not feature an overflow interrupt, set this bit to the interrupt bit for the timer match interrupt.
  • OS_TREL()
    • This macro specifies a code sequence to reload the peripheral timer count value on an overflow or match interrupt. If the peripheral timer features auto-reload functionality, leave this macro empty.
  • OS_TFIRQ()
    • This macro specifies a code sequence to force a timer interrupt. This must be a software-triggered interrupt if the peripheral timer does not allow manual setting of an overflow flag. If manual setting is possible, this macro should set a peripheral timer overflow flag, which causes a timer interrupt.
  • OS_TIACK()
    • This macro specifies a code sequence to acknowledge an interrupt from the timer interrupt function to release the timer interrupt logic.
  • OS_TINIT()
    • This macro is used to initialize the peripheral timer/counter, set up a timer mode, and set a timer reload. Timer interrupts are also activated here by enabling a peripheral timer interrupt. This code is executed from the os_sys_init() function.
  • OS_IACK()
    • This macro specifies a code sequence to acknowledge a forced interrupt.
  • OS_LOCK()
    • This macro specifies a code sequence to disable timer tick interrupts. It is used to avoid interrupting the system task scheduler. It should disable both the periodic timer interrupts and forced interrupts. This code is executed from the tsk_lock() function.
  • OS_UNLOCK()
    • This macro specifies a code sequence to enable the timer tick interrupts. The code sequence specified here should enable the periodic timer interrupts and forced interrupts. This code is executed from the tsk_unlock() function.

The code sequence below has been defined for the LPC3180. Replace the code after the RTX User configuration part of the RTX_Config.c file with the following:

Define the Interrupt Handler

If your target does not feature a vectored interrupt controller, you need to define an IRQ interrupt handler to determine in software which interrupt to handle. In the RTX_Config.c file, the function prototype is defined as:

__asm void IRQ_Handler(void) {}

Specify in this function a sequence of assembly code to handle IRQ interrupts. For the purposes of this demonstration, only timer tick interrupts are handled.

The following code sequence for the interrupt handler has been defined for the LPC3180. Add this code to the Global Functions section of RTX_Config.c:

__asm void IRQ_Handler(void) {   

       PRESERVE8

       ARM

       LDR     PC,=__cpp(os_clock_interrupt)  ; OS Clock IRQ Function

}

Back to Top

Bookmark & Share


Ratings

Rate this document

Answered Your Question?
Yes No

Submit