Porting guide

nobody wrote on Monday, July 17, 2006:

I am currently using a Toshiba TCLS 900H processor with a custom built RTOS. Although this works well for the required application, I am about to move it to a M32/80 processor but the changes required are fairly complex as this was not written for portability.

It did occur to me that the freertos provides all the portability features I require but is available in neither configurations.  Is there a porting manual that would allow a fairly painless port to these processors.

I have over 30 years programming experience so the software is not a problem and I am even willing to provide the ports back to freertos.  I could do it by code inspection but it is ultimately quicker and less error prone if this documentation is available.

rtel wrote on Monday, July 17, 2006:

I suggest you start with the standard demo file flash.c.  This simply flashes LED.  To do this (rather random ordering in this list!):

i) Include FreeRTOS/demo/common/include in your project include path.
ii) Include the file FreeRTOS/demo/minimal/flash.c in your project.
iii) Find a main() file that calls vStartLEDFlashTasks(), use this as a basis.  Comment out all lines other than those required to setup the hardare, the call to vStartLEDFlashTasks() itself, and a call to vTaskStartScheduler().
iv) Include FreeRTOS/source/portable/memmang/heap_1.c in your project (as a minimum).
v) Include the three files from the FreeRTOS/source directory.  You won’t need to co-routine file.  These are the kernel files.
vi) Of coarse include the new port file in your build also.
vi) I suspect I’ve forgotten one or two things, but your linker warnings will let you know what.

The first thing to do after getting it to compile is step into the function xPortStartScheduler() and check that the context of the first task is restored correctly.  This may take one or two attempts, but you should see the initial values you placed in the stack you created for the task popped into the registers one by one, then finally the program counter loaded and a jump made to the start of the flash tasks. 

Once you have the first task executing the next thing to do is to step though a call to taskYIELD() to ensure the reverse is true, that the context is saved as you expect, then restored once more as the next task starts to execute.

Finally do the same for a preemptive tick.  Just ensure that on entry and exit from the tick (if preemptive is being used this is only) that the context is saved and restored correctly.

Hope this is more help that hindrance.

Regards.

rtel wrote on Monday, July 17, 2006:

{try again, posting problems}

> It did occur to me that the freertos provides all the portability
> features I require but is available in neither configurations.
> Is there a porting manual that would allow a fairly painless port to
> these processors.

There is a small amount of information on the FAQ. 

The FAQ is a bit out of date and this particular answer is lacking somewhat.  I have therefore elaborated at the end of this post.

Can you provide a link to a datasheet or short form for the processor you are wanting to use?

> I have over 30 years programming experience so the software is not a
> problem and I am even willing to provide the ports back to freertos.

That would in fact be a condition of using FreeRTOS.org.  There is no obligation to open source your application code (ie. the code that uses FreeRTOS.org through the published API), but this is an obligation to provide modifications to the kernel itself which includes new ports.  Providing the code could just be emailing it to me so I am aware of it and can use it to assist others should the need arise.

> I could do it by code inspection but it is ultimately quicker and
> less error prone if this documentation is available.

Below I have attempted to provide more information.  Some of this is a repeat of the FAQ.

1) First make sure you understand the directory structure.  See http://www.freertos.org/a00017.html.

2) Create a new directory to hold the new port files.  To follow the convention described in the link just given this should take the form:  FreeRTOS/Source/Portable/[compiler name]/[processor name].  If you are using a compiler that is already supported for a different processor then the only new directory that you should need to create is the bottom most with the name of the processor.

3) This new directory will require either two or three files, depending on the compiler used and to some extend the processor.

You will always require a port.c and a portmacro.h file.  If your compiler has a powerful inline assembler and the ability to produce ‘naked’ functions (i.e. with no compiler generated prologue or epilogue code) then these are the only two files you require.

Alternatively, if all the processor registers are automatically saved by the compiler generated prologue code then you may also get away with just these two files, but this is rare.

Generally GCC is an example of a compiler where only two files are required, although this depends on the features built into GCC for your particular port to some degree.  If you think only two files are required then copy the files port.c and portmacro.c from FreeRTOS/Source/portable/GCC/atmega323 into your newly created directory.

If these conditions are not met then you will also require a small assembler file.  One of the goals of FreeRTOS.org is to be as simple as possible and use as little assembler as possible, so this file should be straight forward.

IAR is an example of a compiler that requires a separate assembler file.  If you think a separate assembly file will be required then copy the files port.c, portmacro.h and portmacro.s79 from FreeRTOS/Source/portable/IAR/ATMega323 into your newly created directory.

4) The files you have copied into the new directory can be used as a skeleton for your new port.  The bodies of the functions/macros they contain can be deleted to leave stubs that can be filled in.  First take a look at portmacro.h.

4.1)  portmacro.h

Data Types
----------
At the top of this file are a load of type definitions.  Set these to be correct for your processor.  I would guess that they can be left as is down to portSHORT, which you should set to a 16 bit data type.  portBASE_TYPE should be set to the natural data type for your architecture, and portSTACK_TYPE to the (unsigned) size of a single item placed onto the stack.  In the AVR code this is char as the AVR is only 8 bits.

Definitions starting ‘config’ will be defined in the FreeRTOSConfig.h file, which is part of the application code not the port.  Needless to say unless you are using an 8bit processor with very inefficient 32bit handling, configUSE_16_BIT_TICKS will be set to 0 which causes portTickType to be a 32 data type.

Critical sections
-----------------
Next we come down to the critical section macros.  There are two ways of implementing critical sections (currently used).  If you can guarantee that you can push and pop items onto the stack without screwing up your compiler generated code then you can simply push the interrupt status bits onto the stack and clear interrupts to enter critical, then pop the flags from the stack to exit.  This way you automatically get nesting of critical sections.

