Convert SmartFusion2 CLI to use the interrupt UART driver functions instead of the polled UART driver functions.

This commit is contained in:
Richard Barry 2013-05-12 13:02:16 +00:00
parent 5ff880fee8
commit 063c05ccad
7 changed files with 222 additions and 112 deletions

View File

@ -50,6 +50,7 @@
</option>
<option id="gnu.c.compiler.option.misc.verbose.1351799799" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" value="true" valueType="boolean"/>
<option id="gnu.c.compiler.option.optimization.flags.435998408" name="Other optimization flags" superClass="gnu.c.compiler.option.optimization.flags" value="-ffunction-sections -fdata-sections" valueType="string"/>
<option id="gnu.c.compiler.option.misc.other.1001754914" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -Wextra" valueType="string"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.2036217646" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.cross.cortexm3.exe.debug.612642130" name="GNU C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.cross.cortexm3.exe.debug">

View File

@ -98,18 +98,14 @@
#include <stdint.h>
extern uint32_t SystemCoreClock;
/* Driver includes required for UART IO. */
#include "drivers/mss_uart/mss_uart.h"
extern const mss_uart_instance_t * const pxUART;
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 27648 ) )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 25000 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0

View File

@ -58,7 +58,7 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"
/* Driver includes. */
#include "drivers/mss_uart/mss_uart.h"
@ -73,6 +73,11 @@
/* The maximum time in ticks to wait for the UART access mutex. */
#define cmdMAX_MUTEX_WAIT ( 200 / portTICK_RATE_MS )
/* Characters are only ever received slowly on the CLI so it is ok to pass
received characters from the UART interrupt to the task on a queue. This sets
the length of the queue used for that purpose. */
#define cmdRXED_CHARS_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
@ -80,6 +85,19 @@
*/
static void prvUARTCommandConsoleTask( void *pvParameters );
/*
* Ensure a previous interrupt driven Tx has completed before sending the next
* data block to the UART.
*/
static void prvSendBuffer( const uint8_t * pcBuffer, size_t xBufferLength );
/*
* A UART is used for printf() output and CLI input and output. Configure the
* UART and register prvUARTRxNotificationHandler() to handle UART Rx events.
*/
static void prvConfigureUART( void );
static void prvUARTRxNotificationHandler( mss_uart_instance_t * this_uart );
/*-----------------------------------------------------------*/
/* Const messages output by the command console. */
@ -87,10 +105,24 @@ static const uint8_t * const pcWelcomeMessage = ( uint8_t * ) "\r\n\r\nFreeRTOS
static const uint8_t * const pcEndOfOutputMessage = ( uint8_t * ) "\r\n[Press ENTER to execute the previous command again]\r\n>";
static const uint8_t * const pcNewLine = ( uint8_t * ) "\r\n";
/* The UART used by the CLI. */
static const mss_uart_instance_t * const pxUART = &g_mss_uart0;
static const IRQn_Type xUART_IRQ = UART0_IRQn;
/* Because characters are received slowly (at the speed somebody can type) then
it is ok to pass received characters from the Rx interrupt to the task on a
queue. This is the queue used for that purpose. */
static xQueueHandle xRxedChars = NULL;
/*-----------------------------------------------------------*/
void vUARTCommandConsoleStart( uint16_t usStackSize, unsigned portBASE_TYPE uxPriority )
{
/* A UART is used for printf() output and CLI input and output. Note there
is no mutual exclusion on the UART, but the demo as it stands does not
require mutual exclusion. */
prvConfigureUART();
/* Create that task that handles the console itself. */
xTaskCreate( prvUARTCommandConsoleTask, /* The task that implements the command console. */
( const int8_t * const ) "CLI", /* Text name assigned to the task. This is just to assist debugging. The kernel does not use this name itself. */
@ -106,7 +138,6 @@ static void prvUARTCommandConsoleTask( void *pvParameters )
int8_t cRxedChar, cInputIndex = 0, *pcOutputString;
static int8_t cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];
portBASE_TYPE xReturned;
mss_uart_instance_t * const pxUART = &g_mss_uart0;
( void ) pvParameters;
@ -116,24 +147,21 @@ mss_uart_instance_t * const pxUART = &g_mss_uart0;
pcOutputString = FreeRTOS_CLIGetOutputBuffer();
/* Send the welcome message. */
MSS_UART_polled_tx_string( pxUART, ( uint8_t * ) pcWelcomeMessage );
prvSendBuffer( pcWelcomeMessage, strlen( ( char * ) pcWelcomeMessage ) );
for( ;; )
{
/* No characters received yet for the current input string. */
cRxedChar = 0;
/* Only interested in reading one character at a time. */
if( MSS_UART_get_rx( pxUART, ( uint8_t * ) &cRxedChar, sizeof( cRxedChar ) ) > 0 )
/* Wait for the next character to arrive. */
if( xQueueReceive( xRxedChars, &cRxedChar, portMAX_DELAY ) == pdPASS )
{
/* Echo the character back. */
MSS_UART_polled_tx( pxUART, ( uint8_t * ) &cRxedChar, sizeof( cRxedChar ) );
prvSendBuffer( ( uint8_t * ) &cRxedChar, sizeof( cRxedChar ) );
/* Was it the end of the line? */
if( cRxedChar == '\n' || cRxedChar == '\r' )
{
/* Just to space the output from the input. */
MSS_UART_polled_tx_string( pxUART, ( uint8_t * ) pcNewLine );
prvSendBuffer( ( uint8_t * ) pcNewLine, strlen( ( char * ) pcNewLine ) );
/* See if the command is empty, indicating that the last command is
to be executed again. */
@ -153,8 +181,7 @@ mss_uart_instance_t * const pxUART = &g_mss_uart0;
xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
/* Write the generated string to the UART. */
MSS_UART_polled_tx_string( pxUART, ( uint8_t * ) pcOutputString );
vTaskDelay( 1 );
prvSendBuffer( ( uint8_t * ) pcOutputString, strlen( ( char * ) pcOutputString ) );
} while( xReturned != pdFALSE );
@ -166,7 +193,7 @@ mss_uart_instance_t * const pxUART = &g_mss_uart0;
cInputIndex = 0;
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
MSS_UART_polled_tx_string( pxUART, ( uint8_t * ) pcEndOfOutputMessage );
prvSendBuffer( ( uint8_t * ) pcEndOfOutputMessage, strlen( ( char * ) pcEndOfOutputMessage ) );
}
else
{
@ -204,3 +231,60 @@ mss_uart_instance_t * const pxUART = &g_mss_uart0;
}
/*-----------------------------------------------------------*/
static void prvSendBuffer( const uint8_t * pcBuffer, size_t xBufferLength )
{
const portTickType xVeryShortDelay = 2UL;
MSS_UART_irq_tx( ( mss_uart_instance_t * ) pxUART, pcBuffer, xBufferLength );
/* Ensure any previous transmissions have completed. The default UART
interrupt does not provide an event based method of signally the end of a Tx
- this is therefore a crude poll of the Tx end status. Replacing the
default UART handler with one that 'gives' a semaphore when the Tx is
complete would allow this poll loop to be replaced by a simple semaphore
block. */
while( MSS_UART_tx_complete( ( mss_uart_instance_t * ) pxUART ) == pdFALSE )
{
vTaskDelay( xVeryShortDelay );
}
}
/*-----------------------------------------------------------*/
static void prvConfigureUART( void )
{
/* Initialise the UART which is used for printf() and CLI IO. */
MSS_UART_init( ( mss_uart_instance_t * ) pxUART, MSS_UART_115200_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
/* Characters are only ever received slowly on the CLI so it is ok to pass
received characters from the UART interrupt to the task on a queue. Create
the queue used for that purpose. */
xRxedChars = xQueueCreate( cmdRXED_CHARS_QUEUE_LENGTH, sizeof( char ) );
/* The interrupt handler makes use of FreeRTOS API functions, so its
priority must be at or below the configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
setting (the higher the numeric priority, the lower the logical priority). */
NVIC_SetPriority( xUART_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
/* Set the UART Rx notification function. */
MSS_UART_set_rx_handler( ( mss_uart_instance_t * ) pxUART, prvUARTRxNotificationHandler, MSS_UART_FIFO_SINGLE_BYTE );
}
/*-----------------------------------------------------------*/
static void prvUARTRxNotificationHandler( mss_uart_instance_t * pxUART )
{
uint8_t cRxed;
portBASE_TYPE xHigherPriorityTaskWoken;
/* The command console receives data very slowly (at the speed of somebody
typing), therefore it is ok to just handle one character at a time and use
a queue to send the characters to the task. */
if( MSS_UART_get_rx( pxUART, &cRxed, sizeof( cRxed ) ) == sizeof( cRxed ) )
{
xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR( xRxedChars, &cRxed, &xHigherPriorityTaskWoken );
/* portEND_SWITCHING_ISR() or portYIELD_FROM_ISR() can be used here. */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}

View File

@ -104,6 +104,21 @@
* been discovered. If the green LED toggles every 200ms, then an issue has
* been discovered with at least one task.
*
* FreeRTOS+CLI command console. The command console is access through UART0
* using 115200 baud and the Microsemi MSS UART drivers. Type "help" to see a
* list of registered commands, which include some basic file system commands
* (see FreeRTOS+FAT SL comments below). The FreeRTOS+CLI license is different
* to the FreeRTOS license, see http://www.FreeRTOS.org/cli for license and
* usage details.
*
* FreeRTOS+FAT SL. FreeRTOS+FAT SL is demonstrated using a RAM disk. [At the
* time of writing] The functionality of the file system demo is identical to
* the functionality of the FreeRTOS Win32 simulator file system demo with the
* command console being accessed via the UART (as described above) instead of
* a network terminal. The FreeRTOS+FAT SL license is different to the FreeRTOS
* license, see http://www.FreeRTOS.org/fat_sl for license and usage details,
* and a description of the file system demo functionality.
*
* See the documentation page for this demo on the FreeRTOS.org web site for
* full information, including hardware setup requirements.
*/
@ -115,7 +130,7 @@
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
#include "queue.h"
/* Standard demo application includes. */
#include "integer.h"
@ -163,7 +178,7 @@ standard demo flash timers. */
/* The size of the stack and the priority used by the UART command console
task. */
#define mainUART_COMMAND_CONSOLE_STACK_SIZE ( configMINIMAL_STACK_SIZE * 3 )
#define mainUART_COMMAND_CONSOLE_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 )
#define mainUART_COMMAND_CONSOLE_TASK_PRIORITY ( tskIDLE_PRIORITY )
/*-----------------------------------------------------------*/
@ -180,31 +195,28 @@ static void prvCheckTimerCallback( xTimerHandle xTimer );
extern void vRegisterSampleCLICommands( void );
extern void vRegisterFileSystemCLICommands( void );
/* Prepare to run the full demo: Configure the IO, register the CLI
* commands, and depending on configuration, generate a set of sample files on
* a RAM disk.
*/
static void prvPrepareForFullDemo( void );
/*
* Creates and verifies different files on the volume, demonstrating the use of
* various different API functions.
*/
extern void vCreateAndVerifySampleFiles( void );
/*-----------------------------------------------------------*/
void main_full( void )
{
xTimerHandle xCheckTimer = NULL;
/* If the file system is only going to be accessed from one task then
F_FS_THREAD_AWARE can be set to 0 and the set of example files are created
before the RTOS scheduler is started. If the file system is going to be
access from more than one task then F_FS_THREAD_AWARE must be set to 1 and
the set of sample files are created from the idle task hook function
vApplicationIdleHook() - which is defined in this file. */
#if F_FS_THREAD_AWARE == 0
{
/* Initialise the drive and file system, then create a few example
files. The output from this function just goes to the stdout window,
allowing the output to be viewed when the UDP command console is not
connected. */
vCreateAndVerifySampleFiles();
}
#endif
/* Register both the standard and file system related CLI commands. */
vRegisterSampleCLICommands();
vRegisterFileSystemCLICommands();
/* Prepare to run the full demo: Configure the IO, register the CLI
commands, and depending on configuration, generate a set of sample files on
a RAM disk. */
prvPrepareForFullDemo();
/* Start all the other standard demo/test tasks. The have not particular
functionality, but do demonstrate how to use the FreeRTOS API and test the
@ -331,3 +343,25 @@ unsigned long ulErrorFound = pdFALSE;
}
/*-----------------------------------------------------------*/
static void prvPrepareForFullDemo( void )
{
/* If the file system is only going to be accessed from one task then
F_FS_THREAD_AWARE can be set to 0 and the set of example files are created
before the RTOS scheduler is started. If the file system is going to be
access from more than one task then F_FS_THREAD_AWARE must be set to 1 and
the set of sample files are created from the idle task hook function
vApplicationIdleHook() - which is defined in this file. */
#if F_FS_THREAD_AWARE == 0
{
/* Initialise the drive and file system, then create a few example
files. The output from this function just goes to the stdout window,
allowing the output to be viewed when the UDP command console is not
connected. */
vCreateAndVerifySampleFiles();
}
#endif
/* Register both the standard and file system related CLI commands. */
vRegisterSampleCLICommands();
vRegisterFileSystemCLICommands();
}

View File

@ -119,8 +119,6 @@ void vApplicationIdleHook( void );
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );
void vApplicationTickHook( void );
/* The UART used for printf() and CLI IO. */
const mss_uart_instance_t * const pxUART = &g_mss_uart0;
/*-----------------------------------------------------------*/
/* See the documentation page for this demo on the FreeRTOS.org web site for
full information - including hardware setup requirements. */
@ -152,9 +150,6 @@ static void prvSetupHardware( void )
functions. The name ParTest is now somewhat obsolete - originally it
stood for PARallel port Test. */
vParTestInitialise();
/* Initialise the UART which is used for printf() and CLI IO. */
MSS_UART_init( pxUART, MSS_UART_115200_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
}
/*-----------------------------------------------------------*/

View File

@ -36,7 +36,7 @@ static void printchar(char **str, int c)
}
else
{
MSS_UART_polled_tx( pxUART, ( uint8_t * ) &c, sizeof( uint8_t ) );
/* Output char here. */
}
}