Thursday, August 11, 2016

FreeRTOS 9.0.0 on ArduinoMEGA - Demo AVR323

Before we move on to the Demo Full, I'll first implement the same Demo you can find for the AVR323 port ("FreeRTOSv9.0.0\FreeRTOS\Demo\AVR_ATMega323_WinAVR"). This way we can check closely on how to configure the serial port, which will be very helpful for debugging purposes when we move on to the Demo Full.

To quick start, grab the source code in https://github.com/brunolalb/FreeRTOS_ArduinoMEGA-Demo_AVR323

For that, first we'll need a few extra files from the FreeRTOS.

  • From the folder "FreeRTOSv9.0.0\FreeRTOS\Demo\Common\include", copy the following files to the project folder "FreeRTOS_ArduinoMEGA-Demo_AVR323\FreeRTOS\Demo\Common\include": 
    • integer.h,
    • comtest.h,
    • serial.h,
    • PollQ.h,
    • crflash.h
  • From the folder "FreeRTOSv9.0.0\FreeRTOS\Demo\Common\Minimal", copy the following files to the project folder "FreeRTOS_ArduinoMEGA-Demo_AVR323\FreeRTOS\Demo\Common\Minimal": 
    • integer.c,
    • comtest.c,
    • PollQ.c,
    • crflash.c
  • A few other source files will have to be created (or adapted from the existing ones), so copy the folder "FreeRTOSv9.0.0\FreeRTOS\Demo\AVR_ATMega323_WinAVR\serial" to your project's root (it has the implementation of the serial port routines). 
  • The registers test routine, present in the ATmega323 Demo project can also be used, so I created a "RegTest" folder in the root of my project and added the regtest.c and regtest.h available in "FreeRTOSv9.0.0\FreeRTOS\Demo\AVR_ATMega323_WinAVR". 
  • Finally, for the co-routine capability be present, the source file croutine.c, available in "FreeRTOSv9.0.0\FreeRTOS\Source" must be copied to your projects folder "FreeRTOS_ArduinoMEGA-Demo_AVR323\FreeRTOS\Source".


On the following paragraphs, I'll describe the changes I made in the AVR323 Demo to run in our ArduinoMEGA port.

serial.c

As I told before, the serial routines are implemented in this file and they're very platform dependent, as many internal registers will be manipulated. This file is located in your project folder (if you copied the files I told you to) "FreeRTOS_ArduinoMEGA-Demo_AVR323\serial\serial.c". I understand the ATmega2560 has 4 serial ports (serial 0 to 3), but right now, I'm only implementing the Serial0, which is the one available on the USB connection. In the future, the serial.c can be modified to implement all the 4 hardware UART.

Basically what is needed is to correct the registers and interrupt vector names to the right ones, according to the microcontroller's datasheet. Besides that, I'm also using the option to double the communication speed, which will reduce the baud rate error rate (see table 22-12, page 226 of the datasheet), specially when using 115200 bps. Also, to enhance the routines, I added some error detection to the reception interrupt by checking the UCSRnA register prior to reading the data.

main.c

This file had several changes. First of all, I wanted it to keep the Demo Blinky routines, as I knew they're already working and blinking its LED, so it would be a good way of knowing if the program halted for some reason. Also, my approach on merging both projects (Demo Blinky and Demo AVR323) was to add each task creation call and compile. It wouldn't work, of course, so I would go after the missing headers and source files and compile again until it worked. So I added a bunch of flags to enable or disable each functionality. In the end, I got everything to work almost out of the box. Almost, as I realized a few things:

  • The coroutines use the first 3 LEDs (LEDs 0, 1 and 2) and this isn't easily configurable, so I made them available in the ParTest.c.
  • The Demo Blinky was configured to blink the LED 3
  • The Communication Tests uses the configured LED (4, for reporting a TX) and the next one (5, for reporting a RX) and expect to receive the same value it sent (a loop connection)
  • The Error Check task was configured to blink the LED 6 while the program worked fine (it stops blinking if something goes wrong).
  • The Assert Called function kept its LED number 7.
To see all that working, I had to place all LEDs in a protoboard, but don't forget to check Arduino's pin mapping to connect everything. The whole PORTB will blink LEDs now. The connection is as follows:

LED number Pin Name Mapped Pin Function
0
PB0
Digital 53
Co routine
1
PB1
Digital 52
Co routine
2
PB2
Digital 51
Co routine
3
PB3
Digital 50
Demo Blinky
4
PB4
Digital 10
Com Test - TX
5
PB5
Digital 11
Com Test - RX
6
PB6
Digital 12
Erro Check
7
PB7
Digital 13
(on board LED)
Assert Called


The project was uploaded to GitHub.

Tuesday, August 9, 2016

FreeRTOS 9.0.0 on ArduinoMEGA - Demo Blinky

By now, we have a <seemingly> operating FreeRTOS running in our ArduinoMEGA, but we're not using its whole capability. In order to test more functions, let's add a few functionalities step by step until we reach the Full Demo.

To quick start, grab the source code in https://github.com/brunolalb/FreeRTOS_ArduinoMEGA-Demo_Blinky.

FreeRTOS Demo Blinky

Yet another blinky project. This time I'm using the functionality we've studied a few months ago: here and here. This blinky project makes use of a Queue and has two tasks instead of one. One task (prvQueueSendTask()) is a sender and will add a constant value to a queue every 200 ms, while the other task (prvQueueReceiveTask()) is the receiver and will try to get the value from the queue (blocking operation) and, if the value is right, will toggle a LED on PORTB.PB6 (the same from the Blink project).

Another test performed in this project is the implementation of the configASSERT() function, which is very useful for debugging purposes. In this project, a parameter is passed to the tasks when they're created and the task should check it in order to attest that it's right. The configASSERT() will turn on the LED embedded in ArduinoMEGA's board (PORTB.PB7), as by now there's nothing much implemented yet. In the future, it could be changed to a message sent through the Serial port.

To get things moving faster, I thought on using the whole main_blinky.c from the Win32 Demo with as little changes as possible. The problem is that it wouldn't be very efficient, once the Windows Demo uses several long variables (32 bits wide) and we're running on an 8-bits microcontroller. Thus I made a few changes to optimize the code.

The main() function initializes not only the queue, which now stores unsigned char variables, but also the LEDs, using the same function as the Blink project. It then creates both tasks with predefined parameters (changed to accommodate one unsigned int) and starts the scheduler.

int main( void )
{
 /* Create the queue. */
 xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned char ) );

 /* Setup the LED's for output. */
 vParTestInitialise();
 if( xQueue != NULL )
 {
  /* Start the two tasks as described in the comments at the top of this file. */
  xTaskCreate( prvQueueReceiveTask,   /* The function that implements the task. */
        "RX",      /* The text name assigned to the task - for debug only as it is not used by the kernel. */
        configMINIMAL_STACK_SIZE,    /* The size of the stack to allocate to the task. */
        ( void * ) mainQUEUE_RECEIVE_PARAMETER, /* The parameter passed to the task - just to check the functionality. */
        mainQUEUE_RECEIVE_TASK_PRIORITY,   /* The priority assigned to the task. */
        NULL );     /* The task handle is not required, so NULL is passed. */

  xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL );
 }

 /* In this port, to use preemptive scheduler define configUSE_PREEMPTION
 as 1 in portmacro.h.  To use the cooperative scheduler define
 configUSE_PREEMPTION as 0. */
 vTaskStartScheduler();

 return 0;
}

The receiver task now blinks a LED instead of printing something. The request from the queue blocks the task for a long time while waiting something to be added to it.

static void prvQueueReceiveTask( void *pvParameters )
{
unsigned char ucReceivedValue;

 /* Remove compiler warning in the case that configASSERT() is not
 defined. */
 ( void ) pvParameters;

 /* Check the task parameter is as expected. */
 configASSERT( ( ( unsigned int ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER );

 for( ;; )
 {
  /* Wait until something arrives in the queue - this task will block
  indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
  FreeRTOSConfig.h. */
  xQueueReceive( xQueue, &ucReceivedValue, portMAX_DELAY );

  /*  To get here something must have been received from the queue, but
  is it the expected value?  If it is, toggle the LED. */
  if( ucReceivedValue == 100UL )
  {
   /* The Windows Blinky Demo prints a message with printf().
    * In Arduino, we'll just blink a LED */
   vParTestToggleLED(mainLEDBLINK_TASK_LED);

   ucReceivedValue = 0U;
  }
 }
}

The sender task gave a bit more trouble, even though the changes in its code were minimal (this is why I'm not pasting it here). Its objective is to add a certain value to the queue, then sleep for a certain amount of time (200 ms). Instead of using the vTaskDelay(), as used in our last project, it uses the vTaskDelayUntil() (it is used to ensure the routine will run every X milliseconds, despite the execution time), and the time was previously defined in milliseconds. To calculate the number of ticks to wait, the pdMS_TO_TICKS() macro is used. If you expand the macro (you can check in FreeRTOS/Source/Include/projdefs.h), you'll see that it multiplies the time, in milliseconds, with the tick rate in Hz, casting everything to TickType_t, which, in Windows is an uint32_t (thus 32-bits), but in our port is an uint16_t (thus 16-bits). This means it will multiply 200 (ms) with 1000 (Hz), which exceeds 16-bits. In order to the macro to work, it has to be redefined in FreeRTOSConfig.h (if you check the comments in projdefs.h, it's already something expected). This is what was added to the end of the header:

/* It is a good idea to define configASSERT() while developing.  configASSERT()
uses the same semantics as the standard C assert() macro. */
extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ )

/* Due to problems with integer overflow, this macro is defined here */
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( unsigned long ) ( xTimeInMs ) * ( unsigned long ) configTICK_RATE_HZ ) / ( unsigned long ) 1000 ) )

