There are currently three FreeRTOS ports for the MSP430. One that uses the open source MSPGCC (GCC) compiler, and two that use the Rowley Associates CrossWorks tool suite. This page relates only to the CrossWorks ports. Thanks goes to Milos Prokic for his efforts in producing this port.
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.
As downloaded this demo application does not demonstrate the use of co-routines. See the co-routine documentation page for information on how co-routine functionality can be quickly added to this demonstration.
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.
This project can be used to build both CrossWorks ports. See Selecting the Port to Use
for information on switching between the two CrossWorks ports, along with some details of their differences.
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:
The '*' in the fifth position on the LCD is under control of the 'Check' task. Every three seconds the 'Check' task examines all the tasks in the system to ensure they are executing without error. It then toggles '*' 5. If '*' 5 is toggling every three seconds then no errors have ever been detected. The toggle rate increasing to 500ms indicates that the 'Check' task has discovered at least one error.
The demo application uses the LCD in place of LEDs so no other hardware setup is required.

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.
Each port #defines 'portBASE_TYPE' to equal the most efficient data type for that processor. This port defines portBASE_TYPE to be of type short.
Note that vPortEndScheduler() has not been implemented.
Two MSP430 ports are provided for the CrossWorks development suite:
Often you will require an interrupt service routine to cause a context switch. For example a serial port character being received may wake a high priority task that was blocked waiting for the character. If the ISR interrupted a lower priority task then it should return immediately to the woken task. How this is achieved depends on the port being used:
The interrupt service routine can be defined using the standard CrossWorks syntax. If a context switch is required a
call to portYIELD() can be used. portYIELD() must only ever be called at the end of the ISR function. For
example, the UART1 receive interrupt might take the following format:
/* Define the ISR using standard CrossWorks syntax. */
void vRxISR( void ) __interrupt[ UART1RX_VECTOR ]
{
/* ...
/* Process the interrupt here. */
/* ...
/* Is a switch required? */
if( SwitchRequired )
{
/* Simply call taskYIELD() as this is the end
of the ISR and the interrupt has been processed. */
taskYIELD();
}
}
The interrupt service routine should be defined as a standard C function. The function name must start with "ISR".
A wrapper for the function (without the ISR prefix) must then be declared in the portext.asm
assembly file. Again a context switch should only occur at the end of the ISR, and this time be requested with a call
to the macro portEXIT_SWITCHING_ISR( bool ). The same example would therefore take the following format:
/* Declared as a standard C function prefixed with "ISR".
This can be in any C source file. */
void ISRvRxISR( void )
{
/* ...
/* Process the interrupt here. */
/* ...
/* We are at the end of the interrupt, call
portEXIT_SWITCHING_ISR() passing in a bool to indicate
whether or not a switch should occur. */
portEXIT_SWITCHING_ISR( bSwitchRequired );
}
The following lines should then be added to the file FreeRTOS/Source/Portable/Rowley/MSP430F449/portext.asm.
/* Define the wrapper. */
MSPINT vRxISR
/* Place the ISR in the appropriate vector. */
.VECTORS
.KEEP
ORG UART1RX_VECTOR
DW _Com1Rx
Port1 uses assembly macros to save and restore the task context, whereas Port2 uses functions. This means Port1 will be faster, but Port2 will use less code space.
Port1 is very simplistic, whereas Port2 is more elaborate. This elaboration results in the code space saving, but also requires a slightly more complex procedure to define interrupt service routines.
Port1 uses the compiler generated function prologue and epilogue code to save and restore the necessary registers within an interrupt service routine (other than the RTOS tick ISR). Should a context switch be required from within the ISR the entire processor context is saved. This can result in some registers being saved twice - once by the compiler generated code, and then again by the FreeRTOS code.
Port2 saves and restores all the processor registers within each interrupt service routine, whether or not a context switch actually occurs. This means no registers ever get saved twice, but imposes an overhead on the occasions that no context switch occurs.