/* * 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 * */ /****************************************************************************** * This project provides two demo applications. A simple blinky style project, * and a more comprehensive test and demo application. The * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to * select between the two. The simply blinky demo is implemented and described * in main_blinky.c. The more comprehensive test and demo application is * implemented and described in main_full.c. * * This file implements the code that is not demo specific, including the * hardware setup and FreeRTOS hook functions. * * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT! * https://www.FreeRTOS.org/RTOS_Intel_Quark_Galileo_GCC.html * */ /* Standard includes. */ #include /* Scheduler include files. */ #include "FreeRTOS.h" #include "task.h" #include "semphr.h" /* Standard demo includes, only necessary for the tick hook. */ #include "TimerDemo.h" #include "QueueOverwrite.h" #include "EventGroupsDemo.h" #include "QueueSet.h" #include "TaskNotify.h" #include "IntQueue.h" /* Added Galileo serial support. */ #include "galileo_support.h" /* Set to 1 to sit in a loop on start up, allowing a debugger to connect to the * application before main() executes. */ #define mainWAIT_FOR_DEBUG_CONNECTION 0 /* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo, * or 0 to run the more comprehensive test and demo application. */ #define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1 /*-----------------------------------------------------------*/ /* * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. */ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) extern void main_blinky( void ); #else extern void main_full( void ); #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */ /* Prototypes for functions called from asm start up code. */ int main( void ); void CRT_Init( void ); /* * Prototypes for the standard FreeRTOS callback/hook functions implemented * within this file. */ void vApplicationMallocFailedHook( void ); void vApplicationIdleHook( void ); void vApplicationStackOverflowHook( TaskHandle_t pxTask, char * pcTaskName ); void vApplicationTickHook( void ); /* * Perform any hardware/peripheral related initialisation necessary to run the * demo. */ static void prvSetupHardware( void ); static void prvCalibrateLVTimer( void ); /* * If mainWAIT_FOR_DEBUG_CONNECTION is set to 1 then the following function will * sit in a loop on start up, allowing a debugger to connect to the application * before main() executes. If mainWAIT_FOR_DEBUG_CONNECTION is not set to 1 * then the following function does nothing. */ static void prvLoopToWaitForDebugConnection( void ); /* * Helper functions used when an assert is triggered. The first periodically * displays an assert message, and the second clears the assert message when the * function called by the configASSERT() macro is exited. */ static void prvDisplayAssertion( const char * pcFile, unsigned long ulLine ); static void prvClearAssertionLine( void ); /*-----------------------------------------------------------*/ /* See http://www.FreeRTOS.org/RTOS_Intel_Quark_Galileo_GCC.html for usage * instructions. */ int main( void ) { /* Optionally wait for a debugger to connect. */ prvLoopToWaitForDebugConnection(); /* Init the UART, GPIO, etc. */ prvSetupHardware(); /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top * of this file. */ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) { g_printf_rcc( 3, 2, DEFAULT_SCREEN_COLOR, "Running main_blinky()." ); main_blinky(); } #else { g_printf_rcc( 3, 2, DEFAULT_SCREEN_COLOR, "Running main_full()." ); main_full(); } #endif return 0; } /*-----------------------------------------------------------*/ void vApplicationMallocFailedHook( void ) { /* Called if a call to pvPortMalloc() fails because there is insufficient * free memory available in the FreeRTOS heap. pvPortMalloc() is called * internally by FreeRTOS API functions that create tasks, queues, software * timers, and semaphores. The size of the FreeRTOS heap is set by the * configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. * * Force an assert. */ configASSERT( xTaskGetTickCount() == 0 ); taskDISABLE_INTERRUPTS(); for( ; ; ) { } } /*-----------------------------------------------------------*/ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char * pcTaskName ) { ( void ) pcTaskName; ( void ) pxTask; /* Run time stack overflow checking is performed if * configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook * function is called if a stack overflow is detected. * * Increase the size of the stack allocated to the offending task. * * Force an assert. */ configASSERT( pxTask == NULL ); taskDISABLE_INTERRUPTS(); for( ; ; ) { } } /*-----------------------------------------------------------*/ void vApplicationIdleHook( void ) { volatile unsigned long xFreeHeapSpace; /* This is just a trivial example of an idle hook. It is called on each * cycle of the idle task. It must *NOT* attempt to block. In this case the * idle task just queries the amount of FreeRTOS heap that remains. See the * memory management section on the http://www.FreeRTOS.org web site for memory * management options. If there is a lot of heap memory free then the * configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up * RAM. */ xFreeHeapSpace = xPortGetFreeHeapSize(); /* Remove compiler warning about xFreeHeapSpace being set but never used. */ ( void ) xFreeHeapSpace; } /*-----------------------------------------------------------*/ static void prvDisplayAssertion( const char * pcFile, unsigned long ulLine ) { extern void vMilliSecondDelay( uint32_t DelayTime ); const uint32_t ul500ms = 500UL; /* Display assertion file and line. Don't use the gated g_printf just in * the assert was triggered while the gating semaphore was taken. Always print * on line 23. */ UngatedMoveToScreenPosition( 23, 2 ); printf( ANSI_COLOR_RED ); printf( "ASSERT: File = %s, Line = %u\n\r", pcFile, ulLine ); printf( ANSI_COLOR_RESET ); printf( ANSI_SHOW_CURSOR ); vMilliSecondDelay( ul500ms ); } /*-----------------------------------------------------------*/ static void prvClearAssertionLine( void ) { UngatedMoveToScreenPosition( 23, 1 ); printf( ANSI_COLOR_RESET ); printf( ANSI_CLEAR_LINE ); printf( ANSI_HIDE_CURSOR ); } /*-----------------------------------------------------------*/ void vAssertCalled( const char * pcFile, unsigned long ulLine ) { volatile uint32_t ul = 0; ( void ) pcFile; ( void ) ulLine; taskENTER_CRITICAL(); { /* Set ul to a non-zero value or press a key to step out of this * function in order to inspect the location of the assert(). */ /* Clear any pending key presses. */ while( ucGalileoGetchar() != 0 ) { /* Nothing to do here - the key press is just discarded. */ } do { prvDisplayAssertion( pcFile, ulLine ); } while( ( ul == pdFALSE ) && ( ucGalileoGetchar() == 0 ) ); prvClearAssertionLine(); } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ void vApplicationTickHook( void ) { #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 0 ) { extern void vTimerPeriodicISRTests( void ); /* The full demo includes a software timer demo/test that requires * prodding periodically from the tick interrupt. */ vTimerPeriodicISRTests(); /* Call the periodic queue overwrite from ISR demo. */ vQueueOverwritePeriodicISRDemo(); /* Call the periodic event group from ISR demo. */ vPeriodicEventGroupsProcessing(); /* Call the periodic queue set from ISR demo. */ vQueueSetAccessQueueSetFromISR(); /* Use task notifications from an interrupt. */ xNotifyTaskFromISR(); } #endif /* if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 0 ) */ } /*-----------------------------------------------------------*/ static void prvSetupHardware( void ) { /* Initialise the serial port and GPIO. */ vInitializeGalileoSerialPort( DEBUG_SERIAL_PORT ); vGalileoInitializeGpioController(); vGalileoInitializeLegacyGPIO(); /* Initialise HPET interrupt(s) */ #if ( ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) && ( hpetHPET_TIMER_IN_USE != 0 ) ) { portDISABLE_INTERRUPTS(); vInitializeAllHPETInterrupts(); } #endif /* Setup the LED. */ vGalileoLegacyGPIOInitializationForLED(); /* Demonstrates how to calibrate LAPIC Timer. The calibration value * calculated here may get overwritten when the scheduler starts. */ prvCalibrateLVTimer(); /* Print RTOS loaded message. */ vPrintBanner(); } /*-----------------------------------------------------------*/ static void prvLoopToWaitForDebugConnection( void ) { /* Debug if define = 1. */ #if ( mainWAIT_FOR_DEBUG_CONNECTION == 1 ) { /* When using the debugger, set this value to pdFALSE, and the application * will sit in a loop at the top of main() to allow the debugger to attached * before the application starts running. Once attached, set * ulExitResetSpinLoop to a non-zero value to leave the loop. */ volatile uint32_t ulExitResetSpinLoop = pdFALSE; /* Must initialize UART before anything will print. */ vInitializeGalileoSerialPort( DEBUG_SERIAL_PORT ); /* RTOS loaded message. */ vPrintBanner(); /* Output instruction message. */ MoveToScreenPosition( 3, 1 ); g_printf( DEFAULT_SCREEN_COLOR ); g_printf( " Waiting for JTAG connection.\n\n\r" ); g_printf( ANSI_COLOR_RESET ); g_printf( " Once connected, either set ulExitResetSpinLoop to a non-zero value,\n\r" ); g_printf( " or you can [PRESS ANY KEY] to start the debug session.\n\n\r" ); printf( ANSI_SHOW_CURSOR ); /* Use the debugger to set the ulExitResetSpinLoop to a non-zero value * or press a key to exit this loop, and step through the application. In * Eclipse, simple hover over the variable to see its value in a pop-over * box, then edit the value in the pop-over box. */ do { portNOP(); } while( ( ulExitResetSpinLoop == pdFALSE ) && ( ucGalileoGetchar() == 0 ) ); } #endif /* if ( mainWAIT_FOR_DEBUG_CONNECTION == 1 ) */ } /*-----------------------------------------------------------*/ void CRT_Init( void ) { extern uint32_t __bss_start[]; extern uint32_t __bss_end[]; extern uint32_t __data_vma[]; extern uint32_t __data_lma[]; extern uint32_t __data_start[]; extern uint32_t __data_end[]; uint32_t x = 255; size_t xSize; /* Zero out bss. */ xSize = ( ( size_t ) __bss_end ) - ( ( size_t ) __bss_start ); memset( ( void * ) __bss_start, 0x00, xSize ); /* Copy initialised variables. */ xSize = ( ( size_t ) __data_end ) - ( ( size_t ) __data_start ); memcpy( ( void * ) __data_vma, __data_lma, xSize ); /* Ensure no interrupts are pending. */ do { portAPIC_EOI = 0; x--; } while( x > 0 ); } /*-----------------------------------------------------------*/ static void prvCalibrateLVTimer( void ) { uint32_t uiInitialTimerCounts, uiCalibratedTimerCounts; /* Disable LAPIC Counter. */ portAPIC_LVT_TIMER = portAPIC_DISABLE; /* Calibrate the LV Timer counts to ensure it matches the HPET timer over * extended periods. */ uiInitialTimerCounts = ( ( configCPU_CLOCK_HZ >> 4UL ) / configTICK_RATE_HZ ); uiCalibratedTimerCounts = uiCalibrateTimer( 0, hpetLVTIMER ); if( uiCalibratedTimerCounts != 0 ) { uiInitialTimerCounts = uiCalibratedTimerCounts; } /* Set the interrupt frequency. */ portAPIC_TMRDIV = portAPIC_DIV_16; portAPIC_TIMER_INITIAL_COUNT = uiInitialTimerCounts; /* Enable LAPIC Counter. */ portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR; /* Sometimes needed. */ portAPIC_TMRDIV = portAPIC_DIV_16; }