As you can see, I casted this multiplication operation to an unsigned long, which is 4 bytes wide.

The vAssertCalled(), which is defined in main.c only sets the LED.

void vAssertCalled( unsigned long ulLine, const char * const pcFileName )
{
 /* Parameters are not used. */
 ( void ) ulLine;
 ( void ) pcFileName;

 vParTestSetLED(mainASSERTCALLED_LED, pdTRUE);
}

The project was uploaded to GitHub.

Friday, August 5, 2016

FreeRTOS 9.0.0 on ArduinoMEGA - Blink project

For a quick start, refer to the project on github:
http://github.com/brunolalb/FreeRTOS_ArduinoMEGA-Blink

FreeRTOS 8.2.3 to 9.0.0 changelog

It's finally time to start working on the FreeRTOS port to ArduinoMEGA. It's been a long time since I started this blog that even a new version of FreeRTOS came up. The system is now on 9.0.0 version, so that's the one I'll use from now on. So first of all, you should download the source code from their website: click here. There aren't many differences from the latest version and the code is pretty much compatible. The complete changelog can be checked here, but I'll describe some of the new features, enhancements and new ports implemented.

  • Support to completely statically allocated systems: remember the post about the memory allocation systems? heap_1.c, heap_2.c, etc? Those were about dynamic allocation. The new version supports static allocation, which means the RAM footprint is defined by linking time, rather than running time. More info can be found here and here.
  • Forcing a task to leave the blocked state: while the task is waiting for something (a semaphore take with timeout or a simple delay), the task is remained in blocked state. The new version implements an API function that unblocks a task (xTaskAbortDelay()). More info here.
  • Deleting tasks: in prior versions, when a task was deleted, its memory were only freed by the Idle function, independently of who has deleted it. Now, when one task is deleted by another task, the memory (stack and TCB) is freed immediately.
  • Obtaining a Task Handle from the Task Name: it's now possible to do this with the new API function: xTaskGetHandle(). More info here.
  • configAPPLICATION_ALLOCATED_HEAP: it's now possible to specify the memory position where the heap will be allocated when using heap_1 or heap_2 (and heap_4, but that was already possible) by declaring the array "uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];". More info here.

Creating required files and the Eclipse project

The initial objective will be to have the bare minimal amount of code to run the FreeRTOS and just make a LED blink. On your file explorer, create the folder where your project will be. In that folder, create another folder called FreeRTOS, where we'll keep all the RTOS code, just for cleanliness purposes. Let's copy the source files from the FreeRTOS official folder:
  • The basic kernel: Source/tasks.c, queue.c and list.c
  • Memory management: Source/MemMang/heap_1.c (this is the simpler one)
  • The portable bits: Source/portable/[compiler]/[processor]/port.c and portmacro.c
    • In this case, I created the folder WinAVR as the [compiler] and ATmega2560 as the [processor].
    • I copied the files from the ATmega323 port (FreeRTOSv9.0.0\FreeRTOS\Source\portable\GCC\ATMega323) to start with something close to what I want.
  • Header files: Source/include/ (you may copy the whole folders) and Demo\Common\include\partest.h.
To the root folder of the project we'll add the application specifics (I copied them from the ATmega323 Demo project, in FreeRTOSv9.0.0\FreeRTOS\Demo\AVR_ATMega323_WinAVR):
  • FreeRTOSConfig.h 
  • main.c
  • ParTest/ParTest.c
This is what we have in our project folder:


