]> git.sur5r.net Git - freertos/blobdiff - Demo/MSP430X_MSP430F5438_IAR/main.c
Add the debugger settings to the MSP430X IAR demo directory.
[freertos] / Demo / MSP430X_MSP430F5438_IAR / main.c
index 4bcfe27ed5a6761091032474a74c14f5bbb29e12..9a922b81cb9b82cd49b208071de17aa79b7107b3 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
+/* Standard demo includes. */\r
+#include "ParTest.h"\r
+#include "dynamic.h"\r
+#include "comtest2.h"\r
+#include "GenQTest.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
 cMessageID member of the message structure (defined below). */\r
@@ -67,7 +77,7 @@ 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
@@ -79,7 +89,16 @@ to send messages from tasks and interrupts the the LCD task. */
 #define mainQUEUE_LENGTH                               ( 5 )\r
 \r
 #define mainLCD_TASK_PRIORITY                  ( tskIDLE_PRIORITY + 1 )\r
+#define mainCOM_TEST_PRIORITY                  ( tskIDLE_PRIORITY + 2 )\r
+#define mainGENERIC_QUEUE_TEST_PRIORITY        ( tskIDLE_PRIORITY )\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
+/* The baud rate used by the comtest tasks described at the top of this file. */\r
+#define mainCOM_TEST_BAUD_RATE                 ( 9600 )\r
 /*-----------------------------------------------------------*/\r
 \r
 extern void vRegTest1Task( void *pvParameters );\r
@@ -92,6 +111,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
@@ -102,33 +122,40 @@ 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, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
+               vStartDynamicPriorityTasks();\r
+               vStartGenericQueueTasks( mainGENERIC_QUEUE_TEST_PRIORITY );\r
+               \r
                /* Create the terminal IO and button poll tasks, as described at the top\r
                of this file. */\r
-               xTaskCreate( prvTerminalIOTask, ( signed char * ) "IO", 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
+               /* Create the register test tasks as described at the top of this file. */\r
+               xTaskCreate( vRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, NULL, 0, NULL );\r
+               xTaskCreate( vRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, NULL, 0, NULL );\r
                vTaskStartScheduler();\r
        }\r
+       \r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -142,6 +169,8 @@ 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\r
 when the task is created. */\r
 static char cBuffer[ 512 ];\r
+unsigned char ucLine = 1;\r
+\r
 \r
        /* This function is the only function that uses printf().  If printf() is\r
        used from any other function then some sort of mutual exclusion on stdout\r
@@ -162,6 +191,13 @@ static char cBuffer[ 512 ];
                has been received. */\r
                xQueueReceive( xLCDQueue, &xReceivedMessage, portMAX_DELAY );\r
 \r
