TI MSP430 (MSP430F449) RTOS Port
for the CrossWorks Development Tools
[RTOS Ports]
The port was developed on an ES449 development/prototyping board
from SoftBaugh (instructions are provided should you wish to use an alternative development board),
using the CrossWorks
MSP430 compiler and a SoftBaugh FETP parallel
port JTAG interface
The ES449 is a neat little MSP430F449 based prototyping board. It allows easy access to the MSP430 peripherals and includes
an LCD display - great for debugging! The FETP / CrossWorks interface is seamless and fast making this a very easy to use
development platform.
FreeRTOS V5.1.0 upgraded this port and demo to permit tasks to use the MSP430 low power modes 1 to 3.
IMPORTANT! Notes on using the CrossWorks MSP430 RTOS port
Please read all the following points before using this RTOS port.
- Source Code Organization
- The Demo Application
- Configuration and Usage Details
- Selecting the Port to Use
See also the FAQ My application does not run, what could be wrong?
Source Code Organization
The FreeRTOS download contains the source code for all the FreeRTOS ports so contains many more files than required to run just this demo.
See the Source Code Organization section for a description of the
downloaded files and information on creating a new project.
The CrossWorks project used to build the MSP430 FreeRTOS demo is located in the Demo/msp430_CrossWorks directory.
The Demo Application
Functionality
The ES449 prototyping board includes a built in LCD display and a single built in user
LED. To make use of this hardware, the standard demo tasks that would normally flash an LED, instead flash
'*' characters on the LCD. The left most '*' represents LED 0, the
next LED 1, etc.
The single on board LED is used by one of the ComTest tasks. It is toggled every time a character is received on the
serial port.
The demo application creates 10 tasks - 9 of the standard demo application tasks
and the idle task. When executing
correctly the demo application will behave as follows:
Demo application hardware setup
The demo application includes tasks that send and receive characters over the serial port. The characters are transmitted by
one task and received by another - if any character is missed or received out of sequence an error condition is flagged.
Normally a loopback connector is required for this mechanism to work (so each character transmitted by the UART is also received
by the UART). In this case the 'loopback' mode of the MSP430 UART is used and no external connector is required.
The demo application uses the LCD in place of LEDs so no other hardware setup is required.
Building
To build the demo application:
- Open the project file FreeRTOS/Demo/MSP430_CrossWorks/RTOSDemo.hzp from within the CrossStudio IDE.
- Select the required build (Debug or Release).
Selecting the required build
- Select "Build Solution" from the CrossStudio project menu or simply press F7.
Downloading and executing
To download the application to the target hardware:
- Connect the FETP JTAG interface between the target and host. The target will be powered via the FETP JTAG interface and no other
power source should be connected.
- Select "Connect MSP430 Flash Emulation Tool" from the CrossStudio Target menu.
- Select "Start Debugging" from the CrossStudio Debug menu. The MSP430 Flash will be automatically programmed
with the demo application.
Once the application has been programmed into flash it can executed within the CrossStudio debugger. Alternatively, stop the
debugger (to power down the target), remove the FETP JTAG interface, then supply the target with an external power
source.
Serial port driver
As provided the serial port drivers are configured for loopback mode. This enables the demo application to execute but
switch loopback mode off for any other use.
It should also be noted that the serial drivers are written to test some of the real time kernel features - and they are not
intended to represent an optimised solution.
RTOS port specific configuration
Configuration items specific to this port are contained in Demo/MSP430_CrossWorks/FreeRTOSConfig.h. The constants defined in
this file can be edited to suit your application. In particular - the definition configTICK_RATE_HZ is used to set the frequency
of the RTOS tick. The supplied value of 1000Hz is useful for testing the RTOS kernel functionality but is faster than most applications
require. Lowering this value will improve efficiency.
Each port #defines 'BaseType_t' to equal the most efficient data type for that processor. This port defines
BaseType_t to be of type short.
Note that vPortEndScheduler() has not been implemented.
To use a part other than an MSP430F449
The core real time kernel components should be
portable across all MSP430F4xx devices - but the peripheral setup and memory requirements will require consideration.
Items to consider:
- prvSetupTimerInterrupt() in Source/portable/Rowley/MSP430F449/port.c configures the microcontroller timer to generate
the RTOS tick.
- Port, memory access and system clock configuration is performed by prvSetupHardware() within Demo/MSP430_CrossWorks/main.c.
- The serial port drivers.
- Register location definitions are provided by the file msp430x44x.h which is included at the top of
Demo/MSP430_CrossWorks/FreeRTOSConfig.h.
- RAM size - see Memory Allocation below.
Switching between the pre-emptive and co-operative RTOS kernels
Set the definition configUSE_PREEMPTION within Demo/MSP430_CrossWorks/FreeRTOSConfig.h to 1 to use pre-emption or 0 to use
co-operative.
Compiler options
As with all the ports, it is essential that the correct compiler options are used. The best way to ensure this is to base your
application on the provided demo application project.
Memory allocation
Source/Portable/MemMang/heap_1.c is included in the MSP430 demo project to provide the memory allocation required
by the real time kernel.
Please refer to the Memory Management section of the API documentation for
full information.
Interrupt Service Routines
Versions of FreeRTOS prior to V5.1.0 included two separate sets of port layer files for the MSP430:
- The officially supported version that uses the extensions provided by the Rowley compiler to implement interrupt service routines completely in C.
- A contributed port that required interrupt service routines to have assembly function wrappers.
FreeRTOS V5.1.0 only includes the officially supported version but introduces a pre-processor macro and a new header file that allows the users to define
which method of writing interrupt service routines will be used. The following sections describe the steps required to use both methods.
The UART driver within the supplied demo application also demonstrates both methods.
Method 1 only requires C code so is simpler to implement than method 2. It only saves and restores the task context when a context switch is actually
required, so can also be more efficient. However - a context switch being performed within the interrupt will result in some processor registers being
saved twice (once on interrupt entry, and then again for the context switch). This means the stack allocated to each task will need to be larger when
using method 1 compared to that required when using method 2.
Writing ISRs - Method 1
To use method 1:
- Set the pre-processor macro configINTERRUPT_EXAMPLE_METHOD to 1. The supplied demo application defines configINTERRUPT_EXAMPLE_METHOD within FreeRTOSConfig.h.
- Use the __interrupt[ ] function qualifier to implement interrupt service routines within C files.
- If using low power modes - ensure __bic_SR_register_on_exit(SCG1 + SCG0 + OSCOFF + CPUOFF) is called prior to exiting the interrupt service routine.
- Use the standard taskYIELD() macro should a context switch be required from within the interrupt routine.
Below is an example UART Rx interrupt written using method 1.
void vRxISR( void ) __interrupt[ UART1RX_VECTOR ]
{
signed char cChar;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Get the character from the UART and post it on the queue of Rxed
characters. */
cChar = U1RXBUF;
xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken )
{
/*If the post causes a task to wake force a context switch
as the woken task may have a higher priority than the task we have
interrupted. */
taskYIELD();
}
/* Make sure any low power mode bits are clear before leaving the ISR. */
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
}
Writing an ISR using method 1
Writing ISRs - Method 2
To use method 2:
- Set the pre-processor macro configINTERRUPT_EXAMPLE_METHOD to 2. The supplied demo application defines configINTERRUPT_EXAMPLE_METHOD within FreeRTOSConfig.h.
- Provide an assembly function that will be installed as the interrupt handler routine. The required format of this function is demonstrated below. Note the assembly file must include the portasm.h header file to gain access to the required portSAVE_CONTEXT and portRESTORE_CONTEXT assembly macros.
- Provide a standard C function that is called by the assembly file wrapper to perform the actual interrupt handling work - again see below for an example.
- Use the portYIELD_FROM_ISR() macro should a context switch be required from within the interrupt routine.
Below are examples of both the assembly file wrapper and C function portions of the interrupt implementation.
/* Ensure the required header files are included. */
#include "FreeRTOSConfig.h"
#include "portasm.h"
.CODE
/* Example wrapper for the Rx UART interrupt. */
_vUARTRx_Wrapper:
/* portSAVE_CONTEXT must be the first macro to be called. This is defined within
portasm.h. */
portSAVE_CONTEXT
/* Following portSAVE_CONTEXT the C portion of the handler can be called. */
call #_vRxISR
/* Finally portRESTORE_CONTEXT must be called at the end of the wrapper. This too
is defined within portasm.h. */
portRESTORE_CONTEXT
/******************************************************************/
/* The wrapper must be installed as the interrupt handler. */
.VECTORS
.KEEP
ORG UART1RX_VECTOR
DW _vUARTRx_Wrapper
END
The assembly file portion of the ISR
/* This is the standard C function called by the assembly file wrapper. */
void vRxISR( void )
{
signed char cChar;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Get the character from the UART and post it on the queue of Rxed
characters. */
cChar = U1RXBUF;
xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
/*If the post causes a task to wake force a context switch
as the woken task may have a higher priority than the task we have
interrupted. */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
The C function called from the assembly file wrapper
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.