Supposing that you already have your Eclipse configured (if not, check here), open it and go to File > New > C++ Project.
  1. Choose the Empty Project under the folder "AVR Cross Target Application"
  2. Pick a name (FreeRTOS_ArduinoMEGA - rev0.1) and point the location to your project folder


  3. Click Next
  4. Click Next again (Debug and Release configs)
  5. Choose the MCU (ATmega2560) and Frequency (16000000 - that's 16 followed by 6 zeroes, 16MHz)
  6. Click Finish. This is what your Project Explorer should be showing:


  7. In the Project Properties, under AVR > AVRDude, in the box Programmer Configuration, choose the config you created for the Blink project (or follow the steps 9 and 10 here): ArduinoMEGA2560 - STK500v2.
  8. Still on the Project Properties, go to C/C++ Build > Settings. On the tab Tool Settings:
    1. Additional Tools in Toolchain, check "Generate HEX file for Flash memory"
    2. AVR Compiler > Optimization, Optimization Levels: Size Optimization (-Os), uncheck Pack Structs and Short Enums
    3. AVR Compiler > Language Standard, uncheck "char is unsigned" and "bitfields are unsigned"
    4. Do the same to AVR C++ Compiler
  9. Adjusting some paths under C/C++ General > Paths and Symbols > Includes, add the following workspace directories:
    1. Project's root
    2. FreeRTOS/Demo/Common/include
    3. FreeRTOS/Source/include
    4. FreeRTOS/Source/portable/WinAVR/ATmega2560
By now, the project should be ready, but the code is all wrong, so let's work on that.

Working on port.c and portmacro.h

Before we start, we should define a few things. First of all, the main timer for the FreeRTOS (the one that will provide the Tick) will be Timer 1 and the Tick will be 1 ms (1000 Hz). No special reason, as it could be any other, but two things made me choose this: it's the same used in AVR323 and it's the same time we used on the Blink project.
This timer should produce interrupts every 1 ms, without any interference of the FreeRTOS functions, thus a simple timer that counts to a certain value, indicates an interrupt and resets on its own, restarting the process. Refer to the function prvSetupTimerInterrupt( void) around line 402 of the port.c file. There are a few differences, since the ATmega323 is bit simpler.
/*
 * Setup timer 1 compare match A to generate a tick interrupt.
 */
static void prvSetupTimerInterrupt( void )
{
uint32_t ulCompareMatch;
uint8_t ucHighByte, ucLowByte;

 /* Using 16bit timer 1 to generate the tick.  Correct fuses must be
 selected for the configCPU_CLOCK_HZ clock. */

 ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;

 /* We only have 16 bits so have to scale to get our required tick rate. */
 ulCompareMatch /= portCLOCK_PRESCALER;

 /* Adjust for correct value. */
 ulCompareMatch -= ( uint32_t ) 1;

 /* Setup compare match value for compare match A.  Interrupts are disabled 
 before this is called so we need not worry here. */
 ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
 ulCompareMatch >>= 8;
 ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
 OCR1AH = ucHighByte;
 OCR1AL = ucLowByte;

 /* Setup clock source and compare match behaviour. */
 ucLowByte = portCLEAR_COUNTER_ON_MATCH_TCCR1A;
 TCCR1A = ucLowByte;
 ucLowByte = portCLEAR_COUNTER_ON_MATCH_TCCR1B | portPRESCALE_64;
 TCCR1B = ucLowByte;

 /* Enable the interrupt - this is okay as interrupt are currently globally
 disabled. */
 ucLowByte = TIMSK1;
 ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
 TIMSK1 = ucLowByte;
}
/*-----------------------------------------------------------*/
You probably realize two changes: The addition of the TCCR1A config and the correct config of the TIMSK1 register (was TIMSK on ATmega323). The definitions (around line 90) change to the following.
/* Hardware constants for timer 1. */
#define portCLEAR_COUNTER_ON_MATCH_TCCR1A  ( ( uint8_t ) 0b00000000 )
#define portCLEAR_COUNTER_ON_MATCH_TCCR1B  ( ( uint8_t ) 0b00001000 )
#define portPRESCALE_64     ( ( uint8_t ) 0b00000011 )
#define portCLOCK_PRESCALER    ( ( uint32_t ) 64 )
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE  ( ( uint8_t ) 0b00000010 )

Even though both microcontrollers use the same AVR architecture, the ATmega2560 has 2 more registers to be saved: RAMPZ and EIND, thus the functions portSAVE_CONTEXT() and portRESTORE_CONTEXT() will need a tweek.

#define portSAVE_CONTEXT()     \
 asm volatile ( "push r0   \n\t" \
   "in r0, __SREG__  \n\t" \
   "cli    \n\t" \
   "push r0   \n\t" \
   "in r0, 0x3b  \n\t" \
   "push r0   \n\t" \
   "in r0, 0x3c  \n\t" \
   "push r0   \n\t" \
   "push r1   \n\t" \
   "clr r1   \n\t" \
   "push r2   \n\t" \
   "push r3   \n\t" \
   "push r4   \n\t" \
   "push r5   \n\t" \
   "push r6   \n\t" \
   "push r7   \n\t" \
   "push r8   \n\t" \
   "push r9   \n\t" \
   "push r10   \n\t" \
   "push r11   \n\t" \
   "push r12   \n\t" \
   "push r13   \n\t" \
   "push r14   \n\t" \
   "push r15   \n\t" \
   "push r16   \n\t" \
   "push r17   \n\t" \
   "push r18   \n\t" \
   "push r19   \n\t" \
   "push r20   \n\t" \
   "push r21   \n\t" \
   "push r22   \n\t" \
   "push r23   \n\t" \
   "push r24   \n\t" \
   "push r25   \n\t" \
   "push r26   \n\t" \
   "push r27   \n\t" \
   "push r28   \n\t" \
   "push r29   \n\t" \
   "push r30   \n\t" \
   "push r31   \n\t" \
   "lds r26, pxCurrentTCB \n\t" \
   "lds r27, pxCurrentTCB + 1 \n\t" \
   "in r0, 0x3d  \n\t" \
   "st x+, r0   \n\t" \
   "in r0, 0x3e  \n\t" \
   "st x+, r0   \n\t" \
 );
#define portRESTORE_CONTEXT()     \
 asm volatile ( "lds r26, pxCurrentTCB \n\t" \
   "lds r27, pxCurrentTCB + 1 \n\t" \
   "ld r28, x+   \n\t" \
   "out __SP_L__, r28  \n\t" \
   "ld r29, x+   \n\t" \
   "out __SP_H__, r29  \n\t" \
   "pop r31   \n\t" \
   "pop r30   \n\t" \
   "pop r29   \n\t" \
   "pop r28   \n\t" \
   "pop r27   \n\t" \
   "pop r26   \n\t" \
   "pop r25   \n\t" \
   "pop r24   \n\t" \
   "pop r23   \n\t" \
   "pop r22   \n\t" \
   "pop r21   \n\t" \
   "pop r20   \n\t" \
   "pop r19   \n\t" \
   "pop r18   \n\t" \
   "pop r17   \n\t" \
   "pop r16   \n\t" \
   "pop r15   \n\t" \
   "pop r14   \n\t" \
   "pop r13   \n\t" \
   "pop r12   \n\t" \
   "pop r11   \n\t" \
   "pop r10   \n\t" \
   "pop r9   \n\t" \
   "pop r8   \n\t" \
   "pop r7   \n\t" \
   "pop r6   \n\t" \
   "pop r5   \n\t" \
   "pop r4   \n\t" \
   "pop r3   \n\t" \
   "pop r2   \n\t" \
   "pop r1   \n\t" \
   "pop r0   \n\t" \
   "out 0x3c, r0  \n\t" \
   "pop r0   \n\t" \
   "out 0x3b, r0  \n\t" \
   "pop r0   \n\t" \
   "out __SREG__, r0  \n\t" \
   "pop r0   \n\t" \
 );

The same goes to the pxPortInitialiseStack(). After saving the address for the task, you'll need an extra increment of the stack pointer, and after saving the interrupt enable, you'll need to save the initialize value of both RAMPZ and EIND registers (they'll be initialized with 0). Then, you can save the rest of the registers. I'll copy here only part of the function.

 /* The start of the task code will be popped off the stack last, so place
 it on first. */
 usAddress = ( unsigned portSHORT ) pxCode;
 *pxTopOfStack = ( StackType_t ) ( usAddress & ( unsigned portSHORT ) 0x00ff );
 pxTopOfStack--;

 usAddress >>= 8;
 *pxTopOfStack = ( StackType_t ) ( usAddress & ( unsigned portSHORT ) 0x00ff );
 pxTopOfStack--;

 *pxTopOfStack = 0;
 pxTopOfStack--;

 /* Next simulate the stack as if after a call to portSAVE_CONTEXT().  
 portSAVE_CONTEXT places the flags on the stack immediately after r0
 to ensure the interrupts get disabled as soon as possible, and so ensuring
 the stack use is minimal should a context switch interrupt occur. */
 *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
 pxTopOfStack--;
 *pxTopOfStack = portFLAGS_INT_ENABLED;
 pxTopOfStack--;

 /* If we have an ATmega2560, we are also saving the RAMPZ and EIND registers.
  * We should default those to 0.
  */
 *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* EIND */
 pxTopOfStack--;
 *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* RAMPZ */
 pxTopOfStack--;


 /* Now the remaining registers.   The compiler expects R1 to be 0. */
 *pxTopOfStack = ( StackType_t ) 0x00; /* R1 */
 pxTopOfStack--;

The port.c is done.

As for the header (portmacro.h), there is no need to change anything (that's the cool thing of starting from a similar architecture).

FreeRTOSConfig.h

This file won't need much work. First of all, our Arduino is running at 16 MHz, thus the configCPU_CLOCK_HZ has to be changed. The tick rate remains at 1000 Hz. The ATmega2560 has 8KB of SRAM, instead of the 2KB available in the ATmega323, thus change the configTOTAL_HEAP_SIZE to something closer to 8KB (I used 7500). I'm not using the idle hook, thus set configUSE_IDLE_HOOK to 0.

main.c

This will need some extra work, as by now we're only trying to blink a led, so most of it is going away. This is what I'm left with.

#include <stdlib.h>
#include <string.h>

/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"

/* Demo file headers. */
#include "partest.h"

/* Priority definitions for most of the tasks in the demo application.  Some
tasks just use the idle priority. */
#define mainLED_TASK_PRIORITY   ( tskIDLE_PRIORITY + 1 )

/* The sleeping period for blinking the LED */
#define mainLEDBLINK_TASK_PERIOD  ( ( TickType_t ) 1000 / portTICK_PERIOD_MS  )

/* LED that is toggled every mainLEDBLINK_TASK_PERIOD */
#define mainLEDBLINK_TASK_LED   ( 6 )

/*
 * The task function for the "Blink" task.
 */
static void vBlink( void *pvParameters );

/*-----------------------------------------------------------*/

int main( void )
{
 /* Setup the LED's for output. */
 vParTestInitialise();

 /* Create the tasks defined within this file. */
 xTaskCreate( vBlink, "Blink", configMINIMAL_STACK_SIZE, NULL, mainLED_TASK_PRIORITY, NULL );

 /* In this port, to use preemptive scheduler define configUSE_PREEMPTION
 as 1 in portmacro.h.  To use the cooperative scheduler define
 configUSE_PREEMPTION as 0. */
 vTaskStartScheduler();

 return 0;
}
/*-----------------------------------------------------------*/

static void vBlink( void *pvParameters )
{
 /* The parameters are not used. */
 ( void ) pvParameters;

 /* Cycle forever, toggling the LED and sleeping */
 while(1)
 {
  vParTestToggleLED(mainLEDBLINK_TASK_LED);
  vTaskDelay(mainLEDBLINK_TASK_PERIOD);
 }

}
/*-----------------------------------------------------------*/

I know ArduinoMEGA's LED is connected to the 7th bit of PORTB, but I added an extra on the 6th bit (digital port 12 on the board) for debug purposes.

ParTest.c

The last changes are in ParTest.c, as the original used the whole port as LEDs. I'm using only bits 6 and 7. Also, the ATmega2560 has this register PINB that, when you write a 1 to a bit, it toggles the value of the output.

#include "FreeRTOS.h"
#include "task.h"
#include "partest.h"

/*-----------------------------------------------------------
 * Simple parallel port IO routines.
 *-----------------------------------------------------------*/

#define partstLEDS_OUTPUT ( ( unsigned char ) 0b11000000 )
#define partstALL_OUTPUTS_OFF ( ( unsigned char ) 0b00111111 )
#define partstMAX_OUTPUT_LED ( ( unsigned char ) 7 )
#define partstMIN_OUTPUT_LED ( ( unsigned char ) 6 )

static volatile unsigned char ucCurrentOutputValue = partstALL_OUTPUTS_OFF;

/*-----------------------------------------------------------*/

void vParTestInitialise( void )
{
 ucCurrentOutputValue = partstALL_OUTPUTS_OFF;

 /* Set port B direction to outputs.  Start with all output off. */
 DDRB = partstLEDS_OUTPUT;
 PORTB &= ucCurrentOutputValue;
}
/*-----------------------------------------------------------*/

void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue )
{
unsigned char ucBit = ( unsigned char ) 1;

 if(( uxLED <= partstMAX_OUTPUT_LED ) && ( uxLED >= partstMIN_OUTPUT_LED ))
 {
  ucBit <<= uxLED; 

  vTaskSuspendAll();
  {
   if( xValue == pdFALSE )
   {
    ucBit ^= ( unsigned char ) 0xff;
    ucCurrentOutputValue &= ucBit;
    PORTB &= ucCurrentOutputValue;
   }
   else
   {
    ucCurrentOutputValue |= ucBit;
    PORTB |= ucCurrentOutputValue;
   }
  }
  xTaskResumeAll();
 }
}
/*-----------------------------------------------------------*/

void vParTestToggleLED( unsigned portBASE_TYPE uxLED )
{
 unsigned char ucBit;

 if(( uxLED <= partstMAX_OUTPUT_LED ) && ( uxLED >= partstMIN_OUTPUT_LED ))
 {
  ucBit = ( ( unsigned char ) 1 ) << uxLED;

  vTaskSuspendAll();
  {

   PINB = ucBit;
   ucCurrentOutputValue = PORTB;
  }
  xTaskResumeAll();   
 }
}

I guess this is it!
Compile, add the forgotten ; and send it to your Arduino. Try changing the delay on the Blink task and send it again. I uploaded the whole project to GitHub.

Monday, August 1, 2016

ArduinoMEGA on Eclipse without Arduino SDK

More than being quite limited, the Arduino IDE comes with its own SDK, which means we can't have our own main() function. I chose Eclipse because it's free and easy to use and there are a few tutorials around on how to use an Arduino board with Eclipse IDE. So, I read lots of them and came up with my own step by step:

  1. On Windows:
    1. Download and install Eclipse IDE for C/C++ Developers (today, the latest is Mars 2)
    2. Download and install WinAVR (today, the latest is 20100110)
    3. Open Eclipse, go to Help > Install New Software.... Add the following to the "Work with" section: http://avr-eclipse.sourceforge.net/updatesite and install the plugin.
    4. Done!
  2. On Linux (Ubuntu in my case):
    1. Install Eclipse
      1. sudo apt-get install eclipse
    2. Install AVR compiler
      1. sudo apt-get install avrdude binutils-avr gcc-avr avr-libc gdb-avr
    3. Open Eclipse, go to Help > Install New Software.... Add the following to the "Work with" section: http://avr-eclipse.sourceforge.net/updatesite and install the plugin.
    4. Add your user to the dialout group, then logout and login again (this is in order to your user have permission to access the serial port).
      1. sudo usermod -a -G dialout <username>
    5. Done!


Wait, what? This is it? Yep! Unless you didn't install WinAVR on its default location (C:/WinAVR-20100110). In that case, you'll need to adjust the paths in the AVR Eclipse plugin (on Eclipse, go to Window > Preference > AVR > Paths):
  • AVR-GCC: <WinAVR path>\bin
  • GNU make: <WinAVR path>\utils\bin
  • AVR Header Files: <WinAVR path>\avr\include
  • AVRDude: <WinAVR path>\bin

Yes, this screen is from Ubuntu.

Now let's create a first project just to check whether it works. Can you guess? A Blink project! This time, we won't use any of the easy Arduino stuff. Instead, let's open the microcontroller datasheet and start configuring the registers. In Eclipse, go to File > New > C++ Project (in Linux, you'll go to File > New > Project and choose C++ Project under C/C++ Folder).
  1. Choose the Empty Project under the folder "AVR Cross Target Application"


  2. Pick a name (Blink) and a location
  3. Click Next
  4. Click Next again
  5. Choose the MCU (ATmega2560) and Frequency (16000000 - that's 16 followed by 6 zeroes, 16MHz)
  6. Click Finish
  7. Go to the project properties (click with the left button on the project and go to Properties)
  8. Under AVR > Target Hardware you can check if the MCU and frequency were correctly chosen

  9. Under AVR > AVRDude, in the box Programmer Configuration, click New....
  10. Choose the bootloader version (Atmel STK500 Version 2.x firmware), choose a name for the configuration, choose the correct COM port in "Override default port" (use the Device Manager in Windows -i.e. COM18 -, or, in Linux, the command line "dmesg | grep tty" and remember to put "/dev/" before the port name - i.e. /dev/ttyUSB0), and override default baudrate with 115200  and click OK.
  11. Still on the Project Properties, go to C/C++ Build > Settings. On the tab Tool Settings:
    1. Additional Tools in Toolchain, check "Generate HEX file for Flash memory"
    2. AVR Compiler > Optimization, Optimization Levels: Size Optimization (-Os), uncheck Pack Structs and Short Enums
    3. AVR Compiler > Language Standard, uncheck "char is unsigned" and "bitfields are unsigned"
    4. Do the same to AVR C++ Compiler
  12. Now for the source code files, click with the left button on the project folder (in Project Explorer) and go to New > Folder, choose the project and the name ("src") and click Finish. Again in the Project Explorer, left click on new folder and New > Source File, choose the name ("blink.cpp") and Finish.
  13. Copy the following source code to your file.
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    int main(void)
    {
     //Setup the clock (timer 1, 62.5kHz (16MHz / 256 = 62.5kHz), CTC mode, interrupt on)
     cli(); //Disable global interrupts
     TCCR1A = 0b00000000; //no physical outputs (COM1Ax, COM1Bx and COM1Cx == 0b00), WGM10 and WGM11 = 0.
     TCCR1B = 0b00001000; //input capture off, WGM13 = 0, WGM12 = 1, prescaler 1/256 (CS1x = 0b100 - off by now, thus 0b000)
     TCCR1C = 0b00000000; //writing a 1 to any of the 3 most significative bits forces a compare match
     TCNT1 = 0x0000; //resets the timer counter
     OCR1A = 62499; //Count 62500 cycles for 1 second interrupt
     OCR1B = 0x0000; //output compare register B is not used
     OCR1C = 0x0000; //output compare register C is not used
     ICR1 = 0x0000; //input capture not used
     TIMSK1 = 0b00000010; //input capture interrupt off, output compare B and C interrupts off, output compare A interrupt on, overflow interrupt off
     TIFR1 = 0x00; //resets the interrupt flags
     TCCR1B |= 0b00000100; //turn on the timer (CS1x = 0b100)
     sei(); //Enable global interrupts
    
     //Setup the I/O for the LED (digital pin 13, or PB7, according to the Arduino pin mapping)
     DDRB = 0b10000000; //PB7 is digital pin 13 (LED), configured as an output
     PORTB |= 0b10000000; //Set PB7 high to turn on LED
    
     while(1) { } //Loop forever, interrupts do the rest
    }
    
    ISR(TIMER1_COMPA_vect) //Interrupt Service Routine - flag is cleared automatically
    {
      PORTB ^= (1<<PB7); //Use xor to toggle the LED
    }
  14. Build it (Ctrl+B)
    1. Edit: If you're using Windows 10 (or other versions) and encountered this error: make: *** [src/blink.o] Error -1073741502, follow the steps on this post.
  15. To transfer to the board, there's a little catch (in Windows): seems like Arduino IDE uses a modified version of AVRDude that resets the board before attempting to upload the HEX file (this is needed in order to the Arduino enter the bootloader). So, if you get this timeout message, just hold the reset button on your board and release when you click the Upload button (that's the AVR button with an arrow pointing downwards, or CTRL+ALT+U).
    avrdude: stk500_2_Receive_Message(): timeout
  16. Now modify the OCR1A to 6249, compile and upload again: The timer will run 10 times faster, thus the LED must blink faster, if it doesn't, well...find out what's wrong and tell me in the comments box :)

