FreeRTOS for ATMega644

August 10, 2008 – 5:19 pm

six-legged chip bug

FreeRTOS is an open-source realtime operating system for microcontrollers. The ATMega644 of ATMEL provides 64KB of flash program memory in a DIY-friendly 40-pin PDIP package. Read on for how to combine both to my new software development platform.

FreeRTOS provides a nice RTOS for embedded systems and is readily available for various platforms. One timer of the hardware is used to implement multitasking features. A library provides routines for creating tasks and synchronization. Unfortunately, FreeRTOS is currently only ported to the ATMega323 - so I created a basic port to the ATMega644 and stripped all unnecessary features.

Typically, the FreeRTOS demo shows how to implement various threads and let them access the hardware. While it is educating to read the code, it is too bloated to serve as a template for new developments. In addition, I prefer Peter Fleury’s UART library for serial outputs. So, I removed all threads and included the library. To make sure that two threads cannot write to the same UART at the same time, I introduced a mutex per UART to synchronize the output on a per-string basis. Please note that there is no Mutex to synchronize read access. The main program starts two tasks which print “foo” and “bar” to the serial line, respectively. I kept the task surveilance mechanism as implemented in the original FreeRTOS demo (this might become handy ;-))

Here is a peek at the main.c file:

/* Based on FreeRTOS Demo main (AVR-GCC Port). */

#include <stdlib.h>
#include <string.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

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

#include "status.h"
#include "uart.h"

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

/* Baud rate used by the serial port tasks. */
#define UART_BAUD_RATE                  ( ( unsigned portLONG ) 9600 )

/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 16000000UL
#endif

/* LED that is toggled by the check task.  The check task periodically checks
that all the other tasks are operating without error.  If no errors are found
the LED is toggled.  If an error is found at any time the LED is never toggles
again. */
#define mainCHECK_TASK_LED                              ( 7 )

/* The period between executions of the check task. */
#define mainCHECK_PERIOD                                ( ( portTickType ) 3000 / portTICK_RATE_MS  )

/*
 * Function prototypes, see below.
 */
static void serialWriter( void *pvParameters );
static void vErrorChecks( void *pvParameters );
static void prvCheckOtherTasksAreStillRunning( void );
void vApplicationIdleHook( void );

/*
 * status variables.
 */
static portBASE_TYPE serialWriterStatus = pdTRUE;

portSHORT main( void ) {
  /* Setup the LED's for output. */
  statusInitialize();
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
  sei();

  /* Create the tasks defined within this file. */
  xTaskCreate( vErrorChecks, ( signed portCHAR * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
  xTaskCreate( serialWriter, ( signed portCHAR * ) "Foo", configMINIMAL_STACK_SIZE, "foo", mainCHECK_TASK_PRIORITY, NULL );
  xTaskCreate( serialWriter, ( signed portCHAR * ) "Bar", configMINIMAL_STACK_SIZE, "bar", mainCHECK_TASK_PRIORITY, NULL );
  uart_puts_P("\r\nFreeRTOS template initialized.");

  vTaskStartScheduler();
  return 0;
}

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

  /* Cycle for ever, delaying then checking all the other tasks are still
     operating without error. */
  for( ;; ) {
    vTaskDelay( mainCHECK_PERIOD );
    prvCheckOtherTasksAreStillRunning();
  }
}

static void serialWriter( void *pvParameters ) {
  char* message = pvParameters;
  for (;;) {
        vTaskDelay((portTickType) 100/portTICK_RATE_MS);
        /* Notify a single error. */
        if (uart_puts_P("\r\n") != pdTRUE)
          serialWriterStatus = pdFALSE;
        if (uart_puts(message) != pdTRUE)
          serialWriterStatus = pdFALSE;
  }
}

static void prvCheckOtherTasksAreStillRunning( void ) {
  static portBASE_TYPE xErrorHasOccurred = pdFALSE;
  if( serialWriterStatus != pdTRUE ) {
    xErrorHasOccurred = pdTRUE;
  }

  if( xErrorHasOccurred == pdFALSE ) {
    /* Toggle the LED if everything is okay so we know if an error occurs even if not
       using console IO. */
    statusToggleLED( mainCHECK_TASK_LED );
    uart_puts_P("\r\nAll tasks working.");
  }
}

void vApplicationIdleHook( void ) {
  vCoRoutineSchedule();
}

HTML code generated by vim-color-improved v.0.4.0.Download this code: freertos-atmega644-main.c

You can get the whole package (GPL licensed) from the download page. Have fun! Kudos for the CC’ed chip bug picture go to oskay.

Related posts

Tags: , , ,

  1. 1 Trackback(s)

  2. Aug 14, 2008: Recent Links Tagged With "gcc" - JabberTags

Post a Comment