+               /* Clear the LCD if no room remains for any more text output. */\r
+               if( ucLine > 8 )\r
+               {\r
+                       halLcdClearScreen();\r
+                       ucLine = 0;\r
+               }\r
+               \r
                /* What is this message?  What does it contain? */\r
                switch( xReceivedMessage.cMessageID )\r
                {\r
@@ -169,7 +205,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
@@ -180,8 +216,20 @@ 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
-//                                                                                             printf( cBuffer );\r
+                                                                                               fflush( stdout );\r
+                                                                                               vTaskGetRunTimeStats( ( signed char * ) cBuffer );\r
+                                                                                               printf( cBuffer );\r
+                                                                                               fflush( stdout );\r
+                                                                                               \r
+                                                                                               /* Also print out a message to\r
+                                                                                               the LCD - in this case the\r
+                                                                                               pointer to the string to print\r
+                                                                                               is sent directly in the\r
+                                                                                               lMessageValue member of the\r
+                                                                                               message.  This just demonstrates\r
+                                                                                               a different communication\r
+                                                                                               technique. */\r
+                                                                                               sprintf( cBuffer, "%s", ( char * ) xReceivedMessage.ulMessageValue );\r
                                                                                                break;\r
                                                                                                \r
                        case mainMESSAGE_STATUS                 :       /* The tick interrupt hook\r
@@ -189,17 +237,15 @@ 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
                                                                                                break;\r
                }\r
                \r
-               /* Output the message that was placed into the cBuffer array within the\r
-               switch statement above. */\r
-               printf( "%s : %u\n", cBuffer, ( unsigned int ) xTaskGetTickCount() );\r
-               fflush( stdout );\r
+               halLcdPrintLine( cBuffer, ucLine,  OVERWRITE_TEXT );\r
+               ucLine++;\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -210,11 +256,11 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue )
        string for output onto the LCD. */\r
        switch( lStatusValue )\r
        {\r
-               case pdPASS                                             :       sprintf( pcBuffer, "Task status = PASS" );\r
+               case pdPASS                                             :       sprintf( pcBuffer, "Status = PASS" );\r
                                                                                        break;\r
-               case mainERROR_DYNAMIC_TASKS    :       sprintf( pcBuffer, "Error: Dynamic tasks" );\r
+               case mainERROR_DYNAMIC_TASKS    :       sprintf( pcBuffer, "Err: Dynamic tsks" );\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
@@ -247,7 +293,7 @@ xQueueMessage xMessage;
                {\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
@@ -261,11 +307,24 @@ xQueueMessage xMessage;
 \r
 static void prvSetupHardware( void )\r
 {\r
+unsigned long ulCPU_Clock_KHz = ( configCPU_CLOCK_HZ / 1000UL );\r
+\r
        halBoardInit();\r
+\r
+       LFXT_Start( XT1DRIVE_0 );\r
+       Init_FLL_Settle( ( unsigned short ) ulCPU_Clock_KHz, 488 );\r
+\r
        halButtonsInit( BUTTON_ALL );\r
        halButtonsInterruptEnable( BUTTON_SELECT );\r
-       LFXT_Start (XT1DRIVE_0);\r
-       Init_FLL_Settle( 18000, 488 );\r
+       halLcdInit();\r
+       halLcdBackLightInit();\r
+       halLcdSetBackLight( 0 );\r
+       halLcdSetContrast( 100 );\r
+       halLcdClearScreen();\r
+       \r
+       halLcdPrintLine( " www.FreeRTOS.org", 0,  OVERWRITE_TEXT );\r
+       \r
+while( ( halButtonsPressed() & BUTTON_UP ) == 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -276,7 +335,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
@@ -313,7 +372,8 @@ 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
@@ -335,40 +395,38 @@ static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS };
        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( xAreComTestTasksStillRunning() != pdPASS )\r
-                       {\r
-                               xStatusMessage.lMessageValue = mainERROR_COM_TEST;\r
-                       }\r
-                       \r
-                       if( xAreGenericQueueTasksStillRunning() != pdPASS )\r
-                       {\r
-                               xStatusMessage.lMessageValue = mainERROR_GEN_QUEUE_TEST;\r
-                       }\r
-               #else\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.cMessageValue = mainERROR_REG_TEST;\r
-                       }\r
-       \r
-                       if( usRegTest2Counter == usLastRegTest2Counter )\r
-                       {\r
-                               xStatusMessage.cMessageValue = mainERROR_REG_TEST;\r
-                       }\r
-       \r
-                       usLastRegTest1Counter = usRegTest1Counter;\r
-                       usLastRegTest2Counter = usRegTest2Counter;\r
-               #endif\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
+               if( xAreDynamicPriorityTasksStillRunning() != pdPASS )\r
+               {\r
+                       xStatusMessage.ulMessageValue = mainERROR_DYNAMIC_TASKS;\r
+               }\r
+               \r
+               if( xAreGenericQueueTasksStillRunning() != pdPASS )\r
+               {\r
+                       xStatusMessage.ulMessageValue = mainERROR_GEN_QUEUE_TEST;\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
                \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
@@ -391,5 +449,70 @@ static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS };
                }\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