]> git.sur5r.net Git - freertos/blobdiff - Demo/MSP430X_MSP430F5438_IAR/main.c
Continue work on the MSP430X demo - still a work in progress.
[freertos] / Demo / MSP430X_MSP430F5438_IAR / main.c
index 2b0821a355d80a25402156ed494e77a85da415a5..600e1f81ff0d5fc3657cd093bfccbb684660fb1c 100644 (file)
     http://www.OpenRTOS.com - Commercial support, development, porting,\r
     licensing and training services.\r
 */\r
+\r
+/* Standard includes. */\r
 #include <stdio.h>\r
 \r
+/* FreeRTOS includes. */\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
 #include "queue.h"\r
 \r
+/* Hardware includes. */\r
 #include "msp430.h"\r
 #include "hal_MSP-EXP430F5438.h"\r
 \r
-/* The rate at which mainCHECK_LED will toggle when all the tasks are running\r
-without error.  Controlled by the check task as described at the top of this\r
-file. */\r
-#define mainNO_ERROR_CYCLE_TIME                ( 5000 / portTICK_RATE_MS )\r
-\r
-/* The rate at which mainCHECK_LED will toggle when an error has been reported\r
-by at least one task.  Controlled by the check task as described at the top of\r
-this file. */\r
-#define mainERROR_CYCLE_TIME           ( 200 / portTICK_RATE_MS )\r
+/* Standard demo includes. */\r
+#include "ParTest.h"\r
+#include "comtest2.h"\r
 \r
 /* Codes sent within messages to the LCD task so the LCD task can interpret\r
 exactly what the message it just received was.  These are sent in the\r
@@ -77,23 +75,30 @@ cMessageID member of the message structure (defined below). */
 #define mainMESSAGE_STATUS                             ( 3 )\r
 \r
 /* When the cMessageID member of the message sent to the LCD task is\r
-mainMESSAGE_STATUS then these definitions are sent in the cMessageValue member\r
+mainMESSAGE_STATUS then these definitions are sent in the ulMessageValue member\r
 of the same message and indicate what the status actually is. */\r
 #define mainERROR_DYNAMIC_TASKS                        ( pdPASS + 1 )\r
 #define mainERROR_COM_TEST                             ( pdPASS + 2 )\r
 #define mainERROR_GEN_QUEUE_TEST               ( pdPASS + 3 )\r
+#define mainERROR_REG_TEST                             ( pdPASS + 4 )\r
 \r
 /* The length of the queue (the number of items the queue can hold) that is used\r
 to send messages from tasks and interrupts the the LCD task. */\r
 #define mainQUEUE_LENGTH                               ( 5 )\r
 \r
 #define mainLCD_TASK_PRIORITY                  ( tskIDLE_PRIORITY + 1 )\r
+#define mainCOM_TEST_PRIORITY                  ( tskIDLE_PRIORITY + 2 )\r
+\r
+/* The LED used by the comtest tasks. See the comtest.c file for more\r
+information.  In this case it is deliberately out of range as there are only\r
+two LEDs, and they are both already in use. */\r
+#define mainCOM_TEST_LED                       ( 3 )\r
+\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
 extern void vRegTest1Task( void *pvParameters );\r
 extern void vRegTest2Task( void *pvParameters );\r
-static void prvCheckTask( void *pvParameters );\r
 static void prvSetupHardware( void );\r
 static void prvTerminalIOTask( void *pvParameters );\r
 static void prvButtonPollTask( void *pvParameters );\r
@@ -102,6 +107,7 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue );
 /*-----------------------------------------------------------*/\r
 \r
 volatile unsigned short usRegTest1Counter = 0, usRegTest2Counter = 0;\r
+volatile unsigned long ulStatsOverflowCount = 0;\r
 \r
 /* The handle of the queue used to send messages from tasks and interrupts to\r
 the LCD task. */\r
@@ -112,32 +118,34 @@ task. */
 typedef struct\r
 {\r
        char cMessageID;        /* << States what the message is. */\r
-       char cMessageValue; /* << States the message value (can be an integer, string pointer, etc. depending on the value of cMessageID. */\r
+       unsigned long ulMessageValue; /* << States the message value (can be an integer, string pointer, etc. depending on the value of cMessageID. */\r
 } xQueueMessage;\r
 /*-----------------------------------------------------------*/\r
 \r
 void main( void )\r
 {\r
        prvSetupHardware();\r
-       \r
+\r
        /* Create the queue used by tasks and interrupts to send strings to the LCD\r
        task. */\r
        xLCDQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( xQueueMessage ) );\r
