You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
585 lines
17 KiB
C
585 lines
17 KiB
C
/*
|
|
FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
|
|
|
|
|
|
***************************************************************************
|
|
* *
|
|
* FreeRTOS tutorial books are available in pdf and paperback. *
|
|
* Complete, revised, and edited pdf reference manuals are also *
|
|
* available. *
|
|
* *
|
|
* Purchasing FreeRTOS documentation will not only help you, by *
|
|
* ensuring you get running as quickly as possible and with an *
|
|
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
|
* the FreeRTOS project to continue with its mission of providing *
|
|
* professional grade, cross platform, de facto standard solutions *
|
|
* for microcontrollers - completely free of charge! *
|
|
* *
|
|
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
|
* *
|
|
* Thank you for using FreeRTOS, and thank you for your support! *
|
|
* *
|
|
***************************************************************************
|
|
|
|
|
|
This file is part of the FreeRTOS distribution.
|
|
|
|
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License (version 2) as published by the
|
|
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
|
>>>NOTE<<< The modification to the GPL is included to allow you to
|
|
distribute a combined work that includes FreeRTOS without being obliged to
|
|
provide the source code for proprietary components outside of the FreeRTOS
|
|
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
more details. You should have received a copy of the GNU General Public
|
|
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
|
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
|
by writing to Richard Barry, contact details for whom are available on the
|
|
FreeRTOS WEB site.
|
|
|
|
1 tab == 4 spaces!
|
|
|
|
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
contact details.
|
|
|
|
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
critical systems.
|
|
|
|
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
licensing and training services.
|
|
*/
|
|
|
|
/*
|
|
* Creates the demo application tasks, then starts the scheduler. The WEB
|
|
* documentation provides more details of the demo application tasks.
|
|
*
|
|
* Main. c also creates four other tasks:
|
|
*
|
|
* 1) vErrorChecks()
|
|
* This only executes every few seconds but has the highest priority so is
|
|
* guaranteed to get processor time. Its main function is to check that all
|
|
* the standard demo application tasks are still operational and have not
|
|
* experienced any errors. vErrorChecks() will toggle the on board LED
|
|
* every mainNO_ERROR_FLASH_PERIOD milliseconds if none of the demo application
|
|
* tasks have reported an error. Should any task report an error at any time
|
|
* the rate at which the on board LED is toggled is increased to
|
|
* mainERROR_FLASH_PERIOD - providing visual feedback that something has gone
|
|
* wrong.
|
|
*
|
|
* 2) vRegisterCheck()
|
|
* This is a very simple task that checks that all the registers are always
|
|
* in their expected state. The task only makes use of the A register, so
|
|
* all the other registers should always contain their initial values.
|
|
* An incorrect value indicates an error in the context switch mechanism.
|
|
* The task operates at the idle priority so will be preempted regularly.
|
|
* Any error will cause the toggle rate of the on board LED to increase to
|
|
* mainERROR_FLASH_PERIOD milliseconds.
|
|
*
|
|
* 3 and 4) vFLOPCheck1() and vFLOPCheck2()
|
|
* These are very basic versions of the standard FLOP tasks. They are good
|
|
* at detecting errors in the context switch mechanism, and also check that
|
|
* the floating point libraries are correctly built to be re-enterant. The
|
|
* stack restrictions of the 8051 prevent the use of the standard FLOP demo
|
|
* tasks.
|
|
*/
|
|
|
|
/* Standard includes. */
|
|
#include <stdlib.h>
|
|
|
|
/* Scheduler includes. */
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
|
|
/* Demo application includes. */
|
|
#include "partest.h"
|
|
#include "flash.h"
|
|
#include "integer.h"
|
|
#include "PollQ.h"
|
|
#include "comtest2.h"
|
|
#include "semtest.h"
|
|
|
|
/* Demo task priorities. */
|
|
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
|
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
#define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
#define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
|
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
#define mainINTEGER_PRIORITY tskIDLE_PRIORITY
|
|
|
|
/* Constants required to disable the watchdog. */
|
|
#define mainDISABLE_BYTE_1 ( ( unsigned char ) 0xde )
|
|
#define mainDISABLE_BYTE_2 ( ( unsigned char ) 0xad )
|
|
|
|
/* Constants to setup and use the on board LED. */
|
|
#define ucLED_BIT ( ( unsigned char ) 0x40 )
|
|
#define mainPORT_1_BIT_6 ( ( unsigned char ) 0x40 )
|
|
#define mainENABLE_CROSS_BAR ( ( unsigned char ) 0x40 )
|
|
|
|
/* Constants to set the clock frequency. */
|
|
#define mainSELECT_INTERNAL_OSC ( ( unsigned char ) 0x80 )
|
|
#define mainDIVIDE_CLOCK_BY_1 ( ( unsigned char ) 0x03 )
|
|
#define mainPLL_USES_INTERNAL_OSC ( ( unsigned char ) 0x04 )
|
|
#define mainFLASH_READ_TIMING ( ( unsigned char ) 0x30 )
|
|
#define mainPLL_POWER_ON ( ( unsigned char ) 0x01 )
|
|
#define mainPLL_NO_PREDIVIDE ( ( unsigned char ) 0x01 )
|
|
#define mainPLL_FILTER ( ( unsigned char ) 0x01 )
|
|
#define mainPLL_MULTIPLICATION ( ( unsigned char ) 0x04 )
|
|
#define mainENABLE_PLL ( ( unsigned char ) 0x02 )
|
|
#define mainPLL_LOCKED ( ( unsigned char ) 0x10 )
|
|
#define mainSELECT_PLL_AS_SOURCE ( ( unsigned char ) 0x02 )
|
|
|
|
/* Toggle rate for the on board LED - which is dependent on whether or not
|
|
an error has been detected. */
|
|
#define mainNO_ERROR_FLASH_PERIOD ( ( portTickType ) 5000 )
|
|
#define mainERROR_FLASH_PERIOD ( ( portTickType ) 250 )
|
|
|
|
/* Baud rate used by the serial port tasks. */
|
|
#define mainCOM_TEST_BAUD_RATE ( ( unsigned long ) 115200 )
|
|
|
|
/* Pass an invalid LED number to the COM test task as we don't want it to flash
|
|
an LED. There are only 8 LEDs (excluding the on board LED) wired in and these
|
|
are all used by the flash tasks. */
|
|
#define mainCOM_TEST_LED ( 200 )
|
|
|
|
/* We want the Cygnal to act as much as possible as a standard 8052. */
|
|
#define mainAUTO_SFR_OFF ( ( unsigned char ) 0 )
|
|
|
|
/* Constants required to setup the IO pins for serial comms. */
|
|
#define mainENABLE_COMS ( ( unsigned char ) 0x04 )
|
|
#define mainCOMS_LINES_TO_PUSH_PULL ( ( unsigned char ) 0x03 )
|
|
|
|
/* Pointer passed as a parameter to vRegisterCheck() just so it has some know
|
|
values to check for in the DPH, DPL and B registers. */
|
|
#define mainDUMMY_POINTER ( ( xdata void * ) 0xabcd )
|
|
|
|
/* Macro that lets vErrorChecks() know that one of the tasks defined in
|
|
main. c has detected an error. A critical region is used around xLatchError
|
|
as it is accessed from vErrorChecks(), which has a higher priority. */
|
|
#define mainLATCH_ERROR() \
|
|
{ \
|
|
portENTER_CRITICAL(); \
|
|
xLatchedError = pdTRUE; \
|
|
portEXIT_CRITICAL(); \
|
|
}
|
|
|
|
/*
|
|
* Setup the Cygnal microcontroller for its fastest operation.
|
|
*/
|
|
static void prvSetupSystemClock( void );
|
|
|
|
/*
|
|
* Setup the peripherals, including the on board LED.
|
|
*/
|
|
static void prvSetupHardware( void );
|
|
|
|
/*
|
|
* Toggle the state of the on board LED.
|
|
*/
|
|
static void prvToggleOnBoardLED( void );
|
|
|
|
/*
|
|
* See comments at the top of the file for details.
|
|
*/
|
|
static void vErrorChecks( void *pvParameters );
|
|
|
|
/*
|
|
* See comments at the top of the file for details.
|
|
*/
|
|
static void vRegisterCheck( void *pvParameters );
|
|
|
|
/*
|
|
* See comments at the top of the file for details.
|
|
*/
|
|
static void vFLOPCheck1( void *pvParameters );
|
|
|
|
/*
|
|
* See comments at the top of the file for details.
|
|
*/
|
|
static void vFLOPCheck2( void *pvParameters );
|
|
|
|
/* File scope variable used to communicate the occurrence of an error between
|
|
tasks. */
|
|
static portBASE_TYPE xLatchedError = pdFALSE;
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* Starts all the other tasks, then starts the scheduler.
|
|
*/
|
|
void main( void )
|
|
{
|
|
/* Initialise the hardware including the system clock and on board
|
|
LED. */
|
|
prvSetupHardware();
|
|
|
|
/* Initialise the port that controls the external LED's utilized by the
|
|
flash tasks. */
|
|
vParTestInitialise();
|
|
|
|
/* Start the used standard demo tasks. */
|
|
vStartLEDFlashTasks( mainLED_TASK_PRIORITY );
|
|
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
|
|
vStartIntegerMathTasks( mainINTEGER_PRIORITY );
|
|
vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );
|
|
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
|
|
|
|
/* Start the tasks defined in this file. The first three never block so
|
|
must not be used with the co-operative scheduler. */
|
|
#if configUSE_PREEMPTION == 1
|
|
{
|
|
xTaskCreate( vRegisterCheck, "RegChck", configMINIMAL_STACK_SIZE, mainDUMMY_POINTER, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );
|
|
xTaskCreate( vFLOPCheck1, "FLOP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );
|
|
xTaskCreate( vFLOPCheck2, "FLOP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );
|
|
}
|
|
#endif
|
|
|
|
xTaskCreate( vErrorChecks, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, ( xTaskHandle * ) NULL );
|
|
|
|
/* Finally kick off the scheduler. This function should never return. */
|
|
vTaskStartScheduler();
|
|
|
|
/* Should never reach here as the tasks will now be executing under control
|
|
of the scheduler. */
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* Setup the hardware prior to using the scheduler. Most of the Cygnal
|
|
* specific initialisation is performed here leaving standard 8052 setup
|
|
* only in the driver code.
|
|
*/
|
|
static void prvSetupHardware( void )
|
|
{
|
|
unsigned char ucOriginalSFRPage;
|
|
|
|
/* Remember the SFR page before it is changed so it can get set back
|
|
before the function exits. */
|
|
ucOriginalSFRPage = SFRPAGE;
|
|
|
|
/* Setup the SFR page to access the config SFR's. */
|
|
SFRPAGE = CONFIG_PAGE;
|
|
|
|
/* Don't allow the microcontroller to automatically switch SFR page, as the
|
|
SFR page is not stored as part of the task context. */
|
|
SFRPGCN = mainAUTO_SFR_OFF;
|
|
|
|
/* Disable the watchdog. */
|
|
WDTCN = mainDISABLE_BYTE_1;
|
|
WDTCN = mainDISABLE_BYTE_2;
|
|
|
|
/* Set the on board LED to push pull. */
|
|
P1MDOUT |= mainPORT_1_BIT_6;
|
|
|
|
/* Setup the cross bar to enable serial comms here as it is not part of the
|
|
standard 8051 setup and therefore is not in the driver code. */
|
|
XBR0 |= mainENABLE_COMS;
|
|
P0MDOUT |= mainCOMS_LINES_TO_PUSH_PULL;
|
|
|
|
/* Enable the cross bar so our hardware setup takes effect. */
|
|
XBR2 = mainENABLE_CROSS_BAR;
|
|
|
|
/* Setup a fast system clock. */
|
|
prvSetupSystemClock();
|
|
|
|
/* Return the SFR page. */
|
|
SFRPAGE = ucOriginalSFRPage;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvSetupSystemClock( void )
|
|
{
|
|
volatile unsigned short usWait;
|
|
const unsigned short usWaitTime = ( unsigned short ) 0x2ff;
|
|
unsigned char ucOriginalSFRPage;
|
|
|
|
/* Remember the SFR page so we can set it back at the end. */
|
|
ucOriginalSFRPage = SFRPAGE;
|
|
SFRPAGE = CONFIG_PAGE;
|
|
|
|
/* Use the internal oscillator set to its fasted frequency. */
|
|
OSCICN = mainSELECT_INTERNAL_OSC | mainDIVIDE_CLOCK_BY_1;
|
|
|
|
/* Ensure the clock is stable. */
|
|
for( usWait = 0; usWait < usWaitTime; usWait++ );
|
|
|
|
/* Setup the clock source for the PLL. */
|
|
PLL0CN &= ~mainPLL_USES_INTERNAL_OSC;
|
|
|
|
/* Change the read timing for the flash ready for the fast clock. */
|
|
SFRPAGE = LEGACY_PAGE;
|
|
FLSCL |= mainFLASH_READ_TIMING;
|
|
|
|
/* Turn on the PLL power. */
|
|
SFRPAGE = CONFIG_PAGE;
|
|
PLL0CN |= mainPLL_POWER_ON;
|
|
|
|
/* Don't predivide the clock. */
|
|
PLL0DIV = mainPLL_NO_PREDIVIDE;
|
|
|
|
/* Set filter for fastest clock. */
|
|
PLL0FLT = mainPLL_FILTER;
|
|
PLL0MUL = mainPLL_MULTIPLICATION;
|
|
|
|
/* Ensure the clock is stable. */
|
|
for( usWait = 0; usWait < usWaitTime; usWait++ );
|
|
|
|
/* Enable the PLL and wait for it to lock. */
|
|
PLL0CN |= mainENABLE_PLL;
|
|
for( usWait = 0; usWait < usWaitTime; usWait++ )
|
|
{
|
|
if( PLL0CN & mainPLL_LOCKED )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Select the PLL as the clock source. */
|
|
CLKSEL |= mainSELECT_PLL_AS_SOURCE;
|
|
|
|
/* Return the SFR back to its original value. */
|
|
SFRPAGE = ucOriginalSFRPage;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvToggleOnBoardLED( void )
|
|
{
|
|
/* If the on board LED is on, turn it off and visa versa. */
|
|
if( P1 & ucLED_BIT )
|
|
{
|
|
P1 &= ~ucLED_BIT;
|
|
}
|
|
else
|
|
{
|
|
P1 |= ucLED_BIT;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* See the documentation at the top of this file.
|
|
*/
|
|
static void vErrorChecks( void *pvParameters )
|
|
{
|
|
portBASE_TYPE xErrorHasOccurred = pdFALSE;
|
|
|
|
/* Just to prevent compiler warnings. */
|
|
( void ) pvParameters;
|
|
|
|
/* Cycle for ever, delaying then checking all the other tasks are still
|
|
operating without error. The delay period depends on whether an error
|
|
has ever been detected. */
|
|
for( ;; )
|
|
{
|
|
if( xLatchedError == pdFALSE )
|
|
{
|
|
/* No errors have been detected so delay for a longer period. The
|
|
on board LED will get toggled every mainNO_ERROR_FLASH_PERIOD ms. */
|
|
vTaskDelay( mainNO_ERROR_FLASH_PERIOD );
|
|
}
|
|
else
|
|
{
|
|
/* We have at some time recognised an error in one of the demo
|
|
application tasks, delay for a shorter period. The on board LED
|
|
will get toggled every mainERROR_FLASH_PERIOD ms. */
|
|
vTaskDelay( mainERROR_FLASH_PERIOD );
|
|
}
|
|
|
|
|
|
|
|
/* Check the demo application tasks for errors. */
|
|
|
|
if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
|
|
{
|
|
xErrorHasOccurred = pdTRUE;
|
|
}
|
|
|
|
if( xArePollingQueuesStillRunning() != pdTRUE )
|
|
{
|
|
xErrorHasOccurred = pdTRUE;
|
|
}
|
|
|
|
if( xAreComTestTasksStillRunning() != pdTRUE )
|
|
{
|
|
xErrorHasOccurred = pdTRUE;
|
|
}
|
|
|
|
if( xAreSemaphoreTasksStillRunning() != pdTRUE )
|
|
{
|
|
xErrorHasOccurred = pdTRUE;
|
|
}
|
|
|
|
/* If an error has occurred, latch it to cause the LED flash rate to
|
|
increase. */
|
|
if( xErrorHasOccurred == pdTRUE )
|
|
{
|
|
xLatchedError = pdTRUE;
|
|
}
|
|
|
|
/* Toggle the LED to indicate the completion of a check cycle. The
|
|
frequency of check cycles is dependent on whether or not we have
|
|
latched an error. */
|
|
prvToggleOnBoardLED();
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* See the documentation at the top of this file. Also see the standard FLOP
|
|
* demo task documentation for the rationale of these tasks.
|
|
*/
|
|
static void vFLOPCheck1( void *pvParameters )
|
|
{
|
|
volatile portFLOAT fVal1, fVal2, fResult;
|
|
|
|
( void ) pvParameters;
|
|
|
|
for( ;; )
|
|
{
|
|
fVal1 = ( portFLOAT ) -1234.5678;
|
|
fVal2 = ( portFLOAT ) 2345.6789;
|
|
|
|
fResult = fVal1 + fVal2;
|
|
if( ( fResult > ( portFLOAT ) 1111.15 ) || ( fResult < ( portFLOAT ) 1111.05 ) )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
fResult = fVal1 / fVal2;
|
|
if( ( fResult > ( portFLOAT ) -0.51 ) || ( fResult < ( portFLOAT ) -0.53 ) )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* See the documentation at the top of this file.
|
|
*/
|
|
static void vFLOPCheck2( void *pvParameters )
|
|
{
|
|
volatile portFLOAT fVal1, fVal2, fResult;
|
|
|
|
( void ) pvParameters;
|
|
|
|
for( ;; )
|
|
{
|
|
fVal1 = ( portFLOAT ) -12340.5678;
|
|
fVal2 = ( portFLOAT ) 23450.6789;
|
|
|
|
fResult = fVal1 + fVal2;
|
|
if( ( fResult > ( portFLOAT ) 11110.15 ) || ( fResult < ( portFLOAT ) 11110.05 ) )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
fResult = fVal1 / -fVal2;
|
|
if( ( fResult > ( portFLOAT ) 0.53 ) || ( fResult < ( portFLOAT ) 0.51 ) )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* See the documentation at the top of this file.
|
|
*/
|
|
static void vRegisterCheck( void *pvParameters )
|
|
{
|
|
( void ) pvParameters;
|
|
|
|
for( ;; )
|
|
{
|
|
if( SP != configSTACK_START )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
_asm
|
|
MOV ACC, ar0
|
|
_endasm;
|
|
|
|
if( ACC != 0 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
_asm
|
|
MOV ACC, ar1
|
|
_endasm;
|
|
|
|
if( ACC != 1 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
_asm
|
|
MOV ACC, ar2
|
|
_endasm;
|
|
|
|
if( ACC != 2 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
_asm
|
|
MOV ACC, ar3
|
|
_endasm;
|
|
|
|
if( ACC != 3 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
_asm
|
|
MOV ACC, ar4
|
|
_endasm;
|
|
|
|
if( ACC != 4 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
_asm
|
|
MOV ACC, ar5
|
|
_endasm;
|
|
|
|
if( ACC != 5 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
_asm
|
|
MOV ACC, ar6
|
|
_endasm;
|
|
|
|
if( ACC != 6 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
_asm
|
|
MOV ACC, ar7
|
|
_endasm;
|
|
|
|
if( ACC != 7 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
if( DPL != 0xcd )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
if( DPH != 0xab )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
|
|
if( B != 0x01 )
|
|
{
|
|
mainLATCH_ERROR();
|
|
}
|
|
}
|
|
}
|
|
|
|
|