Right now you should have a working hardware, with a working IDE and burner (close enough).
The project is available on GitHub.

On the next post, let's talk business and start porting the FreeRTOS.

Wednesday, June 1, 2016

Arduino's guts

After a long period of FreeRTOS posts, it's time to go back to Arduino to check some peculiarities. One of the great things that comes with an Arduino, besides the hardware ready to use out-of-the-box, is the Bootloader already burned in it. This means there is no need for the user to buy an expensive AVR programmer to work with it, you just have to plug it in an USB port and Download your application.

This bootloader uses a communication protocol originally developed by Atmel for the STK500 starterkit [http://www.atmel.com/Images/doc2525.pdf], which is why the protocol has this name. I believe there is no need to understand exactly how the protocol works, but a few remarks should be done. The bootloader will occupy some space in memory and that space mustn't be erased/overwritten, otherwise the bootloader is lost and we'll have to burn it again [https://www.arduino.cc/en/Hacking/Bootloader?from=Tutorial.Bootloader]. This can be prevented by correctly configuring the linker to only use addresses far from the bootloader and to place the main() function on the correct address that will be called.

So, let's check those information. First of all, we need to find the version of the bootloader that runs in our Arduino, so there goes a nice tip: send the string "!!!" to the Arduino just after it resets (you can use a serial terminal application, such as RealTerm [http://realterm.sourceforge.net/]). This will send us to the "Arduino Explorer" (a kind of terminal with a few commands we can send to the bootloader). So, press "H" to show the available commands: one of them should be "?=CPU stats" that will show which version is used. Step by step:

  1. Connect Arduino Board to your computer
  2. Open RealTerm and select the COM Port and Speed (115200), connect to COM Port
  3. Preset the string to be sent: "!!!" (3 exclamation points)
  4. Quickly, press the reset button on Arduino and send the String (this should be done within 1 or 2 seconds)
  5. Send "H" to check the available commands
  6. Send "?" to check the CPU Stats

In my case, the bootloader is the STK500v2 compiled in September 9th 2010 running on a ATmega2560. If you already installed the Arduino IDE, it's possible to analyze the code, under C:\Arduino\hardware\arduino\avr\bootloaders\stk500v2 (you can open the Programmer's Notepad project file STK500V2.pnproj).

