/*\r
- FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
\r
\r
FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by:\r
*\r
* The main() Function:\r
* main() creates two demo specific software timers, one demo specific queue,\r
- * and two demo specific tasks. It then creates a whole host of 'standard demo'\r
- * tasks/queues/semaphores, before starting the scheduler. The demo specific\r
- * tasks and timers are described in the comments here. The standard demo\r
- * tasks are described on the FreeRTOS.org web site.\r
+ * and three demo specific tasks. It then creates a whole host of 'standard\r
+ * demo' tasks/queues/semaphores, before starting the scheduler. The demo\r
+ * specific tasks and timers are described in the comments here. The standard\r
+ * demo tasks are described on the FreeRTOS.org web site.\r
*\r
* The standard demo tasks provide no specific functionality. They are\r
* included to both test the FreeRTOS port, and provide examples of how the\r
* the Blocked state every 200 milliseconds, and therefore toggles the LED\r
* every 200 milliseconds.\r
*\r
+ * The Demo Specific OLED Task:\r
+ * The OLED task is a very simple task that just scrolls a message across the\r
+ * OLED. Ideally this would be done in a timer, but the OLED driver accesses\r
+ * the I2C which is time consuming.\r
+ *\r
* The Demo Specific LED Software Timer and the Button Interrupt:\r
* The user button SW1 is configured to generate an interrupt each time it is\r
* pressed. The interrupt service routine switches an LED on, and resets the\r
* Therefore, pressing the user button will turn the LED on, and the LED will\r
* remain on until a full five seconds pass without the button being pressed.\r
*\r
- * The Demo Specific Idle Hook Function:\r
- * The idle hook function demonstrates how to query the amount of FreeRTOS heap\r
- * space that is remaining (see vApplicationIdleHook() defined in this file).\r
- *\r
* The Demo Specific "Check" Callback Function:\r
* This is called each time the 'check' timer expires. The check timer\r
* callback function inspects all the standard demo tasks to see if they are\r
* is ever discovered. The check timer callback toggles the LED defined by\r
* the mainCHECK_LED definition each time it executes. Therefore, if LED\r
* mainCHECK_LED is toggling every three seconds, then no error have been found.\r
- * If LED mainCHECK_LED is toggling every 500ms, then at least one error has\r
+ * If LED mainCHECK_LED is toggling every 500ms, then at least one errors has\r
* been found. The task in which the error was discovered is displayed at the\r
* bottom of the "task stats" page that is served by the embedded web server.\r
*\r
+ * The Demo Specific Idle Hook Function:\r
+ * The idle hook function demonstrates how to query the amount of FreeRTOS heap\r
+ * space that is remaining (see vApplicationIdleHook() defined in this file).\r
+ *\r
* The Web Server Task:\r
* The IP address used by the SmartFusion target is configured by the\r
* definitions configIP_ADDR0 to configIP_ADDR3, which are located in the\r
/* Microsemi drivers/libraries includes. */\r
#include "mss_gpio.h"\r
#include "mss_watchdog.h"\r
-#include "OLED.h"\r
+#include "mss_timer.h"\r
+#include "mss_ace.h"\r
+#include "oled.h"\r
\r
/* Common demo includes. */\r
#include "partest.h"\r
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )\r
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
#define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
+#define mainOLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
\r
\r
/* The period at which the check timer will expire, in ms, provided no errors\r
have been reported by any of the standard demo tasks. */\r
-#define mainCHECK_TIMER_PERIOD_ms ( 3000UL )\r
+#define mainCHECK_TIMER_PERIOD_MS ( 3000UL / portTICK_RATE_MS )\r
+\r
+/* The period at which the OLED timer will expire. Each time it expires, it's\r
+callback function updates the OLED text. */\r
+#define mainOLED_PERIOD_MS ( 75UL / portTICK_RATE_MS )\r
\r
/* The period at which the check timer will expire, in ms, if an error has been\r
-reported in one of the standard demo tasks. */
-#define mainERROR_CHECK_TIMER_PERIOD_ms ( 500UL )\r
+reported in one of the standard demo tasks. */\r
+#define mainERROR_CHECK_TIMER_PERIOD_MS ( 500UL / portTICK_RATE_MS )\r
+\r
+/* The LED will remain on until the button has not been pushed for a full\r
+5000ms. */\r
+#define mainLED_TIMER_PERIOD_MS ( 5000UL / portTICK_RATE_MS )\r
\r
/* A zero block time. */\r
#define mainDONT_BLOCK ( 0UL )\r
static void prvQueueSendTask( void *pvParameters );\r
\r
/*\r
- * The LED timer callback function. This does nothing but switch the red LED \r
+ * The LED timer callback function. This does nothing but switch the red LED\r
* off.\r
*/\r
-static void vLEDTimerCallback( xTimerHandle xTimer );\r
+static void prvLEDTimerCallback( xTimerHandle xTimer );\r
\r
/*\r
- * The check timer callback function, as described at the top of this file.
+ * The check timer callback function, as described at the top of this file.\r
*/\r
-static void vCheckTimerCallback( xTimerHandle xTimer );\r
+static void prvCheckTimerCallback( xTimerHandle xTimer );\r
\r
/*\r
* This is not a 'standard' partest function, so the prototype is not in\r
- * partest.h, and is instead included here.
+ * partest.h, and is instead included here.\r
*/\r
void vParTestSetLEDFromISR( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue );\r
\r
*/\r
extern void vuIP_Task( void *pvParameters );\r
\r
+/*\r
+ * A very simply task that does nothing but scroll the OLED display. Ideally\r
+ * this would be done within a timer, but it accesses the I2C port which is\r
+ * time consuming.\r
+ */\r
+static void prvOLEDTask( void * pvParameters);\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* The queue used by both application specific demo tasks defined in this file. */\r
static xQueueHandle xQueue = NULL;\r
\r
-/* The LED software timer. This uses vLEDTimerCallback() as it's callback\r
+/* The LED software timer. This uses prvLEDTimerCallback() as it's callback\r
function. */\r
static xTimerHandle xLEDTimer = NULL;\r
\r
-/* The check timer. This uses vCheckTimerCallback() as it's callback\r
+/* The check timer. This uses prvCheckTimerCallback() as it's callback\r
function. */\r
static xTimerHandle xCheckTimer = NULL;\r
\r
by the check timer callback. */\r
static const char *pcStatusMessage = NULL;\r
\r
-\r
/*-----------------------------------------------------------*/\r
\r
int main(void)\r
\r
if( xQueue != NULL )\r
{\r
- /* Start the two application specific demo tasks, as described in the\r
+ /* Start the three application specific demo tasks, as described in the\r
comments at the top of this file. */\r
xTaskCreate( prvQueueReceiveTask, ( signed char * ) "Rx", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );\r
xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );\r
+ xTaskCreate( prvOLEDTask, ( signed char * ) "OLED", configMINIMAL_STACK_SIZE, NULL, mainOLED_TASK_PRIORITY, NULL );\r
\r
- /* Create the software timer that is responsible for turning off the LED \r
- if the button is not pushed within 5000ms, as described at the top of \r
+ /* Create the software timer that is responsible for turning off the LED\r
+ if the button is not pushed within 5000ms, as described at the top of\r
this file. */\r
xLEDTimer = xTimerCreate( ( const signed char * ) "LEDTimer", /* A text name, purely to help debugging. */\r
- ( 5000 / portTICK_RATE_MS ), /* The timer period, in this case 5000ms (5s). */\r
+ ( mainLED_TIMER_PERIOD_MS ), /* The timer period, in this case 5000ms (5s). */\r
pdFALSE, /* This is a one shot timer, so xAutoReload is set to pdFALSE. */\r
( void * ) 0, /* The ID is not used, so can be set to anything. */\r
- vLEDTimerCallback /* The callback function that switches the LED off. */\r
+ prvLEDTimerCallback /* The callback function that switches the LED off. */\r
);\r
\r
/* Create the software timer that performs the 'check' functionality,\r
as described at the top of this file. */\r
- xCheckTimer = xTimerCreate( ( const signed char * ) "CheckTimer", /* A text name, purely to help debugging. */\r
- ( mainCHECK_TIMER_PERIOD_ms / portTICK_RATE_MS ),/* The timer period, in this case 3000ms (3s). */\r
- pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */\r
- ( void * ) 0, /* The ID is not used, so can be set to anything. */\r
- vCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */\r
+ xCheckTimer = xTimerCreate( ( const signed char * ) "CheckTimer",/* A text name, purely to help debugging. */\r
+ ( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */\r
+ pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */\r
+ ( void * ) 0, /* The ID is not used, so can be set to anything. */\r
+ prvCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */\r
);\r
\r
/* Create a lot of 'standard demo' tasks. */\r
\r
/* Create the web server task. */\r
xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL );\r
+ \r
+ /* The suicide tasks must be created last, as they need to know how many\r
+ tasks were running prior to their creation in order to ascertain whether\r
+ or not the correct/expected number of tasks are running at any given\r
+ time. */\r
+ vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );\r
\r
/* Start the tasks and timer running. */\r
vTaskStartScheduler();\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void vCheckTimerCallback( xTimerHandle xTimer )\r
+static void prvCheckTimerCallback( xTimerHandle xTimer )\r
{\r
/* Check the standard demo tasks are running without error. Latch the\r
latest reported error in the pcStatusMessage character pointer. */\r
pcStatusMessage = "Error: RecMutex\r\n";\r
}\r
\r
- if( xAreTimerDemoTasksStillRunning( ( mainCHECK_TIMER_PERIOD_ms / portTICK_RATE_MS ) ) != pdTRUE )\r
+ if( xAreTimerDemoTasksStillRunning( ( mainCHECK_TIMER_PERIOD_MS ) ) != pdTRUE )\r
{\r
pcStatusMessage = "Error: TimerDemo";\r
}\r
\r
/* Toggle the check LED to give an indication of the system status. If\r
- the LED toggles every mainCHECK_TIMER_PERIOD_ms milliseconds then\r
+ the LED toggles every mainCHECK_TIMER_PERIOD_MS milliseconds then\r
everything is ok. A faster toggle indicates an error. */\r
vParTestToggleLED( mainCHECK_LED );\r
\r
/* Have any errors been latch in pcStatusMessage? If so, shorten the\r
- period of the check timer to mainERROR_CHECK_TIMER_PERIOD_ms milliseconds.\r
+ period of the check timer to mainERROR_CHECK_TIMER_PERIOD_MS milliseconds.\r
This will result in an increase in the rate at which mainCHECK_LED\r
toggles. */\r
if( pcStatusMessage != NULL )\r
/* This call to xTimerChangePeriod() uses a zero block time. Functions\r
called from inside of a timer callback function must *never* attempt\r
to block. */\r
- xTimerChangePeriod( xCheckTimer, ( mainERROR_CHECK_TIMER_PERIOD_ms / portTICK_RATE_MS ), mainDONT_BLOCK );\r
+ xTimerChangePeriod( xCheckTimer, ( mainERROR_CHECK_TIMER_PERIOD_MS ), mainDONT_BLOCK );\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void vLEDTimerCallback( xTimerHandle xTimer )\r
+static void prvLEDTimerCallback( xTimerHandle xTimer )\r
{\r
/* The timer has expired - so no button pushes have occurred in the last\r
five seconds - turn the LED off. */\r
portTickType xNextWakeTime;\r
const unsigned long ulValueToSend = 100UL;\r
\r
- /* The suicide tasks must be created last, as they need to know how many\r
- tasks were running prior to their creation in order to ascertain whether\r
- or not the correct/expected number of tasks are running at any given time.\r
- Therefore the standard demo 'death' tasks are not created in main(), but\r
- instead created here. */\r
- vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );\r
-\r
- /* The check timer command queue will have been filled when the timer test\r
- tasks were created in main() (this is part of the test they perform).\r
- Therefore, while the check timer can be created in main(), it could not be\r
- started from main(). Once the scheduler has started, the timer service\r
- task will have drained the command queue, and now the check task can be\r
- started successfully. */
+ /* The timer command queue will have been filled when the timer test tasks\r
+ were created in main() (this is part of the test they perform). Therefore,\r
+ while the check timer can be created in main(), it cannot be started from \r
+ main(). Once the scheduler has started, the timer service task will drain \r
+ the command queue, and now the check timer can be started successfully. */\r
xTimerStart( xCheckTimer, portMAX_DELAY );\r
\r
/* Initialise xNextWakeTime - this only needs to be done once. */\r
toggle an LED. 0 is used as the block time so the sending operation\r
will not block - it shouldn't need to block as the queue should always\r
be empty at this point in the code. */\r
- xQueueSend( xQueue, &ulValueToSend, 0 );\r
+ xQueueSend( xQueue, &ulValueToSend, mainDONT_BLOCK );\r
}\r
}\r
/*-----------------------------------------------------------*/\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvOLEDTask( void * pvParameters)\r
+{\r
+static struct oled_data xOLEDData;\r
+static unsigned char ucOffset1 = 0, ucOffset2 = 5;\r
+static portTickType xLastScrollTime = 0UL;\r
+\r
+ /* Initialise the display. */\r
+ OLED_init();\r
+\r
+ /* Initialise the parts of the oled_data structure that do not change. */\r
+ xOLEDData.line1 = FIRST_LINE;\r
+ xOLEDData.string1 = " www.FreeRTOS.org";\r
+ xOLEDData.line2 = SECOND_LINE;\r
+ xOLEDData.string2 = " www.FreeRTOS.org";\r
+ xOLEDData.contrast_val = OLED_CONTRAST_VAL;\r
+ xOLEDData.on_off = OLED_HORIZ_SCROLL_OFF;\r
+ xOLEDData.column_scrool_per_step = OLED_HORIZ_SCROLL_STEP;\r
+ xOLEDData.start_page = OLED_START_PAGE;\r
+ xOLEDData.time_intrval_btw_scroll_step = OLED_HORIZ_SCROLL_TINVL;\r
+ xOLEDData.end_page = OLED_END_PAGE;\r
+\r
+\r
+ /* Initialise the last scroll time. This only needs to be done once,\r
+ because from this point on it will get automatically updated in the\r
+ xTaskDelayUntil() API function. */\r
+ xLastScrollTime = xTaskGetTickCount();\r
+\r
+ for( ;; )\r
+ {\r
+ /* Wait until it is time to update the OLED again. */\r
+ vTaskDelayUntil( &xLastScrollTime, mainOLED_PERIOD_MS );\r
+ \r
+ xOLEDData.char_offset1 = ucOffset1++;\r
+ xOLEDData.char_offset2 = ucOffset2++;\r
+ \r
+ OLED_write_data( &xOLEDData, BOTH_LINES );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvSetupHardware( void )\r
{\r
+ SystemCoreClockUpdate();\r
+ \r
/* Disable the Watch Dog Timer */\r
MSS_WD_disable( );\r
\r
/* Configure the GPIO for the LEDs. */\r
vParTestInitialise();\r
-\r
- /* Initialise the display. */\r
- OLED_init();\r
+ \r
+ /* ACE Initialization */\r
+ ACE_init();\r
\r
/* Setup the GPIO and the NVIC for the switch used in this simple demo. */\r
NVIC_SetPriority( GPIO8_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
{\r
/* Called if a call to pvPortMalloc() fails because there is insufficient\r
free memory available in the FreeRTOS heap. pvPortMalloc() is called\r
- internally by FreeRTOS API functions that create tasks, queues, software \r
+ internally by FreeRTOS API functions that create tasks, queues, software\r
timers, and semaphores. The size of the FreeRTOS heap is set by the\r
configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */\r
for( ;; );\r
return ( char * ) pcStatusMessage;\r
}\r
}\r
+/*-----------------------------------------------------------*/\r
\r
+void vMainConfigureTimerForRunTimeStats( void )\r
+{\r
+const unsigned long ulMax32BitValue = 0xffffffffUL;\r
+\r
+ MSS_TIM64_init( MSS_TIMER_PERIODIC_MODE );\r
+ MSS_TIM64_load_immediate( ulMax32BitValue, ulMax32BitValue );\r
+ MSS_TIM64_start();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+unsigned long ulGetRunTimeCounterValue( void )\r
+{\r
+unsigned long long ullCurrentValue;\r
+const unsigned long long ulMax64BitValue = 0xffffffffffffffffULL;\r
+unsigned long *pulHighWord, *pulLowWord;\r
+\r
+ pulHighWord = ( unsigned long * ) &ullCurrentValue;\r
+ pulLowWord = pulHighWord++;\r
+ \r
+ MSS_TIM64_get_current_value( ( uint32_t * ) pulHighWord, ( uint32_t * ) pulLowWord );\r
+ \r
+ /* Convert the down count into an upcount. */\r
+ ullCurrentValue = ulMax64BitValue - ullCurrentValue;\r
+ \r
+ /* Scale to a 32bit number of suitable frequency. */\r
+ ullCurrentValue >>= 13;\r
+\r
+ /* Just return 32 bits. */\r
+ return ( unsigned long ) ullCurrentValue;\r
+}\r
\r