-       \r
+\r
        if( xLCDQueue != NULL )\r
        {\r
                /* Add the created queue to the queue registry so it can be viewed in\r
                the IAR FreeRTOS state viewer plug-in. */\r
                vQueueAddToRegistry( xLCDQueue, "LCDQueue" );\r
 \r
+               /* Create the standard demo tasks. */\r
+               vAltStartComTestTasks( mainCOM_TEST_PRIORITY, 9600, mainCOM_TEST_LED );\r
+               \r
                /* Create the terminal IO and button poll tasks, as described at the top\r
                of this file. */\r
-               xTaskCreate( prvTerminalIOTask, ( signed char * ) "LCD", configMINIMAL_STACK_SIZE, NULL, mainLCD_TASK_PRIORITY, NULL );\r
-               xTaskCreate( prvButtonPollTask, ( signed char * ) "ButPoll", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
+               xTaskCreate( prvTerminalIOTask, ( signed char * ) "IO", configMINIMAL_STACK_SIZE * 2, NULL, mainLCD_TASK_PRIORITY, NULL );\r
+               xTaskCreate( prvButtonPollTask, ( signed char * ) "BPoll", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
 \r
-               xTaskCreate( vRegTest1Task, "RegTest1", configMINIMAL_STACK_SIZE, NULL, 0, NULL );\r
-               xTaskCreate( vRegTest2Task, "RegTest2", configMINIMAL_STACK_SIZE, NULL, 0, NULL );\r
-               xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+               xTaskCreate( vRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, NULL, 0, NULL );\r
+               xTaskCreate( vRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, NULL, 0, NULL );\r
                vTaskStartScheduler();\r
        }\r
        for( ;; );\r
@@ -180,7 +188,7 @@ static char cBuffer[ 512 ];
                                                                                                informed this task that the up\r
                                                                                                button on the joystick input has\r
                                                                                                been pressed or released. */\r
-                                                                                               sprintf( cBuffer, "Button up = %d", xReceivedMessage.cMessageValue );\r
+                                                                                               sprintf( cBuffer, "Button up = %d", ( int ) xReceivedMessage.ulMessageValue );\r
                                                                                                break;\r
 \r
                        case mainMESSAGE_BUTTON_SEL             :       /* The select button interrupt\r
@@ -191,7 +199,8 @@ static char cBuffer[ 512 ];
                                                                                                the terminal IO window in the IAR\r
                                                                                                embedded workbench. */\r
                                                                                                printf( "\nTask\t     Abs Time\t     %%Time\n*****************************************" );\r
-//                                                                                             vTaskGetRunTimeStats( ( signed char * ) cBuffer );\r
+                                                                                               fflush( stdout );\r
+                                                                                               vTaskGetRunTimeStats( ( signed char * ) cBuffer );\r
 //                                                                                             printf( cBuffer );\r
                                                                                                break;\r
                                                                                                \r
@@ -200,7 +209,7 @@ static char cBuffer[ 512 ];
                                                                                                task of the system status.\r
                                                                                                Generate a string in accordance\r
                                                                                                with the status value. */\r
-                                                                                               prvGenerateStatusMessage( cBuffer, xReceivedMessage.cMessageValue );\r
+                                                                                               prvGenerateStatusMessage( cBuffer, xReceivedMessage.ulMessageValue );\r
                                                                                                break;\r
                                                                                                \r
                        default                                                 :       sprintf( cBuffer, "Unknown message" );\r
@@ -209,7 +218,8 @@ static char cBuffer[ 512 ];
                \r
                /* Output the message that was placed into the cBuffer array within the\r
                switch statement above. */\r
-               printf( "%s", cBuffer );\r
+               printf( "%s : %u\n", cBuffer, ( unsigned int ) xTaskGetTickCount() );\r
+               fflush( stdout );\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -224,10 +234,12 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue )
                                                                                        break;\r
                case mainERROR_DYNAMIC_TASKS    :       sprintf( pcBuffer, "Error: Dynamic tasks" );\r
                                                                                        break;\r
-               case mainERROR_COM_TEST                 :       sprintf( pcBuffer, "Err: loop connected?" ); /* Error in COM test - is the Loopback connector connected? */                                                                                                             \r
+               case mainERROR_COM_TEST                 :       sprintf( pcBuffer, "Err: COM test" ); /* Error in COM test - is the Loopback connector connected? */                                                                                                            \r
                                                                                        break;\r
                case mainERROR_GEN_QUEUE_TEST   :       sprintf( pcBuffer, "Error: Gen Q test" );\r
                                                                                        break;\r
+               case mainERROR_REG_TEST                 :       sprintf( pcBuffer, "Error: Reg test" );\r
+                                                                                       break;\r
                default                                                 :       sprintf( pcBuffer, "Unknown status" );\r
                                                                                        break;\r
        }\r
