jmr1972 wrote on Thursday, December 06, 2007:
Guys,
I started off with the ATMega323_WinAVR port and fixed up the various parts that didn’t compile at first for the ATMega640.
Below is my config.h, port.c and main.c files Note I’ve stripped it to the bare minimum (I want to check that my timer interrupt works before I get into debugging my application (I’m and adept of the KISS method
)
JMR
FreeRTOSconfig.h:
------8<-----------------------8<-----------------------------------------------------
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include <avr/io.h>
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE ‘CONFIGURATION’ SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned portLONG ) 11059200 )
#define configTICK_RATE_HZ ( ( portTickType ) 20 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 4 )
#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 85 )
#define configTOTAL_HEAP_SIZE ( (size_t ) ( 2500 ) )
#define configMAX_TASK_NAME_LEN ( 8 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 1
#define configIDLE_SHOULD_YIELD 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#endif /* FREERTOS_CONFIG_H */
------8<-----------------------8<-----------------------------------------------------
port.c:
------8<-----------------------8<-----------------------------------------------------
#include <stdlib.h>
#include <avr/interrupt.h>
#include "FreeRTOS.h"
#include "task.h"
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the AVR port.
*----------------------------------------------------------*/
/* Start tasks with interrupts enables. */
#define portFLAGS_INT_ENABLED ( ( portSTACK_TYPE ) 0x80 )
/* Hardware constants for timer 1. */
#define portCLEAR_COUNTER_ON_MATCH ( ( unsigned portCHAR ) 0x08 )
#define portPRESCALE_64 ( ( unsigned portCHAR ) 0x03 )
#define portCLOCK_PRESCALER ( ( unsigned portLONG ) 0x64 )
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( unsigned portCHAR ) 0x02 )
------8<-----------------------8<-----------------------------------------------------
Cut out the various macros and functions as they haven’t changed…
------8<-----------------------8<-----------------------------------------------------
/*
* Setup timer 1 compare match A to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt( void )
{
unsigned portLONG ulCompareMatch;
unsigned portCHAR 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 -= ( unsigned portLONG ) 1;
/* Setup compare match value for compare match A. Interrupts are disabled
before this is called so we need not worry here. */
ucLowByte = ( unsigned portCHAR ) ( ulCompareMatch & ( unsigned portLONG ) 0xff );
ulCompareMatch >>= 8;
ucHighByte = ( unsigned portCHAR ) ( ulCompareMatch & ( unsigned portLONG ) 0xff );
OCR1AH = ucHighByte;
OCR1AL = ucLowByte;
/* Setup clock source and compare match behaviour. */
ucLowByte = portCLEAR_COUNTER_ON_MATCH | 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;
}
/*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 1
/*
* Tick ISR for preemptive scheduler. We can use a naked attribute as
* the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved.
*/
ISR(TIMER1_COMPA_vect)
{
vPortYieldFromTick();
asm volatile ( "reti" );
}
#else
/*
* Tick ISR for the cooperative scheduler. All this does is increment the
* tick count. We don’t need to switch context, this can only be done by
* manual calls to taskYIELD();
*/
ISR(TIMER1_COMPA_vect)
{
vTaskIncrementTick();
}
#endif
------8<-----------------------8<-----------------------------------------------------
main.c:
------8<-----------------------8<-----------------------------------------------------
#include <stdlib.h>
#include <string.h>
#ifdef GCC_MEGA_AVR
/* EEPROM routines used only with the WinAVR compiler. */
#include <avr/eeprom.h>
#endif
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
/* Demo file headers. */
//#include "PollQ.h"
//#include "integer.h"
//#include "serial.h"
//#include "comtest.h"
//#include "crflash.h"
//#include "print.h"
//#include "partest.h"
//#include "regtest.h"
/* Priority definitions for the tasks in the application. */
#define mainRADIO_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainGSM_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainGPS_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainPROTOCOL_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainCONTROL_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
/* Baud rate used by the serial port tasks. */
#define mainCOM_TEST_BAUD_RATE ( ( unsigned portLONG ) 38400 )
/* LED used by the serial port tasks. This is toggled on each character Tx,
and mainCOM_TEST_LED + 1 is toggles on each character Rx. */
#define mainCOM_TEST_LED ( 4 )
/* 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. 5 seconds */
#define mainCONTROL_PERIOD ( ( portTickType ) 5000 / portTICK_RATE_MS )
/* An address in the EEPROM used to count resets. This is used to check that
the demo application is not unexpectedly resetting. */
#define mainRESET_COUNT_ADDRESS ( ( void * ) 0x50 )
/*
* Called on boot to increment a count stored in the EEPROM. This is used to
* ensure the CPU does not reset unexpectedly.
*/
static void prvIncrementResetCount( void );
/*
* The various tasks for the application.
*/
void vRadioTask( void *pvParameters );
void vGSMTask( void *pvParameters );
void vGPSTask( void *pvParameters );
void vProtocolTask( void *pvParameters );
void vControlTask( void *pvParameters );
/*
* The idle hook is used to scheduler co-routines.
*/
void vApplicationIdleHook( void );
/*-----------------------------------------------------------*/
portSHORT main( void )
{
prvIncrementResetCount();
/* Create the tasks defined within this file. */
xTaskCreate( vRadioTask, "Radio", configMINIMAL_STACK_SIZE, NULL, mainRADIO_TASK_PRIORITY, NULL );
xTaskCreate( vGSMTask, "GSM", configMINIMAL_STACK_SIZE, NULL, mainGSM_TASK_PRIORITY, NULL );
xTaskCreate( vGPSTask, "GPS", configMINIMAL_STACK_SIZE, NULL, mainGPS_TASK_PRIORITY, NULL );
xTaskCreate( vProtocolTask, "Proto", configMINIMAL_STACK_SIZE, NULL, mainPROTOCOL_TASK_PRIORITY, NULL );
xTaskCreate( vControlTask, "Control", configMINIMAL_STACK_SIZE, NULL, mainCONTROL_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 prvIncrementResetCount( void )
{
unsigned portCHAR ucCount;
eeprom_read_block( &ucCount, mainRESET_COUNT_ADDRESS, sizeof( ucCount ) );
ucCount++;
eeprom_write_byte( mainRESET_COUNT_ADDRESS, ucCount );
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook( void )
{
/* Do some background checks */
}
void vRadioTask( void *pvParameters )
{
volatile long cnt = 0;
for(;
{
cnt += 1;
}
}
void vGSMTask( void *pvParameters )
{
volatile long cnt = 0;
for(;
{
cnt += 1;
}
}
void vGPSTask( void *pvParameters )
{
volatile long cnt = 0;
for(;
{
cnt += 1;
}
}
void vProtocolTask( void *pvParameters )
{
volatile long cnt = 0;
for(;
{
cnt += 1;
}
}
void vControlTask( void *pvParameters )
{
volatile long cnt = 0;
for(;
{
cnt += 1;
}
}