From fe1600325e9b176108626e4fb301c3f47f4d649a Mon Sep 17 00:00:00 2001 From: richardbarry Date: Thu, 23 Dec 2010 17:04:34 +0000 Subject: [PATCH] Comment and spell check the STM32L152 demo project. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1184 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Demo/Cortex_STM32L152_IAR/ParTest.c | 2 + Demo/Cortex_STM32L152_IAR/main.c | 316 +++++++++++++++--- Demo/Cortex_STM32L152_IAR/serial.c | 26 +- .../settings/RTOSDemo.dbgdt | 12 +- .../settings/RTOSDemo.dni | 16 +- .../settings/RTOSDemo.wsdt | 10 +- 6 files changed, 309 insertions(+), 73 deletions(-) diff --git a/Demo/Cortex_STM32L152_IAR/ParTest.c b/Demo/Cortex_STM32L152_IAR/ParTest.c index 3009d685e..53353d6c6 100644 --- a/Demo/Cortex_STM32L152_IAR/ParTest.c +++ b/Demo/Cortex_STM32L152_IAR/ParTest.c @@ -68,6 +68,8 @@ void vParTestInitialise( void ) { + /* Configure the output LEDs. Note that JP18 and JP19 must be closed on + the Eval board for LED3 and LED4 to work. */ STM_EVAL_LEDInit( LED1 ); STM_EVAL_LEDInit( LED2 ); STM_EVAL_LEDInit( LED3 ); diff --git a/Demo/Cortex_STM32L152_IAR/main.c b/Demo/Cortex_STM32L152_IAR/main.c index 8dbf6daba..a47d0ce28 100644 --- a/Demo/Cortex_STM32L152_IAR/main.c +++ b/Demo/Cortex_STM32L152_IAR/main.c @@ -51,6 +51,71 @@ licensing and training services. */ +/* + * The documentation page for this demo available on http://www.FreeRTOS.org + * documents the hardware configuration required to run this demo. It also + * provides more information on the expected demo application behaviour. + * + * main() creates all the demo application tasks, then starts the scheduler. + * A lot of the created tasks are from the pool of "standard demo" tasks. The + * web documentation provides more details of the standard demo application + * tasks, which provide no particular functionality but do provide a good + * example of how to use the FreeRTOS API. + * + * In addition to the standard demo tasks, the following tasks, interrupts and + * tests are defined and/or created within this file: + * + * "LCD" task - The LCD task is a 'gatekeeper' task. It is the only task that + * is permitted to access the LCD and therefore ensures access to the LCD is + * always serialised and there are no mutual exclusion issues. When a task or + * an interrupt wants to write to the LCD, it does not access the LCD directly + * but instead sends the message to the LCD task. The LCD task then performs + * the actual LCD output. This mechanism also allows interrupts to, in effect, + * write to the LCD by sending messages to the LCD task. + * + * The LCD task is also a demonstration of a controller task design pattern. + * Some tasks do not actually send a string to the LCD task directly, but + * instead send a command that is interpreted by the LCD task. In a normal + * application these commands can be control values or set points, in this + * simple example the commands just result in messages being displayed on the + * LCD. + * + * "Button Poll" task - This task polls the state of the 'up' key on the + * joystick input device. It uses the vTaskDelay() API function to control + * the poll rate to ensure debouncing is not necessary and that the task does + * not use all the available CPU processing time. + * + * Button Interrupt and run time stats display - The select button on the + * joystick input device is configured to generate an external interrupt. The + * handler for this interrupt sends a message to LCD task, which interprets the + * message to mean, firstly write a message to the LCD, and secondly, generate + * a table of run time statistics. The run time statistics are displayed as a + * table that contains information on how much processing time each task has + * been allocated since the application started to execute. This information + * is provided both as an absolute time, and as a percentage of the total run + * time. The information is displayed in the terminal IO window of the IAR + * embedded workbench. The online documentation for this demo shows a screen + * shot demonstrating where the run time stats can be viewed. + * + * Idle Hook - The idle hook is a function that is called on each iteration of + * the idle task. In this case it is used to place the processor into a low + * power mode. Note however that this application is implemented using standard + * components, and is therefore not optimised for low power operation. Lower + * power consumption would be achieved by converting polling tasks into event + * driven tasks, and slowing the tick interrupt frequency. + * + * "Check" function called from the tick hook - The tick hook is called during + * each tick interrupt. It is called from an interrupt context so must execute + * quickly, not attempt to block, and not call any FreeRTOS API functions that + * do not end in "FromISR". In this case the tick hook executes a 'check' + * function. This only executes every five seconds. Its main function is to + * check that all the standard demo tasks are still operational. Each time it + * executes it sends a status code to the LCD task. The LCD task interprets the + * code and displays an appropriate message - which will be PASS if no tasks + * have reported any errors, or a message stating which task has reported an + * error. +*/ + /* Standard includes. */ #include @@ -66,81 +131,131 @@ #include "comtest2.h" #include "GenQTest.h" -/* ST driver includes. */ -#include "stm32l1xx_usart.h" - /* Eval board includes. */ #include "stm32_eval.h" #include "stm32l152_eval_lcd.h" +/* The priorities assigned to the tasks. */ #define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainLCD_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainGENERIC_QUEUE_TEST_PRIORITY ( tskIDLE_PRIORITY ) -#define mainLCD_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) - +/* The length of the queue (the number of items the queue can hold) that is used +to send messages from tasks and interrupts the the LCD task. */ #define mainQUEUE_LENGTH ( 5 ) +/* Codes sent within message to the LCD task so the LCD task can interrupt +exactly what the message it just received was. These are sent in the +cMessageID member of the message structure (defined below). */ #define mainMESSAGE_BUTTON_UP ( 1 ) -#define mainMESSAGE_BUTTON_DOWN ( 2 ) -#define mainMESSAGE_BUTTON_LEFT ( 3 ) -#define mainMESSAGE_BUTTON_RIGHT ( 4 ) -#define mainMESSAGE_BUTTON_SEL ( 5 ) -#define mainMESSAGE_STATUS ( 6 ) - -#define mainERROR_DYNAMIC_TASKS ( 2 ) -#define mainERROR_COM_TEST ( 3 ) -#define mainERROR_GEN_QUEUE_TEST ( 4 ) +#define mainMESSAGE_BUTTON_SEL ( 2 ) +#define mainMESSAGE_STATUS ( 3 ) + +/* When cMessageID member of the message sent to the LCD task is +mainMESSAGE_STATUS then these definitions are sent in the lMessageValue member +of the same message to indicate what the status actually is. The value 1 is not +used as this is globally defined as pdPASS, and indicates that no errors have +been reported (the system is running as expected). */ +#define mainERROR_DYNAMIC_TASKS ( pdPASS + 1 ) +#define mainERROR_COM_TEST ( pdPASS + 2 ) +#define mainERROR_GEN_QUEUE_TEST ( pdPASS + 3 ) /* Baud rate used by the comtest tasks. */ -#define mainCOM_TEST_BAUD_RATE ( 9600 ) +#define mainCOM_TEST_BAUD_RATE ( 115200 ) /* The LED used by the comtest tasks. See the comtest.c file for more information. */ #define mainCOM_TEST_LED ( 3 ) +/*-----------------------------------------------------------*/ /* * System configuration is performed prior to main() being called, this function * configures the peripherals used by the demo application. */ static void prvSetupHardware( void ); + +/* + * Definition of the LCD/controller task described in the comments at the top + * of this file. + */ static void prvLCDTask( void *pvParameters ); -static void vTempTask( void *pv ); + +/* + * Definition of the button poll task described in the comments at the top of + * this file. + */ +static void vButtonPollTask( void *pvParameters ); + +/* + * Converts a status message value into an appropriate string for display on + * the LCD. The string is written to pcBuffer. + */ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue ); +/*-----------------------------------------------------------*/ + +/* The time base for the run time stats is generated by the 16 bit timer 6. +Each time the timer overflows ulTIM6_OverflowCount is incremented. Therefore, +when converting the total run time to a 32 bit number, the most significant two +bytes are given by ulTIM6_OverflowCount and the least significant two bytes are +given by the current TIM6 counter value. Care must be taken with data +consistency when combining the two in case a timer overflow occurs as the +value is being read. */ unsigned long ulTIM6_OverflowCount = 0UL; +/* The handle of the queue used to send messages from tasks and interrupts to +the LCD task. */ static xQueueHandle xLCDQueue = NULL; +/* The definition of each message sent from tasks and interrupts to the LCD +task. */ typedef struct { - char cMessageID; - long lMessageValue; + char cMessageID; /* << States what the message is. */ + long lMessageValue; /* << States the message value (can be an integer, string pointer, etc. depending on the value of cMessageID. */ } xQueueMessage; +/*-----------------------------------------------------------*/ + void main( void ) { + /* Configure the peripherals used by this demo application. This includes + configuring the joystick input select button to generate interrupts. */ prvSetupHardware(); /* Create the queue used by tasks and interrupts to send strings to the LCD task. */ xLCDQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( xQueueMessage ) ); + /* If the queue could not be created then don't create any tasks that might + attempt to use the queue. */ if( xLCDQueue != NULL ) { + /* Add the created queue to the queue registry so it can be viewed in + the IAR FreeRTOS state viewer plug-in. */ vQueueAddToRegistry( xLCDQueue, "LCDQueue" ); - xTaskCreate( prvLCDTask, ( signed char * ) "LCD", mainLCD_TASK_STACK_SIZE, NULL, mainLCD_TASK_PRIORITY, NULL ); - xTaskCreate( vTempTask, ( signed char * ) "Temp", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + + /* Create the LCD and button poll tasks, as described at the top of this + file. */ + xTaskCreate( prvLCDTask, ( signed char * ) "LCD", configMINIMAL_STACK_SIZE, NULL, mainLCD_TASK_PRIORITY, NULL ); + xTaskCreate( vButtonPollTask, ( signed char * ) "Temp", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + + /* Create a subset of the standard demo tasks. */ vStartDynamicPriorityTasks(); vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY ); vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED ); vStartGenericQueueTasks( mainGENERIC_QUEUE_TEST_PRIORITY ); + /* Start the scheduler. */ vTaskStartScheduler(); } + /* If all is well then this line will never be reached. If it is reached + then it is likely that there was insufficient (FreeRTOS) heap memory space + to create the idle task. This may have been trapped by the malloc() failed + hook function, if one is configured. */ for( ;; ); } /*-----------------------------------------------------------*/ @@ -150,49 +265,88 @@ static void prvLCDTask( void *pvParameters ) xQueueMessage xReceivedMessage; long lLine = Line1; const long lFontHeight = (((sFONT *)LCD_GetFont())->Height); + +/* Buffer into which strings are formatted and placed ready for display on the +LCD. Note this is a static variable to prevent it being allocated on the task +stack, which is too small to hold such a variable. The stack size is configured +when the task is created. */ static char cBuffer[ 512 ]; /* This function is the only function that uses printf(). If printf() is used from any other function then some sort of mutual exclusion on stdout - will be necessary. */ - + will be necessary. + + This is also the only function that is permitted to access the LCD. + + First print out the number of bytes that remain in the FreeRTOS heap. This + can be viewed in the terminal IO window within the IAR Embedded Workbench. */ printf( "%d bytes of heap space remain unallocated\n", xPortGetFreeHeapSize() ); for( ;; ) { + /* Wait for a message to be received. This will wait indefinitely if + INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h, therefore there + is no need to check the function return value. */ xQueueReceive( xLCDQueue, &xReceivedMessage, portMAX_DELAY ); + /* Clear the LCD if the last LCD message was output to the last + available line on the LCD. */ if( lLine > Line9 ) { LCD_Clear( Blue ); lLine = 0; } + /* What is this message? What does it contain? */ switch( xReceivedMessage.cMessageID ) { - case mainMESSAGE_BUTTON_UP : sprintf( cBuffer, "Button up = %d", xReceivedMessage.lMessageValue ); - break; - case mainMESSAGE_BUTTON_DOWN : sprintf( cBuffer, "Button down = %d", xReceivedMessage.lMessageValue ); - break; - case mainMESSAGE_BUTTON_LEFT : sprintf( cBuffer, "Button left = %d", xReceivedMessage.lMessageValue ); - break; - case mainMESSAGE_BUTTON_RIGHT : sprintf( cBuffer, "Button right = %d", xReceivedMessage.lMessageValue ); + case mainMESSAGE_BUTTON_UP : /* The button poll task has just + informed this task that the up + button on the joystick input has + been pressed or released. */ + sprintf( cBuffer, "Button up = %d", xReceivedMessage.lMessageValue ); break; - case mainMESSAGE_BUTTON_SEL : printf( "\nTask\t Abs Time\t %%Time\n*****************************************" ); + + case mainMESSAGE_BUTTON_SEL : /* The select button interrupt + just informed this task that the + select button was pressed. + Generate a table of task run time + statistics and output this to + the terminal IO window in the IAR + embedded workbench. */ + printf( "\nTask\t Abs Time\t %%Time\n*****************************************" ); vTaskGetRunTimeStats( ( signed char * ) cBuffer ); printf( cBuffer ); - /* The select button passes its - own string to print out. */ + /* Also print out a message to + the LCD - in this case the + pointer to the string to print + is sent directly in the + lMessageValue member of the + message. This just demonstrates + a different communication + technique. */ sprintf( cBuffer, "%s", ( char * ) xReceivedMessage.lMessageValue ); break; - case mainMESSAGE_STATUS : prvGenerateStatusMessage( cBuffer, xReceivedMessage.lMessageValue ); + + case mainMESSAGE_STATUS : /* The tick interrupt hook + function has just informed this + task of the system status. + Generate a string in accordance + with the status value. */ + prvGenerateStatusMessage( cBuffer, xReceivedMessage.lMessageValue ); break; + default : sprintf( cBuffer, "Unknown message" ); break; } + /* Output the message that was placed into the cBuffer array within the + switch statement above. */ LCD_DisplayStringLine( lLine, ( uint8_t * ) cBuffer ); + + /* Move onto the next LCD line, ready for the next iteration of this + loop. */ lLine += lFontHeight; } } @@ -200,13 +354,15 @@ static char cBuffer[ 512 ]; static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue ) { + /* Just a utility function to convert a status value into a meaningful + string for output onto the LCD. */ switch( lStatusValue ) { case pdPASS : sprintf( pcBuffer, "Task status = PASS" ); break; case mainERROR_DYNAMIC_TASKS : sprintf( pcBuffer, "Error: Dynamic tasks" ); break; - case mainERROR_COM_TEST : sprintf( pcBuffer, "Error: COM test" ); + case mainERROR_COM_TEST : sprintf( pcBuffer, "Err: loop connected?" ); /* Error in COM test - is the Loopback connector connected? */ break; case mainERROR_GEN_QUEUE_TEST : sprintf( pcBuffer, "Error: Gen Q test" ); break; @@ -218,11 +374,21 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue ) void EXTI9_5_IRQHandler( void ) { +/* Define the message sent to the LCD task from this interrupt. */ const xQueueMessage xMessage = { mainMESSAGE_BUTTON_SEL, ( unsigned long ) "Select Interrupt!" }; long lHigherPriorityTaskWoken = pdFALSE; + /* This is the interrupt handler for the joystick select button input. + The button has been pushed, write a message to the LCD via the LCD task. */ xQueueSendFromISR( xLCDQueue, &xMessage, &lHigherPriorityTaskWoken ); + EXTI_ClearITPendingBit( SEL_BUTTON_EXTI_LINE ); + + /* If writing to xLCDQueue caused a task to unblock, and the unblocked task + has a priority equal to or above the task that this interrupt interrupted, + then lHigherPriorityTaskWoken will have been set to pdTRUE internally within + xQueuesendFromISR(), and portEND_SWITCHING_ISR() will ensure that this + interrupt returns directly to the higher priority unblocked task. */ portEND_SWITCHING_ISR( lHigherPriorityTaskWoken ); } /*-----------------------------------------------------------*/ @@ -231,12 +397,22 @@ void vApplicationTickHook( void ) { static unsigned long ulCounter = 0; static const unsigned long ulCheckFrequency = 5000UL / portTICK_RATE_MS; +long lHigherPriorityTaskWoken = pdFALSE; + +/* Define the status message that is sent to the LCD task. By default the +status is PASS. */ static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS }; -long lHigherPriorityTaskWoken = pdFALSE; /* Not used in this case as this is the tick hook. */ + /* This is called from within the tick interrupt and performs the 'check' + functionality as described in the comments at the top of this file. + + Is it time to perform the 'check' functionality again? */ ulCounter++; if( ulCounter >= ulCheckFrequency ) { + /* See if the standard demo tasks are executing as expected, changing + the message that is sent to the LCD task from PASS to an error code if + any tasks set reports an error. */ if( xAreDynamicPriorityTasksStillRunning() != pdPASS ) { xStatusMessage.lMessageValue = mainERROR_DYNAMIC_TASKS; @@ -252,35 +428,47 @@ long lHigherPriorityTaskWoken = pdFALSE; /* Not used in this case as this is the xStatusMessage.lMessageValue = mainERROR_GEN_QUEUE_TEST; } + /* As this is the tick hook the lHigherPriorityTaskWoken parameter is not + needed (a context switch is going to be performed anyway), but it must + still be provided. */ xQueueSendFromISR( xLCDQueue, &xStatusMessage, &lHigherPriorityTaskWoken ); ulCounter = 0; } } /*-----------------------------------------------------------*/ -static void vTempTask( void *pv ) +static void vButtonPollTask( void *pvParameters ) { long lLastState = pdTRUE; long lState; xQueueMessage xMessage; + /* This tasks performs the button polling functionality as described at the + top of this file. */ for( ;; ) { + /* Check the button state. */ lState = STM_EVAL_PBGetState( BUTTON_UP ); if( lState != lLastState ) { + /* The state has changed, send a message to the LCD task. */ xMessage.cMessageID = mainMESSAGE_BUTTON_UP; xMessage.lMessageValue = lState; lLastState = lState; xQueueSend( xLCDQueue, &xMessage, portMAX_DELAY ); - vTaskDelay( 10 ); } + + /* Block for 10 milliseconds so this task does not utilise all the CPU + time and debouncing of the button is not necessary. */ + vTaskDelay( 10 / portTICK_RATE_MS ); } } /*-----------------------------------------------------------*/ static void prvSetupHardware( void ) { + /* Ensure that all 4 interrupt priority bits are used as the pre-emption + priority. */ NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); /* Initialise the LEDs. */ @@ -294,19 +482,18 @@ static void prvSetupHardware( void ) /* The select button in the middle of the joystick is configured to generate an interrupt. The Eval board library will configure the interrupt - priority to be the lowest priority available - this is important as the - interrupt service routine makes use of a FreeRTOS API function so must - therefore use a priority equal to or below that set by the - configMAX_SYSCALL_INTERRUPT_PRIORITY() value set in FreeRTOSConfig.h. */ + priority to be the lowest priority available so the priority need not be + set here explicitly. It is important that the priority is equal to or + below that set by the configMAX_SYSCALL_INTERRUPT_PRIORITY value set in + FreeRTOSConfig.h. */ STM_EVAL_PBInit( BUTTON_SEL, BUTTON_MODE_EXTI ); /* Initialize the LCD */ - STM32L152_LCD_Init(); - - LCD_Clear(Blue); - LCD_SetBackColor(Blue); - LCD_SetTextColor(White); - LCD_DisplayStringLine(Line0, " www.FreeRTOS.org"); + STM32L152_LCD_Init(); + LCD_Clear( Blue ); + LCD_SetBackColor( Blue ); + LCD_SetTextColor( White ); + LCD_DisplayStringLine( Line0, " www.FreeRTOS.org" ); } /*-----------------------------------------------------------*/ @@ -315,6 +502,18 @@ void vConfigureTimerForRunTimeStats( void ) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; + /* The time base for the run time stats is generated by the 16 bit timer 6. + Each time the timer overflows ulTIM6_OverflowCount is incremented. + Therefore, when converting the total run time to a 32 bit number, the most + significant two bytes are given by ulTIM6_OverflowCount and the least + significant two bytes are given by the current TIM6 counter value. Care + must be taken with data consistency when combining the two in case a timer + overflow occurs as the value is being read. + + The portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro (in FreeRTOSConfig.h) is + defined to call this function, so the kernel will call this function + automatically at the appropriate time. */ + /* TIM6 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); @@ -330,22 +529,32 @@ NVIC_InitTypeDef NVIC_InitStructure; /* Only interrupt on overflow events. */ TIM6->CR1 |= TIM_CR1_URS; + /* Enable the interrupt. */ TIM_ITConfig( TIM6, TIM_IT_Update, ENABLE ); - /* Enable the TIM6 gloabal Interrupt */ + /* Enable the TIM6 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_LOWEST_INTERRUPT_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; /* Not used as 4 bits are used for the pre-emption priority. */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); TIM_ClearITPendingBit( TIM6, TIM_IT_Update ); - NVIC_Init(&NVIC_InitStructure); TIM_Cmd( TIM6, ENABLE ); } /*-----------------------------------------------------------*/ void TIM6_IRQHandler( void ) { + /* Interrupt handler for TIM 6 + + The time base for the run time stats is generated by the 16 bit timer 6. + Each time the timer overflows ulTIM6_OverflowCount is incremented. + Therefore, when converting the total run time to a 32 bit number, the most + significant two bytes are given by ulTIM6_OverflowCount and the least + significant two bytes are given by the current TIM6 counter value. Care + must be taken with data consistency when combining the two in case a timer + overflow occurs as the value is being read. */ if( TIM_GetITStatus( TIM6, TIM_IT_Update) != RESET) { ulTIM6_OverflowCount++; @@ -359,18 +568,27 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ( void ) pcTaskName; ( void ) pxTask; + /* Run time stack overflow checking is performed if + configconfigCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook + function is called if a stack overflow is detected. */ for( ;; ); } /*-----------------------------------------------------------*/ 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 or + semaphores. */ for( ;; ); } /*-----------------------------------------------------------*/ void vApplicationIdleHook( void ) { + /* Called on each itteration of the idle task. In this case the idle task + just enters a low(ish) power mode. */ PWR_EnterSleepMode( PWR_Regulator_ON, PWR_SLEEPEntry_WFI ); } diff --git a/Demo/Cortex_STM32L152_IAR/serial.c b/Demo/Cortex_STM32L152_IAR/serial.c index fd3a15094..0668d49d1 100644 --- a/Demo/Cortex_STM32L152_IAR/serial.c +++ b/Demo/Cortex_STM32L152_IAR/serial.c @@ -53,6 +53,15 @@ /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR UART0. + + ***Note*** This example uses queues to send each character into an interrupt + service routine and out of an interrupt service routine individually. This + is done to demonstrate queues being used in an interrupt, and to deliberately + load the system to test the FreeRTOS port. It is *NOT* meant to be an + example of an efficient implementation. An efficient implementation should + use FIFO's or DMA if available, and only use FreeRTOS API functions when + enough has been received to warrant a task being unblocked to process the + data. */ /* Scheduler includes. */ @@ -71,7 +80,6 @@ /* Misc defines. */ #define serINVALID_QUEUE ( ( xQueueHandle ) 0 ) #define serNO_BLOCK ( ( portTickType ) 0 ) -#define serTX_BLOCK_TIME ( 40 / portTICK_RATE_MS ) /*-----------------------------------------------------------*/ @@ -94,7 +102,7 @@ NVIC_InitTypeDef NVIC_InitStructure; xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) ); xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) ); - /* If the queue/semaphore was created correctly then setup the serial port + /* If the queues were created correctly then setup the serial port hardware. */ if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) ) { @@ -200,12 +208,12 @@ portCHAR cChar; if( USART_GetITStatus( USART3, USART_IT_TXE ) == SET ) { - /* The interrupt was caused by the THR becoming empty. Are there any - more characters to transmit? */ + /* The interrupt was caused by the TX register becoming empty. Are + there any more characters to transmit? */ if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE ) { /* A character was retrieved from the queue so can be sent to the - THR now. */ + USART now. */ USART_SendData( USART3, cChar ); } else @@ -216,10 +224,18 @@ portCHAR cChar; if( USART_GetITStatus( USART3, USART_IT_RXNE ) == SET ) { + /* A character has been received on the USART, send it to the Rx + handler task. */ cChar = USART_ReceiveData( USART3 ); xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken ); } + /* If sending or receiving from a queue has caused a task to unblock, and + the unblocked task has a priority equal to or higher than the currently + running task (the task this ISR interrupted), then xHigherPriorityTaskWoken + will have automatically been set to pdTRUE within the queue send or receive + function. portEND_SWITCHING_ISR() will then ensure that this ISR returns + directly to the higher priority unblocked task. */ portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); } diff --git a/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dbgdt b/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dbgdt index f3fbd8620..be0489899 100644 --- a/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dbgdt +++ b/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dbgdt @@ -19,7 +19,7 @@ - 279272727 + 295272727 @@ -36,7 +36,7 @@ - + TabID-15530-21362 @@ -44,24 +44,24 @@ Workspace - RTOSDemoRTOSDemo/FreeRTOS_SourceRTOSDemo/FreeRTOS_Source/PortableRTOSDemo/System_and_ST_CodeRTOSDemo/System_and_ST_Code/Eval_Board_LibraryRTOSDemo/System_and_ST_Code/Peripheral_LibraryRTOSDemo/System_and_ST_Code/Peripheral_Library/misc.c + RTOSDemoRTOSDemo/FreeRTOS_SourceRTOSDemo/FreeRTOS_Source/Portable - 0TabID-10464-23570TasksTASKVIEW0TabID-31438-23586QueuesQUEUEVIEW0TabID-15541-875Terminal I/OTerminalIO0 + 0TabID-10464-23570TasksTASKVIEW0TabID-31438-23586QueuesQUEUEVIEW0TabID-15541-875Terminal I/OTerminalIO0 - TextEditor$WS_DIR$\main.c0116488448840TextEditor$WS_DIR$\..\Common\Minimal\GenQTest.c05311820518238TextEditor$WS_DIR$\FreeRTOSConfig.h06143594359TextEditor$WS_DIR$\..\..\Source\portable\MemMang\heap_2.c021297759817TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CM3\port.c016170947094TextEditor$WS_DIR$\system_and_ST_code\stm32l1xx_it.c04522442244TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CM3\portasm.s0100456745670100000010000001 + TextEditor$WS_DIR$\system_and_ST_code\STM32L152_EVAL\stm32l152_eval.c03111162611626TextEditor$WS_DIR$\system_and_ST_code\STM32L1xx_StdPeriph_Driver\src\stm32l1xx_gpio.c020360706070TextEditor$WS_DIR$\serial.c0000TextEditor$WS_DIR$\FreeRTOSConfig.h05942504280TextEditor$WS_DIR$\main.c021510723107234TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CM3\port.c0160695069500100000010000001 - iaridepm.enu1debuggergui.enu1armjlink.enu1-2-2465369-2-2200200119048203666220833475560-2-2465435-2-2200200119048203666260119475560-2-23381682-2-216843401002381346232119048203666336-24491682-233616841131002381115071119048203666 + iaridepm.enu1debuggergui.enu1armjlink.enu1-2-2465369-2-2200200119048203666220833475560-2-2465435-2-2200200119048203666260119475560-2-23381682-2-216843401002381346232119048203666336-24491682-233616841131002381115071119048203666 diff --git a/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dni b/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dni index fab1365c8..f310663e6 100644 --- a/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dni +++ b/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.dni @@ -1,5 +1,5 @@ [DebugChecksum] -Checksum=818382432 +Checksum=2056793833 [DisAssemblyWindow] NumStates=_ 1 State 1=_ 1 @@ -70,10 +70,6 @@ ShowTimeLog=1 ShowTimeSum=0 Title0=Power [mA] Setup0=0 1 0 500 2 0 4 1 0 -[Disassemble mode] -mode=0 -[Breakpoints] -Count=0 [Log file] LoggingEnabled=_ 0 LogFile=_ "" @@ -81,9 +77,6 @@ Category=_ 0 [TermIOLog] LoggingEnabled=_ 0 LogFile=_ "" -[Aliases] -Count=0 -SuppressDialog=0 [SWOTraceWindow] PcSampling=0 InterruptLogs=0 @@ -103,3 +96,10 @@ Enabled=0 Mode=3 Graph=0 Symbiont=0 +[Disassemble mode] +mode=0 +[Breakpoints] +Count=0 +[Aliases] +Count=0 +SuppressDialog=0 diff --git a/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.wsdt b/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.wsdt index 0b5da45ab..097c38fb6 100644 --- a/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.wsdt +++ b/Demo/Cortex_STM32L152_IAR/settings/RTOSDemo.wsdt @@ -17,7 +17,7 @@ 20121632481201622 - + TabID-27630-4718 @@ -25,24 +25,24 @@ Workspace - RTOSDemoRTOSDemo/FreeRTOS_SourceRTOSDemo/FreeRTOS_Source/PortableRTOSDemo/Standard_Demo_CodeRTOSDemo/System_and_ST_CodeRTOSDemo/System_and_ST_Code/Peripheral_LibraryRTOSDemo/System_and_ST_Code/Peripheral_Library/stm32l1xx_pwr.c + RTOSDemoRTOSDemo/FreeRTOS_SourceRTOSDemo/FreeRTOS_Source/PortableRTOSDemo/Standard_Demo_CodeRTOSDemo/System_and_ST_CodeRTOSDemo/System_and_ST_Code/Peripheral_LibraryRTOSDemo/System_and_ST_Code/Peripheral_Library/stm32l1xx_pwr.cRTOSDemo/main.c - 0TabID-10002-7709BuildBuildTabID-18437-21512Debug LogDebug-Log0 + 0TabID-10002-7709BuildBuildTabID-18437-21512Debug LogDebug-Log0 - TextEditor$WS_DIR$\main.c03361304513045TextEditor$WS_DIR$\..\Common\Minimal\GenQTest.c05311820518238TextEditor$WS_DIR$\FreeRTOSConfig.h06136653665TextEditor$WS_DIR$\..\..\Source\portable\MemMang\heap_2.c021297759817TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CM3\port.c016170947094TextEditor$WS_DIR$\system_and_ST_code\stm32l1xx_it.c04522442244TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CM3\portasm.s010045674567TextEditor$WS_DIR$\system_and_ST_code\STM32L1xx_StdPeriph_Driver\src\stm32l1xx_pwr.c038982128230TextEditor$WS_DIR$\system_and_ST_code\stm32l1xx_conf.h001632163280100000010000001 + TextEditor$WS_DIR$\system_and_ST_code\STM32L152_EVAL\stm32l152_eval.c03111162611626TextEditor$WS_DIR$\system_and_ST_code\STM32L1xx_StdPeriph_Driver\src\stm32l1xx_gpio.c020360706070TextEditor$WS_DIR$\serial.c0000TextEditor$WS_DIR$\FreeRTOSConfig.h05942504280TextEditor$WS_DIR$\main.c021510723107234TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CM3\port.c0160695069500100000010000001 - iaridepm.enu1-2-2740438-2-2200200119048203666261905755601-2-21981682-2-216842001002381203666119048203666 + iaridepm.enu1-2-2740438-2-2200200119048203666261905755601-2-21981682-2-216842001002381203666119048203666 -- 2.39.2