@@ -245,11 +257,17 @@ xQueueMessage xMessage;
        {\r
                /* Check the button state. */\r
                ucState = ( halButtonsPressed() & BUTTON_UP );\r
+               \r
+               if( ucState != 0 )\r
+               {\r
+                       ucState = pdTRUE;\r
+               }\r
+               \r
                if( ucState != ucLastState )\r
                {\r
                        /* The state has changed, send a message to the LCD task. */\r
                        xMessage.cMessageID = mainMESSAGE_BUTTON_UP;\r
-                       xMessage.cMessageValue = ucState;\r
+                       xMessage.ulMessageValue = ( unsigned long ) ucState;\r
                        ucLastState = ucState;\r
                        xQueueSend( xLCDQueue, &xMessage, portMAX_DELAY );\r
                }\r
@@ -263,46 +281,13 @@ xQueueMessage xMessage;
 \r
 static void prvSetupHardware( void )\r
 {\r
+unsigned long ulCPU_Clock_KHz = ( configCPU_CLOCK_HZ / 1000UL );\r
+\r
        halBoardInit();\r
        halButtonsInit( BUTTON_ALL );\r
        halButtonsInterruptEnable( BUTTON_SELECT );\r
-       LFXT_Start (XT1DRIVE_0);\r
-       Init_FLL_Settle( 25000, 488 );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvCheckTask( void *pvParameters )\r
-{\r
-volatile unsigned short usLastRegTest1Counter = 0, usLastRegTest2Counter = 0;\r
-portTickType xNextWakeTime, xCycleFrequency = mainNO_ERROR_CYCLE_TIME;\r
-const char *pcStatusMessage = "OK";\r
-\r
-       /* Initialise xNextWakeTime - this only needs to be done once. */\r
-       xNextWakeTime = xTaskGetTickCount();\r
-\r
-       for( ;; )\r
-       {\r
-               /* Place this task in the blocked state until it is time to run again. */\r
-               vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );\r
-\r
-               /* Check the reg test tasks are still cycling.  They will stop incrementing\r
-               their loop counters if they encounter an error. */\r
-               if( usRegTest1Counter == usLastRegTest1Counter )\r
-               {\r
-                       pcStatusMessage = "Error: RegTest1";\r
-               }\r
-\r
-               if( usRegTest2Counter == usLastRegTest2Counter )\r
-               {\r
-                       pcStatusMessage = "Error: RegTest2";\r
-               }\r
-\r
-               usLastRegTest1Counter = usRegTest1Counter;\r
-               usLastRegTest2Counter = usRegTest2Counter;\r
-               \r
-               printf( "%s, tick count = %u\n", pcStatusMessage, ( unsigned int ) xTaskGetTickCount() );\r
-               fflush( stdout );\r
-       }\r
+       LFXT_Start( XT1DRIVE_0 );\r
+       Init_FLL_Settle( ( unsigned short ) ulCPU_Clock_KHz, 488 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -313,7 +298,7 @@ const unsigned short usACLK_Frequency_Hz = 32768;
        /* Ensure the timer is stopped. */\r
        TA0CTL = 0;\r
 \r
-       /* Run the timer of the ACLK. */\r
+       /* Run the timer from the ACLK. */\r
        TA0CTL = TASSEL_1;\r
 \r
        /* Clear everything to start with. */\r
@@ -350,8 +335,153 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName
 \r
 void vApplicationIdleHook( void )\r
 {\r
-       __bis_SR_register( LPM3_bits + GIE );\r
+       /* Want to leave the SMCLK running so the COMTest tasks don't fail. */\r
+       __bis_SR_register( LPM1_bits + GIE );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+static unsigned short usLastRegTest1Counter = 0, usLastRegTest2Counter = 0;\r
+static unsigned long ulCounter = 0;\r
+static const unsigned long ulCheckFrequency = 5000UL / portTICK_RATE_MS;\r
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+/* Define the status message that is sent to the LCD task.  By default the\r
+status is PASS. */\r
+static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS };\r
+\r
+       /* This is called from within the tick interrupt and performs the 'check'\r
+       functionality as described in the comments at the top of this file.\r
+\r
+       Is it time to perform the 'check' functionality again? */\r
+       ulCounter++;\r
+       if( ulCounter >= ulCheckFrequency )\r
+       {\r
+               #ifdef LEFT_OVER_FROM_CUT_AND_PASTE\r
+                       /* See if the standard demo tasks are executing as expected, changing\r
+                       the message that is sent to the LCD task from PASS to an error code if\r
+                       any tasks set reports an error. */\r
+                       if( xAreDynamicPriorityTasksStillRunning() != pdPASS )\r
+                       {\r
+                               xStatusMessage.lMessageValue = mainERROR_DYNAMIC_TASKS;\r
+                       }\r
+                       \r
+                       if( xAreGenericQueueTasksStillRunning() != pdPASS )\r
+                       {\r
+                               xStatusMessage.lMessageValue = mainERROR_GEN_QUEUE_TEST;\r
+                       }\r
+               #else\r
+                       /* See if the standard demo tasks are executing as expected, changing\r
+                       the message that is sent to the LCD task from PASS to an error code if\r
+                       any tasks set reports an error. */\r
+                       if( xAreComTestTasksStillRunning() != pdPASS )\r
+                       {\r
+                               xStatusMessage.ulMessageValue = mainERROR_COM_TEST;\r
+                       }\r
+\r
+\r
+                       /* Check the reg test tasks are still cycling.  They will stop incrementing\r
+                       their loop counters if they encounter an error. */\r
+                       if( usRegTest1Counter == usLastRegTest1Counter )\r
+                       {\r
+                               xStatusMessage.ulMessageValue = mainERROR_REG_TEST;\r
+                       }\r
+       \r
+                       if( usRegTest2Counter == usLastRegTest2Counter )\r
+                       {\r
+                               xStatusMessage.ulMessageValue = mainERROR_REG_TEST;\r
+                       }\r
+       \r
+                       usLastRegTest1Counter = usRegTest1Counter;\r
+                       usLastRegTest2Counter = usRegTest2Counter;\r
+               #endif\r
+               \r
+               /* As this is the tick hook the lHigherPriorityTaskWoken parameter is not\r
+               needed (a context switch is going to be performed anyway), but it must\r
+               still be provided. */\r
+               xQueueSendFromISR( xLCDQueue, &xStatusMessage, &xHigherPriorityTaskWoken );\r
+               ulCounter = 0;\r
+       }\r
+\r
+       if( ( ulCounter & 0xff ) == 0 )\r
+       {\r
+               if( ( LED_PORT_OUT & LED_1 ) == 0 )\r
+               {\r
+                       LED_PORT_OUT |= LED_1;\r
+                       LED_PORT_OUT &= ~LED_2;\r
+               }\r
+               else\r
+               {\r
+                       LED_PORT_OUT &= ~LED_1;\r
+                       LED_PORT_OUT |= LED_2;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#pragma vector=PORT2_VECTOR\r
+__interrupt static void prvSelectButtonInterrupt(void)\r
+{\r
+/* Define the message sent to the LCD task from this interrupt. */\r
+static const xQueueMessage xMessage = { mainMESSAGE_BUTTON_SEL, ( unsigned long ) "Select Interrupt!" };\r
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       /* This is the interrupt handler for the joystick select button input.\r
+       The button has been pushed, write a message to the LCD via the LCD task. */\r
+       xQueueSendFromISR( xLCDQueue, &xMessage, &xHigherPriorityTaskWoken );\r
+\r
+       P2IFG = 0;\r
+       \r
+       /* If writing to xLCDQueue caused a task to unblock, and the unblocked task\r
+       has a priority equal to or above the task that this interrupt interrupted,\r
+       then lHigherPriorityTaskWoken will have been set to pdTRUE internally within\r
+       xQueuesendFromISR(), and portEND_SWITCHING_ISR() will ensure that this\r
+       interrupt returns directly to the higher priority unblocked task. */\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vConfigureTimerForRunTimeStats( void )\r
+{\r
+       /* Ensure the timer is stopped. */\r
+       TA1CTL = 0;\r
+\r
+       /* Run the timer from the ACLK/4. */\r
+       TA1CTL = TASSEL_1 | ID__4;\r
+\r
+       /* Clear everything to start with. */\r
+       TA1CTL |= TACLR;\r
+\r
+       /* Enable the interrupts. */\r
+       TA1CCTL0 = CCIE;\r
+\r
+       /* Start up clean. */\r
+       TA1CTL |= TACLR;\r
+\r
+       /* Continuous mode. */\r
+       TA1CTL |= MC__CONTINOUS;\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+#pragma vector=TIMER1_A0_VECTOR\r
+static __interrupt void prvRunTimeStatsOverflowISR( void )\r
+{\r
+       ulStatsOverflowCount++;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+inline unsigned long ulGetRunTimeStatsTime( void )\r
+{\r
+unsigned long ulReturn;\r
+\r
+       TA1CTL &= ~MC__CONTINOUS;\r
+       ulReturn = ( ( ulStatsOverflowCount << 16UL ) | ( unsigned long ) TA1R );\r
+       TA1CTL |= MC__CONTINOUS;\r
+       \r
+       return ulReturn;\r
+}\r
+\r
 \r
 \r
 \r