If you cannot mess with the stack pointer then you have to use a variable to store the critical section nesting depth.  You can find examples of this method in other ports.  Search for a variable called CriticalNesting in the source tree.

The marcos to disable and enable interrupts are straight forward.

Architecture specifics
----------------------
These must be set correctly for your architecture.

portSTACK_GROWTH must be either 1 or -1 for up or down growth respectively.

portBYTE_ALIGNMENT should be 1, 2, 3 or 4.  For example an ARM requires 4 byte alignment so it is set to 4 for these processors.

That’s about it for this file, but the file must be included as part of the build.  To do this you need to edit the file FreeRTOS.org/Source/include/portable.h.  Take a look at this file and it should be clear what to do.  Basically each port has a unique definition to identify the port.  This definition must be defined as part of your project, resulting in the correct portmacro.h file being included in the build.

4.2 port.c (and optionally port assembly file).

Context saving order
--------------------
You need to decide how the context of your processor is going to be stored.  That is, which order are the registers to be saved in.  In the example suggested you will see portSAVE_CONTEXT() and portRESTORE_CONTEXT() macros.

If your processor allows software interrupts then such interrupts can be used for manual context switching (yielding).  This means that both the tick interrupt and yields can be entered via an interrupt and the resultant stack frame will be identical (see an x86 or ARM port for examples).  You then need to save any registers that are not automatically saved by the processor when you enter an interrupt.  This can be done in inline asm if your compiler can cope.  Make sure the yield and tick interrupts are ‘naked’.  You must save all the registers before any compiler generated code is executed.  Also you must not use any registers in the save process that have not already be saved.

If your processor does not permit software interrupts then tick interrupts will be entered via the interrupt mechanism of your processor, but yields will be entered as a standard function.  For the yield you again have to use a naked function, with the inline assembly code used to save the context so that the saved stack frame looks exactly as if an interrupt had occurred.  Remember to disable interrupts immediately after the original interrupt status has been saved as part of the context.  You may need to save the critical section nesting depth as part of the context also.

Once you have decided on how the context is to be saved you can start to implement the functions in port.c.

pxPortInitialiseStack()
-----------------------
This function is straight forward.  It simply sets up an initial stack for the task being created.  The stack uses the save context save order as per the tick and yield code mentioned above.  Note the order is as per the portSAVE/RESTORE_CONTEXT() macros.  Loading known values into the ‘stacked’ registers allows easy debugging when you are restoring the context for the first time.

xPortStartScheduler()
---------------------
This sets up a timer to generate the tick then starts the first task.  How the first task is started is processor dependent.  Basically restore the context then call an end of interrupt instruction, but of coarse it is never this simple ;-)  Each processor is done differently so check out the other ports for examples that match closely to your architecture.

vPortYield()
-----------
Save the context, call vTaskSwitchContext(), restore the context.  The saving and restoring may require an assembly file as the function must be naked.

This function is called when the application calles taskYIELD(), which in turn calls portYIELD().

vPortYieldFromTick()
--------------------
This is called different things in different ports, but is basically the tick interrupt handler.  Again may require an assembly file if you cannot have ‘naked’ functions. 

Simply, save context, call vTaskIncrementTick, call vTaskSwitchContext(), clear interrupt (don’t forget!), then restore context.

If you are also wanting a cooperative version (not preemptive) then this can be a standard interrupt function as generated by the compiler (no need to save or restore context), and just call vTaskIncrementTick() from within the handler.  This is often an easier route to start debugging.

prvSetupTimerInterrupt()
------------------------
Very processor specific.

5) A simple application can now be created.  You will require a FreeRTOSConfig.h file, of which there are plenty of examples in the download.  Remember:
i) Use the definition that ensures your portmacro.h file gets included within portable.h.
ii) FreeRTOS/source/include must be in the include path.
iii) Ensure FreeRTOSConfig.h can be found in the include path.

I suggest you start with the standard demo file flash.c.  This simply flashes LED.  To do this (rather random ordering in this list!):

i) Include FreeRTOS/demo/common/include in your project include path.
ii) Include the file FreeRTOS/demo/minimal/flash.c in your project.
iii) Find a main() file that calls vStartLEDFlashTasks(), use this as a basis.  Comment out all lines other than those required to setup the hardare, the call to vStartLEDFlashTasks() itself, and a call to vTaskStartScheduler().
iv) Include FreeRTOS/source/portable/memmang/heap_1.c in your project (as a minimum).
v) Include the three files from the FreeRTOS/source directory.  You won’t need to co-routine file.  These are the kernel files.
vi) Of coarse include the new port file in your build also.
vi) I suspect I’ve forgotten one or two things, but your linker warnings will let you know what.

The first thing to do after getting it to compile is step into the function xPortStartScheduler() and check that the context of the first task is restored correctly.  This may take one or two attempts, but you should see the initial values you placed in the stack you created for the task popped into the registers one by one, then finally the program counter loaded and a jump made to the start of the flash tasks. 

Once you have the first task executing the next thing to do is to step though a call to taskYIELD() to ensure the reverse is true, that the context is saved as you expect, then restored once more as the next task starts to execute.

Finally do the same for a preemptive tick.  Just ensure that on entry and exit from the tick (if preemptive is being used this is only) that the context is saved and restored correctly.

Hope this is more help that hindrance.

Regards.

cockcroftm wrote on Tuesday, July 18, 2006:

Many thanks for this info - I am well into creating the TLCS900 port utilising it.