FreeRTOS-Kernel/FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/main.c
Rahul Kar 121fbe295b
Fix formatting in kernel demo application files (#1148)
* Fix formatting in kernel demo application files

* Fix header check fail in the demo files

* Add ignored patterns in core header check file

* Fix formatting

* Update vApplicationStackOverflowHook for AVR_ATMega4809_MPLAB.X/main.c

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>

* Update vApplicationStackOverflowHook for AVR_ATMega4809_MPLAB.X/main.c

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>

* Update vApplicationStackOverflowHook for AVR_Dx_IAR/main.c

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>

* Update vApplicationStackOverflowHook for AVR_Dx_IAR/main.c

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>

* Update vApplicationStackOverflowHook for AVR_Dx_MPLAB.X/main.c

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>

* Update vApplicationMallocFailedHook for AVR_Dx_MPLAB.X/main.c

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>

* Fix formatting AVR32_UC3

---------

Co-authored-by: Soren Ptak <ptaksoren@gmail.com>
2024-01-02 11:05:59 +05:30

491 lines
18 KiB
C

/*
* FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* Creates all the demo application tasks, then starts the scheduler. The WEB
* documentation provides more details of the standard demo application tasks.
* In addition to the standard demo tasks, the following tasks and tests are
* defined and/or created within this file:
*
* "OLED" task - the OLED task is a 'gatekeeper' task. It is the only task that
* is permitted to access the display directly. Other tasks wishing to write a
* message to the OLED send the message on a queue to the OLED task instead of
* accessing the OLED themselves. The OLED task just blocks on the queue waiting
* for messages - waking and displaying the messages as they arrive.
*
* "Check" hook - This only executes every five seconds from the tick hook.
* Its main function is to check that all the standard demo tasks are still
* operational. Should any unexpected behaviour within a demo task be discovered
* the tick hook will write an error to the OLED (via the OLED task). If all the
* demo tasks are executing with their expected behaviour then the check task
* writes PASS to the OLED (again via the OLED task), as described above.
*
* Use the following command to start running the application in QEMU, pausing
* to wait for a debugger connection:
* "qemu-system-arm -machine lm3s6965evb -s -S -kernel [pat_to]\RTOSDemo.elf"
*
* To enable FreeRTOS+Trace:
* 1) Add #include "trcRecorder.h" to the bottom of FreeRTOSConfig.h.
* 2) Call vTraceEnable( TRC_START ); at the top of main.
* 3) Ensure the "FreeRTOS+Trace Recorder" folder in the Project Explorer
* window is not excluded from the build.
*
* To retrieve the trace files:
* 1) Use the Memory windows in the Debug perspective to dump RAM from the
* RecorderData variable.
*/
/*************************************************************************
* Please ensure to read http://www.freertos.org/portlm3sx965.html
* which provides information on configuring and running this demo for the
* various Luminary Micro EKs.
*************************************************************************/
/* Standard includes. */
#include <stdio.h>
#include <string.h>
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Hardware library includes. */
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_sysctl.h"
#include "hw_uart.h"
#include "sysctl.h"
#include "gpio.h"
#include "grlib.h"
#include "osram128x64x4.h"
#include "uart.h"
/* Demo app includes. */
#include "death.h"
#include "blocktim.h"
#include "semtest.h"
#include "bitmap.h"
#include "QPeek.h"
#include "recmutex.h"
#include "QueueSet.h"
#include "EventGroupsDemo.h"
#include "MessageBufferDemo.h"
#include "StreamBufferDemo.h"
/*-----------------------------------------------------------*/
/* The time between cycles of the 'check' functionality (defined within the
* tick hook. */
#define mainCHECK_DELAY ( ( TickType_t ) 5000 / portTICK_PERIOD_MS )
/* Task stack sizes. */
#define mainOLED_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE + 40 )
#define mainMESSAGE_BUFFER_TASKS_STACK_SIZE ( 100 )
/* Task priorities. */
#define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
/* The maximum number of message that can be waiting for display at any one
* time. */
#define mainOLED_QUEUE_SIZE ( 3 )
/* Dimensions the buffer into which the jitter time is written. */
#define mainMAX_MSG_LEN 25
/* The period of the system clock in nano seconds. This is used to calculate
* the jitter time in nano seconds. */
#define mainNS_PER_CLOCK ( ( uint32_t ) ( ( 1.0 / ( double ) configCPU_CLOCK_HZ ) * 1000000000.0 ) )
/* Constants used when writing strings to the display. */
#define mainCHARACTER_HEIGHT ( 9 )
#define mainMAX_ROWS_128 ( mainCHARACTER_HEIGHT * 14 )
#define mainMAX_ROWS_96 ( mainCHARACTER_HEIGHT * 10 )
#define mainMAX_ROWS_64 ( mainCHARACTER_HEIGHT * 7 )
#define mainFULL_SCALE ( 15 )
#define ulSSI_FREQUENCY ( 3500000UL )
/*-----------------------------------------------------------*/
/*
* The display is written two by more than one task so is controlled by a
* 'gatekeeper' task. This is the only task that is actually permitted to
* access the display directly. Other tasks wanting to display a message send
* the message to the gatekeeper.
*/
static void prvOLEDTask( void * pvParameters );
/*
* Configure the hardware for the demo.
*/
static void prvSetupHardware( void );
/*
* Configures the high frequency timers - those used to measure the timing
* jitter while the real time kernel is executing.
*/
extern void vSetupHighFrequencyTimer( void );
/*
* Hook functions that can get called by the kernel.
*/
void vApplicationStackOverflowHook( TaskHandle_t pxTask,
char * pcTaskName );
void vApplicationTickHook( void );
/*
* Basic polling UART write function.
*/
static void prvPrintString( const char * pcString );
/*-----------------------------------------------------------*/
/* The queue used to send messages to the OLED task. */
static QueueHandle_t xOLEDQueue;
/* The welcome text. */
const char * const pcWelcomeMessage = " www.FreeRTOS.org";
/*-----------------------------------------------------------*/
/*************************************************************************
* Please ensure to read http://www.freertos.org/portlm3sx965.html
* which provides information on configuring and running this demo for the
* various Luminary Micro EKs.
*************************************************************************/
int main( void )
{
/* Initialise the trace recorder. Use of the trace recorder is optional.
* See http://www.FreeRTOS.org/trace for more information and the comments at
* the top of this file regarding enabling trace in this demo.
* vTraceEnable( TRC_START ); */
prvSetupHardware();
/* Create the queue used by the OLED task. Messages for display on the OLED
* are received via this queue. */
xOLEDQueue = xQueueCreate( mainOLED_QUEUE_SIZE, sizeof( char * ) );
/* Start the standard demo tasks. */
vStartRecursiveMutexTasks();
vCreateBlockTimeTasks();
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
vStartQueuePeekTasks();
vStartQueueSetTasks();
vStartEventGroupTasks();
vStartMessageBufferTasks( mainMESSAGE_BUFFER_TASKS_STACK_SIZE );
vStartStreamBufferTasks();
/* Start the tasks defined within this file/specific to this demo. */
xTaskCreate( prvOLEDTask, "OLED", mainOLED_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
/* The suicide tasks must be created last as they need to know how many
* tasks were running prior to their creation in order to ascertain whether
* or not the correct/expected number of tasks are running at any given time. */
vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
/* Uncomment the following line to configure the high frequency interrupt
* used to measure the interrupt jitter time.
* vSetupHighFrequencyTimer(); */
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was insufficient memory to create the idle
* task. */
for( ; ; )
{
}
}
/*-----------------------------------------------------------*/
void prvSetupHardware( void )
{
/* If running on Rev A2 silicon, turn the LDO voltage up to 2.75V. This is
* a workaround to allow the PLL to operate reliably. */
if( DEVICE_IS_REVA2 )
{
SysCtlLDOSet( SYSCTL_LDO_2_75V );
}
/* Set the clocking to run from the PLL at 50 MHz */
SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ );
/* Initialise the UART - QEMU usage does not seem to require this
* initialisation. */
SysCtlPeripheralEnable( SYSCTL_PERIPH_UART0 );
UARTEnable( UART0_BASE );
}
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
static const char * pcMessage = "PASS";
static uint32_t ulTicksSinceLastDisplay = 0;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Called from every tick interrupt. Have enough ticks passed to make it
* time to perform our health status check again? */
ulTicksSinceLastDisplay++;
if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )
{
ulTicksSinceLastDisplay = 0;
/* Has an error been found in any task? */
if( xAreStreamBufferTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN STRM";
}
else if( xAreMessageBufferTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN MSG";
}
else if( xIsCreateTaskStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN CREATE";
}
else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN BLOCK TIME";
}
else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN SEMAPHORE";
}
else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN PEEK Q";
}
else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN REC MUTEX";
}
else if( xAreQueueSetTasksStillRunning() != pdPASS )
{
pcMessage = "ERROR IN Q SET";
}
else if( xAreEventGroupTasksStillRunning() != pdTRUE )
{
pcMessage = "ERROR IN EVNT GRP";
}
/* Send the message to the OLED gatekeeper for display. */
xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR( xOLEDQueue, &pcMessage, &xHigherPriorityTaskWoken );
}
/* Write to a queue that is in use as part of the queue set demo to
* demonstrate using queue sets from an ISR. */
vQueueSetAccessQueueSetFromISR();
/* Call the event group ISR tests. */
vPeriodicEventGroupsProcessing();
/* Exercise stream buffers from interrupts. */
vPeriodicStreamBufferProcessing();
}
/*-----------------------------------------------------------*/
static void prvPrintString( const char * pcString )
{
while( *pcString != 0x00 )
{
UARTCharPut( UART0_BASE, *pcString );
pcString++;
}
}
/*-----------------------------------------------------------*/
void prvOLEDTask( void * pvParameters )
{
const char * pcMessage;
uint32_t ulY, ulMaxY;
static char cMessage[ mainMAX_MSG_LEN ];
const unsigned char * pucImage;
/* Functions to access the OLED. The one used depends on the dev kit
* being used. */
void ( * vOLEDInit )( uint32_t ) = NULL;
void ( * vOLEDStringDraw )( const char *,
uint32_t,
uint32_t,
unsigned char ) = NULL;
void ( * vOLEDImageDraw )( const unsigned char *,
uint32_t,
uint32_t,
uint32_t,
uint32_t ) = NULL;
void ( * vOLEDClear )( void ) = NULL;
/* Prevent warnings about unused parameters. */
( void ) pvParameters;
/* Map the OLED access functions to the driver functions that are appropriate
* for the evaluation kit being used. */
configASSERT( ( HWREG( SYSCTL_DID1 ) & SYSCTL_DID1_PRTNO_MASK ) == SYSCTL_DID1_PRTNO_6965 );
vOLEDInit = OSRAM128x64x4Init;
vOLEDStringDraw = OSRAM128x64x4StringDraw;
vOLEDImageDraw = OSRAM128x64x4ImageDraw;
vOLEDClear = OSRAM128x64x4Clear;
ulMaxY = mainMAX_ROWS_64;
pucImage = pucBasicBitmap;
ulY = ulMaxY;
/* Initialise the OLED and display a startup message. */
vOLEDInit( ulSSI_FREQUENCY );
vOLEDStringDraw( "POWERED BY FreeRTOS", 0, 0, mainFULL_SCALE );
vOLEDImageDraw( pucImage, 0, mainCHARACTER_HEIGHT + 1, bmpBITMAP_WIDTH, bmpBITMAP_HEIGHT );
for( ; ; )
{
/* Wait for a message to arrive that requires displaying. */
xQueueReceive( xOLEDQueue, &pcMessage, portMAX_DELAY );
/* Write the message on the next available row. */
ulY += mainCHARACTER_HEIGHT;
if( ulY >= ulMaxY )
{
ulY = mainCHARACTER_HEIGHT;
vOLEDClear();
vOLEDStringDraw( pcWelcomeMessage, 0, 0, mainFULL_SCALE );
}
/* Display the message along with the maximum jitter time from the
* high priority time test. */
sprintf( cMessage, "%s %u", pcMessage, ( unsigned int ) xTaskGetTickCount() );
vOLEDStringDraw( cMessage, 0, ulY, mainFULL_SCALE );
prvPrintString( cMessage );
prvPrintString( "\r\n" );
}
}
/*-----------------------------------------------------------*/
volatile char * pcOverflowedTask = NULL; /* Prevent task name being optimised away. */
void vApplicationStackOverflowHook( TaskHandle_t pxTask,
char * pcTaskName )
{
( void ) pxTask;
pcOverflowedTask = pcTaskName;
vAssertCalled( __FILE__, __LINE__ );
for( ; ; )
{
}
}
/*-----------------------------------------------------------*/
void vAssertCalled( const char * pcFile,
uint32_t ulLine )
{
volatile uint32_t ulSetTo1InDebuggerToExit = 0;
taskENTER_CRITICAL();
{
while( ulSetTo1InDebuggerToExit == 0 )
{
/* Nothing to do here. Set the loop variable to a non zero value in
* the debugger to step out of this function to the point that caused
* the assertion. */
( void ) pcFile;
( void ) ulLine;
}
}
taskEXIT_CRITICAL();
}
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
* implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
* used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
* state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
* Note that, as the array is necessarily of type StackType_t,
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
* application must provide an implementation of vApplicationGetTimerTaskMemory()
* to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
uint32_t * pulTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
/* Pass out a pointer to the StaticTask_t structure in which the Timer
* task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
* Note that, as the array is necessarily of type StackType_t,
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/*-----------------------------------------------------------*/
char * _sbrk_r( struct _reent * r,
int incr )
{
/* Just to keep the linker quiet. */
( void ) r;
( void ) incr;
/* Check this function is never called by forcing an assert() if it is. */
configASSERT( incr == -1 );
return NULL;
}