Let's check some of the information we need to configure the linker in our port. First open the makefile of the bootloader and locate the part where the config variables for your board are. In my case, it's a mega2560, thus around line 337. One of the configurations is the BOOTLOADER_ADDRESS, set to 3E000 (hexadecimal), which means that the bootloader uses the last 8KB of read only memory (atmega2560 has 256KB of ROM, 0x3E000 == 248KB, 256 - 248 = 8KB).

Ok. From the paragraphs, please only remember the protocol your board uses (STK500v2) and that the maximum size of your program will have to be 248KB, which is a lot. I was writing and studying the subjects at the same time and just realized we won't have to configure much on the linker. If we were using an on board programmer, such as an ISP or JTAG, that doesn't communicate with the bootloader, than yes, we would have to take good care of the where the program would be programmed, but we're not. We'll actually use the bootloader through a serial connection and the bootloader will store our program in the ROM.

Enough with the bootloader, now: where is Arduino's main function? When you're using Arduino IDE, you have the setup() function, for configuring what you'll use, such as an analog output, a serial communication, etc, and the loop() function, which is basically what is in a while(1) loop. But what calls those functions? This is the job of the core library, which can be found under C:\Arduino\hardware\arduino\avr\cores\arduino. In the file main.cpp is defined the main() function, which initializes the microcontroller (function init()). Another few interesting functions are in wiring.c, such as the timer0 overflow interrupt, responsible for counting mili and microseconds (remember the delay() function?), and the init() itself. The wiring_analog.c has the analogRead() and analogWrite() definitions. pinMode(), digitalRead() and digitalWrite() are in wiring_digital.c.
int main(void)
{
    init();
    initVariant();

    #if defined(USBCON)
    USBDevice.attach();
    #endif

    setup();

    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }

    return 0;
}

FreeRTOS won't use any of this, as my intention is to have the RTOS running on the board as close to any other implementation as possible. This means that the main function will be the one defined in FreeRTOS' code and we won't have any loop() or setup() or digitalWrite() funcions. We're basically using the ArduinoMEGA as a development board that already comes with an easy to use bootloader and nothing more. The whole Arduino SDK will be nothing more than an application that we know it works and we can check for some configuration to use in our FreeRTOS port.

Next step will be to get Eclipse up and running with everything we need to upload our FreeRTOS.

Tuesday, April 19, 2016

ATMega323 port

This post will talk about the portable part of FreeRTOS. As the Windows port is not exactly a port (the FreeRTOS actually runs on top of another operating system, which incurs in a few anomalies when the was made), I'll examine the Atmega323 for WinAVR port files, located under FreeRTOS\Source\portable\GCC\ATMega323. First of all, a quick review on the source file structure.

FreeRTOS Source Files Organization

When you download and extract the zip file containing the FreeRTOS [1], you'll see two directories: FreeRTOS-Plus and FreeRTOS. The first one comprises the FreeRTOS+ ecosystem [2] and the second, the FreeRTOS source code itself (I'll focus on that). Under FreeRTOS directory, there are 3 folders: License (only has the license itself), Demo (all the different official ports and demo applications available) and Source (the real time kernel source). The core RTOS kernel, contained under the Source folder, is comprised of basically three files: tasks.c, queue.c and list.c. The others (croutine.c for co-routine implementation, timers.c for software timers and event_groups.c) are optional.

Each ported processor will require some specific code (mainly the files port.c and portmacro.h), which, for the official ports, is located under FreeRTOS/Source/Portable/[compiler]/[architecture]. For instance, the ATMega323 port we'll check later can be found in FreeRTOS\Source\portable\GCC\ATMega323, as AVR-GCC (WinAVR [3]) is the compiler and ATMega323 is the architecture. The Windows port files we've been using can be found under FreeRTOS\Source\portable\MSVC-MingW.

As the memory management (heap) routines are also needed, the samples we discussed earlier are also provided in the portable layer/folder structure under FreeRTOS\Source\portable\MemMang. There you'll find the 5 sample heap implementations, but you can also write your own and place it there.

Under the Demo folder is where you'll find the specific demo applications source code, along with the common demo implementation code for several functionalities (queues, semaphores, timers, etc) I talked a few times about (here and here). Each official demo application has its own folder, named to indicate the port to which they relate, under FreeRTOS/Demo/ (this is where the FreeRTOSConfig.h is located, for example) as well as an official webpage [4]. Under FreeRTOS/Demo/Common/Minimal/, you'll find the basic implementation for the functionalities that is shared between several applications. The Windows port uses the file under FreeRTOS/Demo/Common/Full/, but that should be avoided, as those are deprecated.
The basic structure of the Windows port demo application can be seen below:

FreeRTOS/
 +- Demo/
 |   +- Common/Minimal/
 |   +- WIN32-MingW/
 +- Source/
     +- *.c
     +- include/
     +- portable/
         +- MemMang/
         +- MSVC-MingW/


Creating a new application

To create a new application from an existing port, the quickest path is to use a Demo application and modify it to fit your needs. Compile and run the standard demo project and, when it runs as expected, you can add and/or remove whatever you may want.

Official Porting Guide

Here, I'll give you a little resume on the official porting guide provided by FreeRTOS [5]. Later on, we'll check the ATMega323 port files.

So the first thing you should do is to familiarize yourself with the source files organization (done that!) and create a folder under FreeRTOS/Source/portable/[compiler]/[processor]. Copy an empty port.c and portmacro.h there (you can use complete files from other ports, just remember clean all functions and macro bodies and only leave the stubs). Create a directory for the demo project for the new port under FreeRTOS/Demo/[architecture_compiler] and add a copy of FreeRTOSConfig.h and main.c (remember to only leave the stubs and modify some of the options from the config file that are hardware dependent, such as the tick rate, heap size, etc - check my other post about that). Now create a new folder under [architecture_compiler] called ParTest and copy some version of ParTest.c with just the stubs inside. This file will have a few LED tests that should run when your port is working fine: setup a few GPIOs to be used as LED outputs, turn on, off or toggle specific LEDs (remember what I said in some earlier post? blinking LEDs is the hello world of the embedded applications).

Now that everything is in place, you can create a project (makefile) that will successfully compile (not run, as there are a lot of stubs to implement) everything:
  • The basic kernel: Source/tasks.c, queue.c and list.c
  • The portable bits: Source/portable/[compiler]/[processor]/port.c
  • Memory management: Source/MemMang/heap_?.c (choose one of them)
  • Application specifics: Demo/[architecture_compiler]/main.c and ParTest/ParTest.c
And the hard part: implementing the stubs. The official guide suggests to start from the pxPortInitializeStack(), as it's very architecture dependent.

ATMega323 port.c

