diff --git a/Demo/MSP430X_MSP430F5438_CCS4/.cdtbuild b/Demo/MSP430X_MSP430F5438_CCS4/.cdtbuild
index d7e95846f..9095ac963 100644
--- a/Demo/MSP430X_MSP430F5438_CCS4/.cdtbuild
+++ b/Demo/MSP430X_MSP430F5438_CCS4/.cdtbuild
@@ -43,7 +43,7 @@
-
+
@@ -137,7 +137,7 @@
-
+
@@ -204,7 +204,7 @@
-
+
+
+
-
+
@@ -319,7 +321,7 @@
-
+
diff --git a/Demo/MSP430X_MSP430F5438_CCS4/CreateProjectDirectoryStructure.bat b/Demo/MSP430X_MSP430F5438_CCS4/CreateProjectDirectoryStructure.bat
index 5dff36f85..4955739fd 100644
--- a/Demo/MSP430X_MSP430F5438_CCS4/CreateProjectDirectoryStructure.bat
+++ b/Demo/MSP430X_MSP430F5438_CCS4/CreateProjectDirectoryStructure.bat
@@ -23,6 +23,7 @@ IF EXIST FreeRTOS_Source Goto END
copy ..\..\Source\tasks.c FreeRTOS_Source
copy ..\..\Source\queue.c FreeRTOS_Source
copy ..\..\Source\list.c FreeRTOS_Source
+ copy ..\..\Source\timers.c FreeRTOS_Source
REM Copy the common header files
@@ -38,6 +39,8 @@ IF EXIST FreeRTOS_Source Goto END
copy ..\Common\minimal\dynamic.c Demo_Source\Common_Demo_Files
copy ..\Common\minimal\comtest.c Demo_Source\Common_Demo_Files
copy ..\Common\minimal\GenQTest.c Demo_Source\Common_Demo_Files
+ copy ..\Common\minimal\TimerDemo.c Demo_Source\Common_Demo_Files
+ copy ..\Common\minimal\countsem.c Demo_Source\Common_Demo_Files
REM Copy the common demo file headers.
copy ..\Common\include\dynamic.h Demo_Source\Common_Demo_Files\include
@@ -46,5 +49,7 @@ IF EXIST FreeRTOS_Source Goto END
copy ..\Common\include\GenQTest.h Demo_Source\Common_Demo_Files\include
copy ..\Common\include\serial.h Demo_Source\Common_Demo_Files\include
copy ..\Common\include\partest.h Demo_Source\Common_Demo_Files\include
+ copy ..\Common\include\TimerDemo.h Demo_Source\Common_Demo_Files\include
+ copy ..\Common\include\countsem.h Demo_Source\Common_Demo_Files\include
-: END
\ No newline at end of file
+: END
diff --git a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/FreeRTOSConfig.h b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/FreeRTOSConfig.h
index f2ac3595e..b0316d7fd 100644
--- a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/FreeRTOSConfig.h
+++ b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/FreeRTOSConfig.h
@@ -81,18 +81,19 @@
#define configCPU_CLOCK_HZ ( 25000000UL )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
-#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 9 * 1024 ) )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
-#define configUSE_TRACE_FACILITY 1
-#define configUSE_16_BIT_TICKS 0
+#define configUSE_TRACE_FACILITY 0
+#define configUSE_16_BIT_TICKS 1
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 0
-#define configGENERATE_RUN_TIME_STATS 1
+#define configGENERATE_RUN_TIME_STATS 0
#define configCHECK_FOR_STACK_OVERFLOW 2
-#define configUSE_RECURSIVE_MUTEXES 0
+#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
#ifdef __LARGE_DATA_MODEL__
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 )
@@ -104,6 +105,12 @@
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+/* Software timer definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY ( 3 )
+#define configTIMER_QUEUE_LENGTH 10
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
+
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
@@ -121,39 +128,8 @@ vector for the chosen tick interrupt source. This implementation of
vApplicationSetupTimerInterrupt() generates the tick from timer A0, so in this
case configTICK_VECTOR is set to TIMER0_A0_VECTOR. */
#define configTICK_VECTOR TIMER0_A0_VECTOR
-
-extern void vConfigureTimerForRunTimeStats( void );
-extern volatile unsigned long ulStatsOverflowCount;
-
-/* Configure a 16 bit timer to generate the time base for the run time stats.
-The timer is configured to interrupt each time it overflows so a count of
-overflows can be kept - that way a 32 bit time value can be constructed from
-the timers current count value and the number of overflows. */
-#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
-/* Construct a 32 bit time value for use as the run time stats time base. This
-comes from the current value of a 16 bit timer combined with the number of times
-the timer has overflowed. */
-#define portALT_GET_RUN_TIME_COUNTER_VALUE( ulCountValue ) \
- { \
- /* Stop the counter counting temporarily. */ \
- TA1CTL &= ~MC__CONTINOUS; \
- \
- /* Check to see if any counter overflow interrupts are pending. */ \
- if( ( TA1CTL & TAIFG ) != 0 ) \
- { \
- /* An overflow has occurred but not yet been processed. */ \
- ulStatsOverflowCount++; \
- \
- /* Clear the interrupt. */ \
- TA1CTL &= ~TAIFG; \
- } \
- \
- /* Generate a 32 bit counter value by combinging the current peripheral \
- counter value with the number of overflows. */ \
- ulCountValue = ( ulStatsOverflowCount << 16UL ); \
- ulCountValue |= ( unsigned long ) TA1R; \
- TA1CTL |= MC__CONTINOUS; \
- }
-#endif /*0*/
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
+
+#endif /* FREERTOS_CONFIG_H */
diff --git a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/main.c b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/main.c
index f9e021c38..8b357d8fa 100644
--- a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/main.c
+++ b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/main.c
@@ -62,8 +62,8 @@
* provide no particular functionality but do provide good examples 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:
+ * In addition to the standard demo tasks, the following tasks, interrupts tests
+ * and timers 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
@@ -85,35 +85,24 @@
* 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.
+ * Button Interrupt - 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 then prints out a string to say the
+ * joystick select button was pressed.
*
* 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.
+ * driven tasks, and slowing the tick interrupt frequency, etc.
*
- * "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.
+ * "Check" callback function - Called each time the 'check' timer expires. The
+ * check timer 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.
*
* "Reg test" tasks - These fill the registers with known values, then check
* that each register still contains its expected value. Each task uses
@@ -122,9 +111,12 @@
* test loop. A register containing an unexpected value is indicative of an
* error in the context switching mechanism and will result in a branch to a
* null loop - which in turn will prevent the check variable from incrementing
- * any further and allow the check task (described a above) to determine that an
- * error has occurred. The nature of the reg test tasks necessitates that they
- * are written in assembly code.
+ * any further and allow the check timer callback (described a above) to
+ * determine that an error has occurred. The nature of the reg test tasks
+ * necessitates that they are written in assembly code.
+ *
+ * Tick hook function - called inside the RTOS tick function, this simple
+ * example does nothing but toggle an LED.
*
* *NOTE 1* vApplicationSetupTimerInterrupt() is called by the kernel to let
* the application set up a timer to generate the tick interrupt. In this
@@ -138,6 +130,7 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
+#include "timers.h"
#include "queue.h"
/* Hardware includes. */
@@ -149,6 +142,8 @@
#include "dynamic.h"
#include "comtest2.h"
#include "GenQTest.h"
+#include "TimerDemo.h"
+#include "countsem.h"
/* Codes sent within messages to the LCD task so the LCD task can interpret
exactly what the message it just received was. These are sent in the
@@ -164,6 +159,8 @@ of the same message and indicate what the status actually is. */
#define mainERROR_COM_TEST ( pdPASS + 2 )
#define mainERROR_GEN_QUEUE_TEST ( pdPASS + 3 )
#define mainERROR_REG_TEST ( pdPASS + 4 )
+#define mainERROR_TIMER_TEST ( pdPASS + 5 )
+#define mainERROR_COUNT_SEM_TEST ( pdPASS + 6 )
/* 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. */
@@ -178,14 +175,24 @@ to send messages from tasks and interrupts the the LCD task. */
information. */
#define mainCOM_TEST_LED ( 1 )
-/* The baud rate used by the comtest tasks described at the top of this file. */
-#define mainCOM_TEST_BAUD_RATE ( 38400 )
+/* The baud rate used by the comtest tasks. */
+#define mainCOM_TEST_BAUD_RATE ( 115200 )
/* The maximum number of lines of text that can be displayed on the LCD. */
#define mainMAX_LCD_LINES ( 8 )
/* Just used to ensure parameters are passed into tasks correctly. */
#define mainTASK_PARAMETER_CHECK_VALUE ( ( void * ) 0xDEAD )
+
+/* The base period used by the timer test tasks. */
+#define mainTIMER_TEST_PERIOD ( 50 )
+
+/* The frequency at which the check timer (described in the comments at the top
+of this file) will call its callback function. */
+#define mainCHECK_TIMER_PERIOD ( 5000UL / ( unsigned long ) portTICK_RATE_MS )
+
+/* Misc. */
+#define mainDONT_BLOCK ( 0 )
/*-----------------------------------------------------------*/
/*
@@ -215,7 +222,12 @@ static void prvButtonPollTask( 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 );
+static void prvGenerateStatusMessage( char *pcBuffer, unsigned long ulStatusValue );
+
+/*
+ * Defines the 'check' functionality as described at the top of this file. This
+ * function is the callback function for the 'check' timer. */
+static void vCheckTimerCallback( xTimerHandle xTimer );
/*-----------------------------------------------------------*/
@@ -229,6 +241,9 @@ volatile unsigned short usRegTest1Counter = 0, usRegTest2Counter = 0;
the LCD task. */
static xQueueHandle xLCDQueue = NULL;
+/* The 'check' timer, as described at the top of this file. */
+static xTimerHandle xCheckTimer = NULL;
+
/* The definition of each message sent from tasks and interrupts to the LCD
task. */
typedef struct
@@ -239,10 +254,6 @@ typedef struct
/*-----------------------------------------------------------*/
-/* The linker script tests the FreeRTOS ports use of 20bit addresses by
-locating all code in high memory. The following pragma ensures that main
-remains in low memory. */
-#pragma CODE_SECTION(main,".main")
void main( void )
{
/* Configure the peripherals used by this demo application. This includes
@@ -261,6 +272,15 @@ void main( void )
vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );
vStartDynamicPriorityTasks();
vStartGenericQueueTasks( mainGENERIC_QUEUE_TEST_PRIORITY );
+ vStartCountingSemaphoreTasks();
+
+ /* Note that creating the timer test/demo tasks will fill the timer
+ command queue. This is intentional, and forms part of the test the tasks
+ perform. It does mean however that, after this function is called, no
+ more timer commands can be sent until after the scheduler has been
+ started (at which point the timer daemon will drained the timer command
+ queue, freeing up space for more commands to be received). */
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
/* Create the LCD, button poll and register test tasks, as described at
the top of this file. */
@@ -269,6 +289,13 @@ void main( void )
xTaskCreate( vRegTest1Task, ( signed char * ) "Reg1", configMINIMAL_STACK_SIZE, NULL, 0, NULL );
xTaskCreate( vRegTest2Task, ( signed char * ) "Reg2", configMINIMAL_STACK_SIZE, NULL, 0, NULL );
+ /* Create the 'check' timer - the timer that periodically calls the
+ check function as described at the top of this file. Note that, for
+ the reasons stated in the comments above the call to
+ vStartTimerDemoTask(), that the check timer is not actually started
+ until after the scheduler has been started. */
+ xCheckTimer = xTimerCreate( ( const signed char * ) "Check timer", mainCHECK_TIMER_PERIOD, pdTRUE, ( void * ) 0, vCheckTimerCallback );
+
/* Start the scheduler. */
vTaskStartScheduler();
}
@@ -289,26 +316,32 @@ xQueueMessage xReceivedMessage;
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 ];
+static char cBuffer[ 50 ];
unsigned char ucLine = 1;
+ /* Now the scheduler has been started (it must have been for this task to
+ be running), start the check timer too. The call to xTimerStart() will
+ block until the command has been accepted. */
+ if( xCheckTimer != NULL )
+ {
+ xTimerStart( xCheckTimer, portMAX_DELAY );
+ }
- /* 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.
-
- This is also the only function that is permitted to access the LCD.
+ /* This is 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", ( int ) xPortGetFreeHeapSize() );
- fflush( stdout );
+ is done after a short delay to ensure all the demo tasks have created all
+ the objects they are going to use. */
+ vTaskDelay( mainTIMER_TEST_PERIOD * 10 );
+ sprintf( cBuffer, "%d heap free", ( int ) xPortGetFreeHeapSize() );
+ halLcdPrintLine( cBuffer, ucLine, OVERWRITE_TEXT );
+ ucLine++;
/* Just as a test of the port, and for no functional reason, check the task
parameter contains its expected value. */
if( pvParameters != mainTASK_PARAMETER_CHECK_VALUE )
{
- halLcdPrintLine( "Invalid parameter", ucLine, OVERWRITE_TEXT );
+ halLcdPrintLine( "Invalid parameter", ucLine, OVERWRITE_TEXT );
ucLine++;
}
@@ -340,33 +373,13 @@ unsigned char ucLine = 1;
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*****************************************" );
- fflush( stdout );
- vTaskGetRunTimeStats( ( signed char * ) cBuffer );
- printf( cBuffer );
- fflush( stdout );
-
- /* Also generate and output a
- table of task states. */
- printf( "\nTask\t\tState Priority\tStack\t#\n*****************************************" );
- fflush( stdout );
- vTaskList( ( signed char * ) cBuffer );
- printf( cBuffer );
- fflush( stdout );
-
- /* Finally print out a message
- to the LCD - in this case the
- pointer to the string to print
- is sent directly in the
- ulMessageValue member of the
- message. This just demonstrates
- a different communication
- technique. */
+ select button has been pressed.
+ In this case the pointer to the
+ string to print is sent directly
+ in the ulMessageValue member of
+ the message. This just
+ demonstrates a different
+ communication technique. */
sprintf( cBuffer, "%s", ( char * ) xReceivedMessage.ulMessageValue );
break;
@@ -391,11 +404,11 @@ unsigned char ucLine = 1;
}
/*-----------------------------------------------------------*/
-static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue )
+static void prvGenerateStatusMessage( char *pcBuffer, unsigned long ulStatusValue )
{
/* Just a utility function to convert a status value into a meaningful
string for output onto the LCD. */
- switch( lStatusValue )
+ switch( ulStatusValue )
{
case pdPASS : sprintf( pcBuffer, "Status = PASS" );
break;
@@ -407,6 +420,10 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue )
break;
case mainERROR_REG_TEST : sprintf( pcBuffer, "Error: Reg test" );
break;
+ case mainERROR_TIMER_TEST : sprintf( pcBuffer, "Error: Tmr test" );
+ break;
+ case mainERROR_COUNT_SEM_TEST : sprintf( pcBuffer, "Error: Count sem" );
+ break;
default : sprintf( pcBuffer, "Unknown status" );
break;
}
@@ -447,6 +464,68 @@ xQueueMessage xMessage;
}
/*-----------------------------------------------------------*/
+static void vCheckTimerCallback( xTimerHandle xTimer )
+{
+static unsigned short usLastRegTest1Counter = 0, usLastRegTest2Counter = 0;
+
+/* Define the status message that is sent to the LCD task. By default the
+status is PASS. */
+static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS };
+
+ /* This is the callback function used by the 'check' timer, as described
+ at the top of this file. */
+
+ /* The parameter is not used. */
+ ( void ) xTimer;
+
+ /* 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( xAreComTestTasksStillRunning() != pdPASS )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_COM_TEST;
+ }
+
+ if( xAreDynamicPriorityTasksStillRunning() != pdPASS )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_DYNAMIC_TASKS;
+ }
+
+ if( xAreGenericQueueTasksStillRunning() != pdPASS )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_GEN_QUEUE_TEST;
+ }
+
+ if( xAreCountingSemaphoreTasksStillRunning() != pdPASS )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_COUNT_SEM_TEST;
+ }
+
+ if( xAreTimerDemoTasksStillRunning( ( portTickType ) mainCHECK_TIMER_PERIOD ) != pdPASS )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_TIMER_TEST;
+ }
+
+ /* Check the reg test tasks are still cycling. They will stop
+ incrementing their loop counters if they encounter an error. */
+ if( usRegTest1Counter == usLastRegTest1Counter )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_REG_TEST;
+ }
+
+ if( usRegTest2Counter == usLastRegTest2Counter )
+ {
+ xStatusMessage.ulMessageValue = mainERROR_REG_TEST;
+ }
+
+ usLastRegTest1Counter = usRegTest1Counter;
+ usLastRegTest2Counter = usRegTest2Counter;
+
+ /* This is called from a timer callback so must not block! */
+ xQueueSendToBack( xLCDQueue, &xStatusMessage, mainDONT_BLOCK );
+}
+/*-----------------------------------------------------------*/
+
static void prvSetupHardware( void )
{
/* Convert a Hz value to a KHz value, as required by the Init_FLL_Settle()
@@ -480,63 +559,13 @@ unsigned long ulCPU_Clock_KHz = ( configCPU_CLOCK_HZ / 1000UL );
}
/*-----------------------------------------------------------*/
+
void vApplicationTickHook( void )
{
-static unsigned short usLastRegTest1Counter = 0, usLastRegTest2Counter = 0;
static unsigned long ulCounter = 0;
-static const unsigned long ulCheckFrequency = 5000UL / portTICK_RATE_MS;
-portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
-/* Define the status message that is sent to the LCD task. By default the
-status is PASS. */
-static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS };
-
- /* 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? */
+ /* Is it time to toggle the LED 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( xAreComTestTasksStillRunning() != pdPASS )
- {
- xStatusMessage.ulMessageValue = mainERROR_COM_TEST;
- }
-
- if( xAreDynamicPriorityTasksStillRunning() != pdPASS )
- {
- xStatusMessage.ulMessageValue = mainERROR_DYNAMIC_TASKS;
- }
-
- if( xAreGenericQueueTasksStillRunning() != pdPASS )
- {
- xStatusMessage.ulMessageValue = mainERROR_GEN_QUEUE_TEST;
- }
-
- /* Check the reg test tasks are still cycling. They will stop
- incrementing their loop counters if they encounter an error. */
- if( usRegTest1Counter == usLastRegTest1Counter )
- {
- xStatusMessage.ulMessageValue = mainERROR_REG_TEST;
- }
-
- if( usRegTest2Counter == usLastRegTest2Counter )
- {
- xStatusMessage.ulMessageValue = mainERROR_REG_TEST;
- }
-
- usLastRegTest1Counter = usRegTest1Counter;
- usLastRegTest2Counter = usRegTest2Counter;
-
- /* 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, &xHigherPriorityTaskWoken );
- ulCounter = 0;
- }
/* Just periodically toggle an LED to show that the tick interrupt is
running. Note that this access LED_PORT_OUT in a non-atomic way, so tasks
@@ -642,3 +671,4 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName
}
/*-----------------------------------------------------------*/
+
diff --git a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/printf-stdarg.c b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/printf-stdarg.c
new file mode 100644
index 000000000..b5ac41be7
--- /dev/null
+++ b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/printf-stdarg.c
@@ -0,0 +1,293 @@
+/*
+ Copyright 2001, 2002 Georges Menie (www.menie.org)
+ stdarg version contributed by Christian Ettinger
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ putchar is the only external dependency for this file,
+ if you have a working putchar, leave it commented out.
+ If not, uncomment the define below and
+ replace outbyte(c) by your own function call.
+
+*/
+
+#define putchar(c) c
+
+#include
+
+static void printchar(char **str, int c)
+{
+ //extern int putchar(int c);
+
+ if (str) {
+ **str = (char)c;
+ ++(*str);
+ }
+ else
+ {
+ (void)putchar(c);
+ }
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+
+static int prints(char **out, const char *string, int width, int pad)
+{
+ register int pc = 0, padchar = ' ';
+
+ if (width > 0) {
+ register int len = 0;
+ register const char *ptr;
+ for (ptr = string; *ptr; ++ptr) ++len;
+ if (len >= width) width = 0;
+ else width -= len;
+ if (pad & PAD_ZERO) padchar = '0';
+ }
+ if (!(pad & PAD_RIGHT)) {
+ for ( ; width > 0; --width) {
+ printchar (out, padchar);
+ ++pc;
+ }
+ }
+ for ( ; *string ; ++string) {
+ printchar (out, *string);
+ ++pc;
+ }
+ for ( ; width > 0; --width) {
+ printchar (out, padchar);
+ ++pc;
+ }
+
+ return pc;
+}
+
+/* the following should be enough for 32 bit int */
+#define PRINT_BUF_LEN 12
+
+static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
+{
+ char print_buf[PRINT_BUF_LEN];
+ register char *s;
+ register int t, neg = 0, pc = 0;
+ register unsigned int u = (unsigned int)i;
+
+ if (i == 0) {
+ print_buf[0] = '0';
+ print_buf[1] = '\0';
+ return prints (out, print_buf, width, pad);
+ }
+
+ if (sg && b == 10 && i < 0) {
+ neg = 1;
+ u = (unsigned int)-i;
+ }
+
+ s = print_buf + PRINT_BUF_LEN-1;
+ *s = '\0';
+
+ while (u) {
+ t = (unsigned int)u % b;
+ if( t >= 10 )
+ t += letbase - '0' - 10;
+ *--s = (char)(t + '0');
+ u /= b;
+ }
+
+ if (neg) {
+ if( width && (pad & PAD_ZERO) ) {
+ printchar (out, '-');
+ ++pc;
+ --width;
+ }
+ else {
+ *--s = '-';
+ }
+ }
+
+ return pc + prints (out, s, width, pad);
+}
+
+static int print( char **out, const char *format, va_list args )
+{
+ register int width, pad;
+ register int pc = 0;
+ char scr[2];
+
+ for (; *format != 0; ++format) {
+ if (*format == '%') {
+ ++format;
+ width = pad = 0;
+ if (*format == '\0') break;
+ if (*format == '%') goto out;
+ if (*format == '-') {
+ ++format;
+ pad = PAD_RIGHT;
+ }
+ while (*format == '0') {
+ ++format;
+ pad |= PAD_ZERO;
+ }
+ for ( ; *format >= '0' && *format <= '9'; ++format) {
+ width *= 10;
+ width += *format - '0';
+ }
+ if( *format == 's' ) {
+ register char *s = (char *)va_arg( args, int );
+ pc += prints (out, s?s:"(null)", width, pad);
+ continue;
+ }
+ if( *format == 'd' ) {
+ pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
+ continue;
+ }
+ if( *format == 'x' ) {
+ pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');
+ continue;
+ }
+ if( *format == 'X' ) {
+ pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');
+ continue;
+ }
+ if( *format == 'u' ) {
+ pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
+ continue;
+ }
+ if( *format == 'c' ) {
+ /* char are converted to int then pushed on the stack */
+ scr[0] = (char)va_arg( args, int );
+ scr[1] = '\0';
+ pc += prints (out, scr, width, pad);
+ continue;
+ }
+ }
+ else {
+ out:
+ printchar (out, *format);
+ ++pc;
+ }
+ }
+ if (out) **out = '\0';
+ va_end( args );
+ return pc;
+}
+
+int printf(const char *format, ...)
+{
+ va_list args;
+
+ va_start( args, format );
+ return print( 0, format, args );
+}
+
+int sprintf(char *out, const char *format, ...)
+{
+ va_list args;
+
+ va_start( args, format );
+ return print( &out, format, args );
+}
+
+
+int snprintf( char *buf, unsigned int count, const char *format, ... )
+{
+ va_list args;
+
+ ( void ) count;
+
+ va_start( args, format );
+ return print( &buf, format, args );
+}
+
+
+#ifdef TEST_PRINTF
+int main(void)
+{
+ char *ptr = "Hello world!";
+ char *np = 0;
+ int i = 5;
+ unsigned int bs = sizeof(int)*8;
+ int mi;
+ char buf[80];
+
+ mi = (1 << (bs-1)) + 1;
+ printf("%s\n", ptr);
+ printf("printf test\n");
+ printf("%s is null pointer\n", np);
+ printf("%d = 5\n", i);
+ printf("%d = - max int\n", mi);
+ printf("char %c = 'a'\n", 'a');
+ printf("hex %x = ff\n", 0xff);
+ printf("hex %02x = 00\n", 0);
+ printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
+ printf("%d %s(s)%", 0, "message");
+ printf("\n");
+ printf("%d %s(s) with %%\n", 0, "message");
+ sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);
+ sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);
+ sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);
+ sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);
+ sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);
+ sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);
+ sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);
+ sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);
+
+ return 0;
+}
+
+/*
+ * if you compile this file with
+ * gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
+ * you will get a normal warning:
+ * printf.c:214: warning: spurious trailing `%' in format
+ * this line is testing an invalid % at the end of the format string.
+ *
+ * this should display (on 32bit int machine) :
+ *
+ * Hello world!
+ * printf test
+ * (null) is null pointer
+ * 5 = 5
+ * -2147483647 = - max int
+ * char a = 'a'
+ * hex ff = ff
+ * hex 00 = 00
+ * signed -3 = unsigned 4294967293 = hex fffffffd
+ * 0 message(s)
+ * 0 message(s) with %
+ * justif: "left "
+ * justif: " right"
+ * 3: 0003 zero padded
+ * 3: 3 left justif.
+ * 3: 3 right justif.
+ * -3: -003 zero padded
+ * -3: -3 left justif.
+ * -3: -3 right justif.
+ */
+
+#endif
+
+
+/* To keep linker happy. */
+int write( int i, char* c, int n)
+{
+ (void)i;
+ (void)n;
+ (void)c;
+ return 0;
+}
+
diff --git a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/serial.c b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/serial.c
index db2789eca..b85079a43 100644
--- a/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/serial.c
+++ b/Demo/MSP430X_MSP430F5438_CCS4/Demo_Source/serial.c
@@ -95,8 +95,8 @@ unsigned portLONG ulBaudRateCount;
portENTER_CRITICAL();
{
/* Create the queues used by the com test task. */
- xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
- xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
+ xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
+ xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
/* Reset UART. */
UCA1CTL1 |= UCSWRST;
@@ -105,11 +105,11 @@ unsigned portLONG ulBaudRateCount;
UCA1CTL1 = UCSSEL0 | UCSSEL1;
/* Setup baud rate low byte. */
- UCA1BR0 = ( unsigned portCHAR ) ( ulBaudRateCount & ( unsigned portLONG ) 0xff );
+ UCA1BR0 = ( unsigned portCHAR ) ( ulBaudRateCount & ( unsigned long ) 0xff );
/* Setup baud rate high byte. */
ulBaudRateCount >>= 8UL;
- UCA1BR1 = ( unsigned portCHAR ) ( ulBaudRateCount & ( unsigned portLONG ) 0xff );
+ UCA1BR1 = ( unsigned portCHAR ) ( ulBaudRateCount & ( unsigned long ) 0xff );
/* UCLISTEN sets loopback mode! */
UCA1STAT = UCLISTEN;
@@ -152,16 +152,21 @@ signed portBASE_TYPE xReturn;
completed and switched itself off. */
xReturn = xQueueSend( xCharsForTx, &cOutChar, xBlockTime );
UCA1IE |= UCTXIE;
-
+
return xReturn;
}
/*-----------------------------------------------------------*/
+/* The implementation of this interrupt is provided to demonstrate the use
+of queues from inside an interrupt service routine. It is *not* intended to
+be an efficient interrupt implementation. A real application should make use
+of the DMA. Or, as a minimum, transmission and reception could use a simple
+RAM ring buffer, and synchronise with a task using a semaphore when a complete
+message has been received or transmitted. */
#pragma vector=USCI_A1_VECTOR
interrupt void prvUSCI_A1_ISR( void )
{
-signed portCHAR cChar;
-portBASE_TYPE xTaskWoken = pdFALSE;
+signed char cChar;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
while( ( UCA1IFG & UCRXIFG ) != 0 )
@@ -177,7 +182,7 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
{
/* The previous character has been transmitted. See if there are any
further characters waiting transmission. */
- if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xTaskWoken ) == pdTRUE )
+ if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
{
/* There was another character queued - transmit it now. */
UCA1TXBUF = cChar;
@@ -189,7 +194,7 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
UCA1IE &= ~UCTXIE;
}
}
-
+
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
/* If writing to a queue caused a task to unblock, and the unblocked task
diff --git a/Demo/MSP430X_MSP430F5438_CCS4/lnk_msp430f5438a.cmd b/Demo/MSP430X_MSP430F5438_CCS4/lnk_msp430f5438a.cmd
index 9238b3473..5f9258739 100644
--- a/Demo/MSP430X_MSP430F5438_CCS4/lnk_msp430f5438a.cmd
+++ b/Demo/MSP430X_MSP430F5438_CCS4/lnk_msp430f5438a.cmd
@@ -110,7 +110,7 @@ SECTIONS
/* Original line. */
.text : {}>> FLASH | FLASH2 /* CODE */
/* Modified line. */
-/* .text : {}>> FLASH2 */ /* CODE */
+/* .text : {}>> FLASH2 */ /* CODE */
.main : {} > FLASH
.text:_isr : {} > FLASH /* ISR CODE SPACE */
.cinit : {} > FLASH /* INITIALIZATION TABLES */