The windows port is not really a conventional port, since the FreeRTOS runs over another operating system that is not real time, and there surely might be a few things to learn by examining it, but as not to waste any time, I'll examine the Atmega323 port for the WinAVR (AVR-GCC) compiler, since it'll be much closer to our goal of porting to an Atmega2560. The port files can be found under FreeRTOS\Source\portable\GCC\ATMega323/ and the demo project under FreeRTOS\Demo\AVR_ATMega323_WinAVR/. You can make an Eclipse project with the files (it's not ready, as was the Windows port project), but as this is for studies purposes, there is no need. I should just warn you of one thing:


Starting with the pxPortInitialiseStack() in port.c, as the official guide says. This function is responsible for initializing the stack of a task as if it has already been there, so that the context change runs as smoothly as possible. This means some data must be stored in a certain order so that it can be retrieved in the right order later.

StackType_t *pxPortInitialiseStack( 
                    StackType_t *pxTopOfStack, 
                    TaskFunction_t pxCode, 
                    void *pvParameters )

First the types:

  • StackType_t, is defined in portmacro.h as a portSTACK_TYPE, which is defined as a uint8_t. This represents the type of the data that will be stored in the stack (in this case, 1 byte-wide).
  • TaskFunction_t, is the return type that has to be used by the tasks. It's defined, in projdefs.h (Source/include/projdefs.h) as a pointer to a void-type function.
The parameters are: a pointer to the current top of the stack, a pointer to the start of the tasks code and a pointer to a set of parameters. This set of parameters is the same you define when creating the task with xTaskCreate(). 

Now to the code, you'll see the first thing it does is to insert a few values to the start of the stack (0x11, 0x22 and 0x33). I haven't actually found much about it, but since this demo was written a long time ago, I presume it was used before any stack overflow detection mechanism was implemented (a few other Demo projects I checked don't have this). Ok, so after each value is added to the stack, the pxTopOfStack pointer is updated to the next position.

Next, the address to the start of the code (pxCode) is added to the stack (as the address is 16-bit wide, it has to be added in two steps, LSB first). Next, the 32 CPU registers (ATMega323 has 32 general purpose registers, where the last 6 are actually 3 16-bit registers called X, Y and Z [6] page 11) are stored with a few singularities: the global interrupt flag is inserted just after register 0 (see ATMega323's SREG) and the address to the parameters is placed just before the X register (also in two steps, as the pxCode address). In the end, the new pxTopOfStack is returned.

Now let's check the context saving and restoring. Context saving means to save all internal registers of the microcontroller in order to, when a task goes back to running mode, it seems like nothing is changed. For instance, if the task stops in the middle of some calculations, a few values will be stored in the registers and those should be saved so that the calculations can go on. Context restoring means to get all the stored values and put them back to the correspondent register. Those functions (portSAVE_CONTEXT() and portRESTORE_CONTEXT()) are written in assembly and are responsible for saving the registers I described earlier. These two and the pxPortInitialiseStack() must be absolutely synchronized, otherwise the value of one register can end up in another and the tasks will most likely fail.

portSAVE_CONTEXT() uses the following assembly instructions (you can check ATMega323 datasheet page 233 [6] for that):
  • push r?: pushes the value in a register into the stack (the stack pointer is already in the right position)
  • in r?,<REG>: loads the value of an I/O Space Register (<REG>) to a Rx register
    • ps.: addresses 0x3D and 0x3E correspond to the Stack Pointer register addresses
  • cli: disables the global interrupts
  • clr r?: clears the register
  • lds r?,<variable>: load direct from RAM (the value in the <variable> is stored in r?)
  • st x+,r?: store indirect and post increment (the value in the address pointed by the X register is updated with the value in the r? register, then the value of X is incremented)
portRESTORE_CONTEXT():
  • ld r?,x+: that's the opposite from "st x+,r?", so the value addressed by the X register is stored in r?, then the value of X is incremented
  • out <REG>,r?: the opposite of "in r?,<REG>" (this time, the Stack Pointer registers are referenced by its names __SP_L__ and __SP_H__)
  • pop r?: pops a value from the stack to the register.
Ok, but when are these functions used? One time is when the task yields manually (i.e. calls vPortYield(), that, if you follow the defines, is the implementation of taskYIELD()). When the task is manually yielded, it has its context saved (a call to portSAVE_CONTEXT()), then the context is changed to the next task to run (you can check the vTaskSwitchContext() in tasks.c) and then the context of the new task is restored (a call to portSAVE_CONTEXT()). Another place those functions are used is when a Tick occurs and another task must take place (vPortYieldFromTick(): the process is the same I described, with the difference that the Tick count is incremented).

Another port function is configuring the timer to generate the tick (prvSetupTimerInterrupt()). This is very architecture specific, since the internal registers should be configured such as an event occurs at the Tick Rate. For ATMega323, the Timer 1 is used in Output Compare mode, the counter is reset after an interrupt and the prescaler is set to 64. In the end, the interrupt is enabled (it will actually only be enabled when the global interrupt flag is set). The interrupt routine is also defined in port.c and has two options: when the scheduler is preemptive (the scheduler stops the current task to other take place), vPortYieldFromTick() is called; when the scheduler is set to cooperative (each task has to yield itself), only the Tick Count is incremented.

Last, but not least, the xPortStartScheduler() function, as the name says, will start the scheduler. First, it calls the prvSetupTimerInterrupt() described above, then, restores the context (portRESTORE_CONTEXT()), which will configure the microcontroller to run the task pointed by pxCurrentTCB. In the end, there is a asm call to "RET", which is a subroutine return and all it does is put the next data in the Stack in the Program Counter (PC), which, if you remember from the pxPortInitialiseStack(), was the pxCode parameter, which is the address where the task code starts (it is added before any register is added to the stack, as it would happen when the Tick Interrupt happens - the point where the code stopped is saved to the stack, then the context is saved, starting from register r0).

As a final observation in this file, I just talk a little about the attributes signal and naked, that we see in some function definitions (at least I didn't know they even exist), such as interruptions. These are directives to the compiler change the way it builds its output. The signal attribute ensures that the compiler inserts code that will save and restore every register that has been used in the interruption code and that the return will be done by a "RETI" instruction instead of the original "RET", as the first will re-enable the interruptions on exit [7]. The naked attribute ensures that the compiler won't add any code to the start and end of the interrupt function, which means nothing will be saved nor restored and this will all be user's responsibility. This is specially useful when the Tick interrupt with preemptive scheduler occurs, since the context switch is done there. Without the attribute, a few registers would be saved to the stack, then the current context saved (causing the registers to be saved twice in the stack), the task context is changed, the new task's context is restored and finally the code produced by the compiler would restore the registers saved, losing the tasks context. Also, when naked is used, the return method ("RETI") must be explicitly declared.

ATMega323 portmacro.h

The portmacro.h contains a few definitions of variable types that are highly architecture dependent such as the portLONG, portSHORT, portSTACK_TYPE, portBASE_TYPE, etc. A few macros are also defined here, such as those for critical code management (you need to disable interruptions): portENTER_CRITICAL() first saves the Status Register, then disables the global interruption flag (even if it was already disabled) and pushes the saved Status Register to the stack; the portEXIT_CRITICAL() pops the saved Status Register from the stack and restores it (there is no need to re-enable the global interruption flag, since it is part of the Status Register). The portSTACK_GROWTH is defined according to the datasheet [6], page 22, where it says
"The Stack Pointer is decremented by one when data is pushed onto the Stack with the PUSH instruction (...)"
thus the portSTACK_GROWTH is defined as -1.



[1] http://www.freertos.org/a00104.html
[2] http://www.freertos.org/FreeRTOS-Plus/
[3] http://winavr.sourceforge.net/
[4] http://www.freertos.org/a00090.html
[5] http://www.freertos.org/FreeRTOS-porting-guide.html
[6] http://www.atmel.com/Images/doc1457.pdf
[7] http://www.freertos.org/implementation/a00012.html

Thursday, April 7, 2016

Memory Management - Heap? Stack Overflow?

Memory Management

Every new task created will require some RAM memory to be allocated by the RTOS kernel (both for the task control and for the task's stack) in a heap (basically an area in the memory known by kernel where everything is stored). The same happens to every queue, mutex, semaphore, etc. When some of those are deleted, the memory should (must?) be freed. In a common OS, with no time restrictions, this is performed by using malloc() and free(). The problem is that these commands are usually non deterministic (the time spent can vary), may take a lot of unnecessary code space, are not thread safe and can just not be available in the system. To solve these problems, the memory management algorithm is allowed to be written by the user, which means this is located rather than in the core code of the FreeRTOS, but in the portable layer. Instead of calling malloc() and free(), the kernel will call pvPortMalloc() and pvPortFree().


Nevertheless, FreeRTOS includes 5 sample implementations of the memory management unit that can be used. These are called "heap_*" and each has its own source file located in Source/Portable/MemMang (the Full Demo only uses the heap_5.c). Other implementations may be added and used, but one of those samples must be included in your project (the RTOS kernel will use it, even though the application uses another one). The 5 sample implementations are describe below.
  • heap_1.c: this is the simplest one and doesn't permit memory to be freed. This is used a lot, as lots of applications creates and initializes all the tasks, queues, semaphores, etc, at system boot and never delete them. The implementation simply divides an array as RAM is requested (the size of this "array", which is actually the size of the heap, is defined in FreeRTOSConfig.h as configTOTAL_HEAP_SIZE). The API function xPortGetFreeHeapSize() may be used to optimize this value. [1]
  • heap_2.c: this is similar to heap_1, but allow freeing memory. To keep it simple, there is no de-fragmentation algorithm, which means that adjacent free blocks aren't combined in one larger block (this is done in heap_4, it's called coalescence algorithm). This implementation should be used if the amount of memory freed and "malloced" are always the same, i.e., the tasks's stacks are always the same size or the amount of queue storage is always the same, otherwise, the memory may become fragmented into small blocks and future allocations may fail. configTOTAL_HEAP_SIZE controls the size of the heap. [2]
  • heap_3.c: just implements a wrapper so that the compiler library's free() and malloc() implementation are used. It just makes those functions thread safe. Beware that this implementation is not deterministic and will probably increase the kernel code size. configTOTAL_HEAP_SIZE has no effect. [3]
  • heap_4.c: works similar to heap_2, but implements a coalescence algorithm (combines adjacent free memory blocks into one larger block). This is quite useful when the application needs to allocate memory by itself (by the use of pvPortMalloc() and pvPortFree()), instead of using an API for that. If necessary, the heap can be located in a specific location (address) by setting the option configAPPLICATION_ALLOCATED_HEAP in FreeRTOSConfig.h and explicitly declaring the ucHeap[ configTOTAL_HEAP_SIZE  ] array (more details on [4]).
  • heap_5.c: implements all that heap_4 does, plus allows heap to be formed by several different sized blocks in RAM, instead of one contiguous huge block (i.e., one block starts at address A, with size X, the next starts at address B, with size Y, and so on). The heap is initialized by calling vPortDefineHeapRegions(), which takes as parameter a structure that describes it. Nothing can use the heap before this functions is executed. As Full Demo uses the heap_5, it has to call the function (you can check under prvInitialiseHeap() in main.c). More details can be seen in the official webpage [5].
A few tricks can be used when talking about the heap management. In systems where there is an external, slower, RAM, using two implementations at once allows task stacks and other RTOS objects to be placed in the fast internal RAM, while application data can be placed in the external one.

Stack Usage - Stack Overflow

The task stack is managed by the task itself, which has to be kept within the size determined at creation time (when xTaskCreate() is called). Sometimes, the task tries to use more memory than is available, which causes a popular problem, a common reason for the system's instability: a Stack Overflow.
To ease the debugging of this problem, FreeRTOS offers two mechanisms to check for stack overflow and call a function (hook) if that happens. The configCHECK_FOR_STACK_OVERFLOW, in FreeRTOSConfig.h, chooses between the two methods and, if one of the methods is chosen, a hook function must be provided (vApplicationStackOverflowHook()).

  • Method 1 (configCHECK_FOR_STACK_OVERFLOW set to 1): the stack pointer is checked whenever the task is swept out of the running state. If the pointer is out of boundaries, the hook is called.
  • Method 1 and 2 (configCHECK_FOR_STACK_OVERFLOW set to 2): the task's stack is filled with known values when the task is first created. Whenever the task is swept out of the running state, the last 16 bytes are check and, if any of those are not as predicted, the hook is called. This method can only be used in conjunction to the method 1.


[1] http://www.freertos.org/a00111.html#heap_1
[2] http://www.freertos.org/a00111.html#heap_2
[3] http://www.freertos.org/a00111.html#heap_3
[4] http://www.freertos.org/a00111.html#heap_4
[5] http://www.freertos.org/a00111.html#heap_5

Wednesday, March 30, 2016

Full demo - FreeRTOSConfig.h

This file is a big deal. Each application should have its own (application, not port) and that's where much of the customization is made. It is mostly comprised of definitions which turn ON or OFF some feature (usually a kernel's feature) that you need in your application. Remember those definitions started with "config", such as configUSE_IDLE_HOOK? In FreeRTOSConfig.h you will find, young Padawan. In this post I'll list and explain briefly all those you will find in the Full Demo for Windows. More detailed info can be found in FreeRTOS' website [1].

  • configUSE_PREEMPTION: this chooses the scheduler, whether preemptive or cooperative. Preemptive scheduling means the task will be stopped in order to other task take place on the processor. Cooperative scheduling will patiently wait until the task kindly leaves the processor (either if its execution finished or it went to sleep, etc).
  • configUSE_PORT_OPTIMISED_TASK_SELECTION: there is usually two kinds of task selection, a generic one, which was written in C and can be used in any port, or an optimized one, usually written in the port's specific assembly and optimized to the port. The generic doesn't have a limit in the amount of priorities for the task, while the optimized is usually limited to 32.
  • configUSE_IDLE_HOOK: this chooses whether the Idle Hook will be used or not.
  • configUSE_TICK_HOOK: this chooses whether the Tick Hook will be used or not.
  • configTICK_RATE_HZ: this is the frequency of the tick interrupt, when the task is stopped to make place to another one (or maybe not). Care must be taken when you choose this value, as the higher the frequency, the more the overhead caused by the context switching will matter. For all the demo projects, it's set to 1000 Hz, and that's a good starting number.
  • configMINIMAL_STACK_SIZE: this is the size of the stack used by the Idle Task and shoul not differ from the one specified on the demo project of the port you're using. It is specified in words, as in the xTaskCreate() function, thus, if your microcontroller/microprocessor uses a 32-bit (4 bytes) wide stack, a stack of 50 words will mean 200 bytes.
  • configTOTAL_HEAP_SIZE: total amount of RAM available to the RTOS kernel. This is only used in certain cases of memory management [2] and I'll discuss that soon.
  • configMAX_TASK_NAME_LEN: the maximum length of the task's descriptive name (the one you write on xTaskCreate()), including the ending NULL char.
  • configUSE_TRACE_FACILITY: enables a few more trace capabilities, in order to assist with execution visualization.
  • configUSE_16_BIT_TICKS: this specifies the size of the variable that counts the ticks. If the config is set, the type (TickType_t) will bean unsigned 16-bit, other wise, it will be 32-bit wide. With a tick rate of 1 kHz and a 16-bit counter, the max amount of time that can be counted is 65535 ticks or 65.535 seconds, instead of 2^32 (4294967296) ticks or around 1193 hours. 8 and 16-bit ports can benefit a lot when setting this option, since the overhead of treating a 32-bi variable can be high.
  • configIDLE_SHOULD_YIELD: if the preemption is being used and there are user tasks with Idle priority, this option tells the idle function to Yield whenever there is another task with the same priority ready to be executed. This means the Idle task will let another task take the remaining time it had (which will be less than one tick). This can lead to a task having less execution time than others with the same priority (imagine tasks A, B and C, where A is always executed when the idle task yields, while B and C take full Ticks), which can be prevented by increasing the other tasks priority.
  • configUSE_MUTEXES: enables Mutex capabilities (check Generic Queue Tasks).
  • configCHECK_FOR_STACK_OVERFLOW: chooses between not using a stack overflow control (set to 0) and two methods of checking (options 1 and 2). It will be discussed soon, but what you should know by now is that, if the config != 0, then you should have a Stack Overflow Hook.
  • configUSE_RECURSIVE_MUTEXES: enables Recursive Mutex capabilities (check Recursive Mutex Tasks).
  • configQUEUE_REGISTRY_SIZE: defines the maximum number of queues and semaphores that can be registered for easier debugging. It only makes sense when using a RTOS kernel aware debugger.
  • configUSE_MALLOC_FAILED_HOOK: enables the Malloc Failed Hook function (vApplicationMallocFailedHook()), which will be called whenever the pvPortMalloc() function returns NULL, which means there were not enough memory left on the heap for the allocation.
  • configUSE_APPLICATION_TASK_TAG: enables the function vTaskSetApplicationTaskTag(), which will allow a tag value (or function) to be assigned to a task. This functionality is used for tracing purposes and an example can be studied here.
  • configUSE_COUNTING_SEMAPHORES: enables Counting Semaphores capabilities (check Counting Semaphore Tasks).
  • configUSE_ALTERNATIVE_API: enables the alternative queue API described in queue.h header. Should not be used as is deprecated (although is set on the Full Demo).
  • configUSE_QUEUE_SETS: enables the Queue Sets functionality (check Queue Set Tasks).
  • configUSE_TASK_NOTIFICATIONS: enables the Direct to Task Notification API (each task will consume 8 more bytes). See Notify Task.
  • configUSE_TIMERS: enables the Software Timers. See Timer Demo Tasks.
  • configTIMER_TASK_PRIORITY: sets the priority of the software timer task. Maybe later I'll go more into that.
  • configTIMER_QUEUE_LENGTH: sets the length of the software timer command queue (the maximum number of unprocessed requests).
  • configTIMER_TASK_STACK_DEPTH: sets the size (in Words) of the stack of the software timer task. Depends highly on the timer callback functions, as the context where the calls are made is the timer service task.
  • configMAX_PRIORITIES: sets the number of priorities available. The higher this number, the higher the amount of RAM spent, so should be kept as low as needed.
  • ulGetRunTimeCounterValue( void ): this is the prototype for a Run Time statistics function. This one, as the name intends, will return the time since the application started.
  • vConfigureTimerForRunTimeStats( void ): initializes the Run Time Statistics.
  • configGENERATE_RUN_TIME_STATS: enables the Run Time Statistics. When this is enabled, the two next macros have to be defined.
  • portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(): this is a macro to a function (in this case, vConfigureTimerForRunTimeStats()) that will initialize a higher resolution (higher than the tick rate usually by 10 to 100 times) timer. The function is usually port specific (the Full Demo for Windows uses the Windows API for that, but a microcontroller may use a hardware timer).
  • portGET_RUN_TIME_COUNTER_VALUE(): this is a macro to a function (in this case, ulGetRunTimeCounterValue()) that will return the current time. The function is also usually port specific, as is the initialization described above.
  • configUSE_CO_ROUTINES: enables co-routine functionality. Even though it is set on the Full Demo, I couldn't find where these co-routines were used. Maybe I'll write another post explaining them, although it should be discontinued in FreeRTOS [3].
  • configMAX_CO_ROUTINE_PRIORITIES: the maximum number of co-routines priorities, similar to configMAX_PRIORITIES.
  • configUSE_STATS_FORMATTING_FUNCTIONS: enables some functions for trace capabilities. If this and configUSE_TRACE_FACILITY are set, vTaskList() and vTaskGetRunTimeStats() may be used.
  • INCLUDE_xxxxxx: these macros force the insertion (or not) of some functions, even though the unused are usually no inserted by the linker.
  • AssertCalled( unsigned long ulLine, const char * const pcFileName );: prototype of the function called by configASSERT(). Check configASSERT().
  • configASSERT( x ): macro that calls the function described above. Check configASSERT().
  • TRACE_ENTER_CRITICAL_SECTION() and TRACE_EXIT_CRITICAL_SECTION(): macros for the entering and existing critical sections, used in trace. The functions are port specific. Check the official FreeRTOS+ Trace docs [4].
  • "trcKernelPort.h": header file for the trace capabilities. Check the official FreeRTOS+ Trace docs [4].
Well, those are all of the options included on the FreeRTOSConfig.h in our Full Demo application. The FreeRTOS website brings a few more options that were left out:
  • configUSE_TICKLESS_IDLE: this is used to enhance the low power capabilities by allowing the application to disable the ticks interruptions and sleep, if there is nothing else to be done (all tasks are blocked or suspended). It can be set to 1, in order to use a port specific implementation of tickless idle, or to 2, to use the generic implementation. More information may be checked on the FreeRTOS specific web page [5].
  • configCPU_CLOCK_HZ: sets the frequency, in Hertz (Hz), of the internal clock of the peripheral that generates the Tick interrupts runs (usually the same as the CPU clock). This parameter is used to correctly configure the timer peripherals.
  • configUSE_TIME_SLICING: when set to 0, the scheduler will let tasks with the same period to run until it wants to stop (may be blocked or suspended). If not set (the default option) or set to 1, the scheduler will change the running task among others with the same priority every Tick.
  • configUSE_NEWLIB_REENTRANT: if set to 1, a newlib reent structure will be allocated for each task created. Any newlib functionalities are not maintained by the FreeRTOS crew. More about that on newlib's website [6].
  • configENABLE_BACKWARD_COMPATIBILITY: this enables the use of older (FreeRTOS pre 8.0.0) structure names.
  • configNUM_THREAD_LOCAL_STORAGE_POINTERS: this set the amount of Thread Local Storage (TLS) pointer. In a multi threaded application, TLS is used to substitute a global variable, as it will be stored inside the task's control block (imagine each task wanted to have an error number variable, commonly called "errno", available to every other task) [7].
  • configKERNEL_INTERRUPT_PRIORITYconfigMAX_SYSCALL_INTERRUPT_PRIORITY and configMAX_API_CALL_INTERRUPT_PRIORITY: those options are used to set some interrupts priorities. configMAX_SYSCALL* and configMAX_API_CALL* are equivalent (the later is the new name). Together, the two options can be set in order to some specific interrupt allow the kernel itself to be stoped (maybe some emergency interrupt that has to be processed as soon as it happens). Check the official documentation for more info [8].
  • configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS: this allows the user to create privileged functions (defined and implemented inside the application_defined_privileged_functions.h file). This means the task will be able to access anything in the application (even memory outside the task's context). Check the example in FreeRTOS specific page [9].
  • configAPPLICATION_ALLOCATED_HEAP: when set, allows the heap to be positioned in a specific location [10].

Uff, that was a lot. See you soon!


[1] http://www.freertos.org/a00110.html
[2] http://www.freertos.org/a00111.html
[3] http://www.freertos.org/taskandcr.html
[4] http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_Trace/RTOS_Trace_Instructions.shtml
[5] http://www.freertos.org/low-power-tickless-rtos.html
[6] http://sourceware.org/newlib/
[7] http://www.freertos.org/thread-local-storage-pointers.html
[8] http://www.freertos.org/a00110.html#kernel_priority
[9] http://www.freertos.org/a00110.html#configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS
[10] http://www.freertos.org/a00111.html#heap_4

Tuesday, February 23, 2016

Full demo - part 2

Well, a few things left unsaid. 


The Check Task

This is there to ensure everything is going as expected. It will run every 2.5 seconds asking each and every set of tasks described in the last post whether they're working fine and will print a "OK" message if so (that's the OK message you saw the first time you run the main_full program).
Each set of tasks has a "xAre*********TasksStillRunning()", which is implemented close to the tasks code and will return a value informing whether or not the functionality tested is ok. You'll notice the order of the tasks is different here from the part 1, but that's how it was implemented.
  • Timer Demo Tasks: xAreTimerDemoTasksStillRunning(), as each successful test of the Software Timer increments a counter, this function tests whether this value has changed, thus all is running fine.
  • Notify Task: xAreTaskNotificationTasksStillRunning(), as the functions and tasks increment counters whenever a notification is taken and given, this test will check whether the counting is changing and if every notification given is taken.
  • Interrupt Semaphores Tasks: xAreInterruptSemaphoreTasksStillRunning(), checks whether the counting semaphores are still working and the master is still running.
  • Event Group Tasks: xAreEventGroupTasksStillRunning(), checks whether the master and slave are still running and the ISR calls are ok.
  • Integer Math Tasks: xAreIntegerMathsTaskStillRunning(), checks whether the answer from the calculations keep being correct all the time.
  • Generic Queue Tasks: xAreGenericQueueTasksStillRunning(), check if the queues and mutexes keep on going well.
  • Queue Peek Tasks: xAreQueuePeekTasksStillRunning(), checks if the queue keeps on being peeked.
  • Blocking Queue Tasks: xAreBlockingQueuesStillRunning(), checks whether all the consumers and producers keep on consuming and producing.
  • Semaphore Tasks: xAreSemaphoreTasksStillRunning(), check if the sempahores are being taken and given.
  • Polled Queue TasksxArePollingQueuesStillRunning(), checks if the producer keeps producing and the consumer keeps consuming to and from the queue.
  • Math Tasks: xAreMathsTaskStillRunning(), same as integer math tasks, but this time there are more tasks testing the floating point operations.
  • Recursive Mutex Tasks: xAreRecursiveMutexTasksStillRunning(), checks if the controlling, blocking and polling tasks keep on running.
  • Counting Semaphore Tasks: xAreCountingSemaphoreTasksStillRunning(), checks if the semaphores keep on being incremented and decremented.
  • Suicidal Tasks: xIsCreateTaskStillRunning(), checks if the creator is still alive and creating and if no more than 4 extra tasks (besides all the other tasks that were created in this project) are created.
  • Dynamic Priority Tasks: xAreDynamicPriorityTasksStillRunning(), checks if everything is still running.
  • Queue Set Tasks: xAreQueueSetTasksStillRunning(), checks if all tasks are still running, if all queues are being used and if the ISR function is still sending values to the queues.
  • Queue Overwrite Tasks: xIsQueueOverwriteTaskStillRunning(), checks if the task and the ISR function are still working.
  • Queue Space Task: (not tested).

Idle Task/Hook

The Idle Hook is a function that runs every time the Idle Task runs, if configUSE_IDLE_HOOK is set to 1. The function, in this case, is defined in main.c (vApplicationIdleHook()) and only has a call to vFullDemoIdleFunction() (defined in main_full.c). It is used to demonstrate how one can use the Idle Hook to do something. 
The first thing it does is to sleep (15ms) just to allow any task that could have been terminated by the idle task to actually terminate. 
Then there are a few demonstrations (prvDemonstrateTaskStateAndHandleGetFunctions()), such as get the idle task handle (should be equal to the idle hook's handle) and the timer daemon handle. It also creates a test task (prvTestTask(), it doesn't actually do anything) to show what could be done with its handle (get its state, suspend, delete). This only happens once while the application is running.
Then there is a demonstration of pending a function call (prvDemonstratePendingFunctionCall()), that is, having the RTOS daemon task (timer service task) call some function (xTimerPendFunctionCall()).
Then, a mutex, created in main_full() function just to this purpose, is deleted to demonstrate the usage of  vSemaphoreDelete().
In the end, a test to heap_5.c is performed, by malloc'ing a random size void variable and freeing it.


Tick Task/Hook

Similar to the Idle Hook, the Tick Hook is a piece of code called whenever a Tick happens (defined in configTICK_RATE_HZ, in FreeRTOSConfig.h), if configUSE_IDLE_HOOK is set to 1. The function is defined in main.c (vApplicationTickHook()) and only performs the call to vFullDemoTickHookFunction(), defined in main_full.c. This is where most (maybe all?) the ISR functions described in part 1 are called, such as vTimerPeriodicISRTests(), from Timer Demo Tasks, xNotifyTaskFromISR() and vQueueSetAccessQueueSetFromISR().

Other Hooks

There are two other hooks defined: vApplicationMallocFailedHook(), which runs if configUSE_MALLOC_FAILED_HOOK is set to 1 and when a malloc (pvPortMalloc()) fails, and vApplicationStackOverflowHook(), which runs if configCHECK_FOR_STACK_OVERFLOW is set to 1 or 2 (which is not) and when (can you guess?) a stack overflow is detected.

On the next post, I'll talk about the FreeRTOSConfig.h, which I mentioned a few times here and there, but never gone further. See you soon!