\r
/* Scheduler includes. */\r
#include "FreeRTOS.h"\r
+#include "task.h"\r
#include "queue.h"\r
#include "semphr.h"\r
\r
-/* Driver includes. */\r
-#include "CircularBuffer.h"\r
-\r
/* Library includes. */\r
#include "stm32f10x_lib.h"\r
-#include "stm32f10x_rcc.h"\r
\r
/* Driver includes. */\r
#include "STM32_USART.h"\r
/* The number of COM ports that can be controlled at the same time. */\r
#define serNUM_COM_PORTS ( 2 )\r
\r
-/* Indexes into the xCOMBufferDefinitions array for the Rx and Tx buffers. */\r
-#define serRX_BUFFER_INDEX ( 0 )\r
-#define serTX_BUFFER_INDEX ( 1 )\r
+/* Queues are used to hold characters that are waiting to be transmitted. This\r
+constant sets the maximum number of characters that can be contained in such a\r
+queue at any one time. */\r
+#define serTX_QUEUE_LEN ( 100 )\r
+\r
+/* Queues are used to hold characters that have been received but not yet \r
+processed. This constant sets the maximum number of characters that can be \r
+contained in such a queue. */\r
+#define serRX_QUEUE_LEN ( 100 )\r
\r
-/* A counting semaphore is used to allows tasks to block to wait for characters\r
-to be received. This constant defines the max count. Making this value higher\r
-does not change the amount of RAM used by the semaphore, so its worth making it\r
-quite high. */\r
-#define serSEMAPHORE_MAX_COUNT ( 100 )\r
+/* The maximum amount of time that calls to lSerialPutString() should wait for\r
+there to be space to post each character to the queue of characters waiting\r
+transmission. NOTE! This is the time to wait per character - not the time to\r
+wait for the entire string. */\r
+#define serPUT_STRING_CHAR_DELAY ( 5 / portTICK_RATE_MS )\r
\r
/*-----------------------------------------------------------*/\r
\r
-/* An Rx and a Tx buffer structure for each COM port. */\r
-static xCircularBuffer xCOMBufferDefinitions[ serNUM_COM_PORTS ][ 2 ];\r
+/* References to the USART peripheral addresses themselves. */\r
+static USART_TypeDef * const xUARTS[ serNUM_COM_PORTS ] = { ( ( USART_TypeDef * ) USART1_BASE ), ( ( USART_TypeDef * ) USART2_BASE ) };\r
\r
-/* The buffers themselves. */\r
-static unsigned char ucCOM0_Rx_Buffer[ configCOM0_RX_BUFFER_LENGTH ];\r
-static unsigned char ucCOM0_Tx_Buffer[ configCOM0_TX_BUFFER_LENGTH ];\r
-static unsigned char ucCOM1_Rx_Buffer[ configCOM1_RX_BUFFER_LENGTH ];\r
-static unsigned char ucCOM1_Tx_Buffer[ configCOM1_TX_BUFFER_LENGTH ];\r
+/* Queues used to hold characters waiting to be transmitted - one queue per port. */\r
+static xQueueHandle xCharsForTx[ serNUM_COM_PORTS ] = { 0 };\r
\r
-/* Semaphores used to block tasks that are waiting for characters to be\r
-received. */\r
-static xSemaphoreHandle xCOM0RxSemaphore, xCOM1RxSemaphore;\r
+/* Queues holding received characters - one queue per port. */\r
+static xQueueHandle xRxedChars[ serNUM_COM_PORTS ] = { 0 };\r
\r
/*-----------------------------------------------------------*/\r
\r
-/* UART interrupt handler. */\r
-void vUARTInterruptHandler( void );\r
+/* UART interrupt handlers, as named in the vector table. */\r
+void USART1_IRQHandler( void );\r
+void USART2_IRQHandler( void );\r
\r
/*-----------------------------------------------------------*/\r
\r
/*\r
- * See serial.h in this project for parameter descriptions.\r
+ * See header file for parameter descriptions.\r
*/\r
long lCOMPortInit( unsigned long ulPort, unsigned long ulWantedBaud )\r
{\r
does not check to see if the COM port has already been initialised. */\r
if( ulPort == 0 )\r
{\r
- /* Create the semaphore used to enable tasks to block to wait for\r
- characters to be received. */\r
- xCOM0RxSemaphore = xSemaphoreCreateCounting( serSEMAPHORE_MAX_COUNT, 0 );\r
-\r
- vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ),\r
- ucCOM0_Rx_Buffer,\r
- configCOM0_RX_BUFFER_LENGTH,\r
- sizeof( unsigned char ),\r
- NULL\r
- );\r
-\r
- vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ),\r
- ucCOM0_Tx_Buffer,\r
- configCOM0_TX_BUFFER_LENGTH,\r
- sizeof( unsigned char ),\r
- NULL\r
- );\r
-\r
- /* Enable COM1 clock - the ST libraries start numbering from UART1, \r
- making this UART 2. */\r
+ /* Create the queue of chars that are waiting to be sent to COM0. */\r
+ xCharsForTx[ 0 ] = xQueueCreate( serTX_QUEUE_LEN, sizeof( char ) );\r
+\r
+ /* Create the queue used to hold characters received from COM0. */\r
+ xRxedChars[ 0 ] = xQueueCreate( serRX_QUEUE_LEN, sizeof( char ) );\r
+\r
+ /* Enable COM0 clock - the ST libraries start numbering from UART1. */\r
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE ); \r
\r
/* Configure USART1 Rx (PA10) as input floating */\r
\r
USART_DMACmd( USART1, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );\r
USART_Cmd( USART1, ENABLE ); \r
+\r
+ /* Everything is ok. */\r
+ lReturn = pdPASS;\r
}\r
- else\r
+ else if( ulPort == 1 )\r
{\r
- /* Create the semaphore used to enable tasks to block to wait for\r
- characters to be received. */\r
- xCOM1RxSemaphore = xSemaphoreCreateCounting( serSEMAPHORE_MAX_COUNT, 0 );\r
-\r
- vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ),\r
- ucCOM1_Rx_Buffer,\r
- configCOM1_RX_BUFFER_LENGTH,\r
- sizeof( unsigned char ),\r
- NULL\r
- );\r
-\r
- vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ),\r
- ucCOM1_Tx_Buffer,\r
- configCOM1_TX_BUFFER_LENGTH,\r
- sizeof( unsigned char ),\r
- NULL\r
- );\r
+ /* Create the queue of chars that are waiting to be sent to COM1. */\r
+ xCharsForTx[ 1 ] = xQueueCreate( serTX_QUEUE_LEN, sizeof( char ) );\r
+\r
+ /* Create the queue used to hold characters received from COM0. */\r
+ xRxedChars[ 1 ] = xQueueCreate( serRX_QUEUE_LEN, sizeof( char ) );\r
\r
/* Enable COM0 clock - the ST libraries start numbering from 1. */\r
RCC_APB2PeriphClockCmd( RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE ); \r
\r
USART_DMACmd( USART2, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );\r
USART_Cmd( USART2, ENABLE ); \r
+\r
+ /* Everything is ok. */\r
+ lReturn = pdPASS;\r
} \r
- \r
- /* Everything is ok. */\r
- lReturn = pdPASS;\r
+ else\r
+ {\r
+ /* Nothing to do unless more than two ports are supported. */\r
+ }\r
}\r
\r
return lReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-signed long xUSARTGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime )\r
+signed long xSerialGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime )\r
{\r
- return pdFALSE;\r
+long lReturn = pdFAIL;\r
+\r
+ if( lPort < serNUM_COM_PORTS ) \r
+ {\r
+ if( xQueueReceive( xRxedChars[ lPort ], pcRxedChar, xBlockTime ) == pdPASS )\r
+ {\r
+ lReturn = pdPASS;\r
+ }\r
+ }\r
+\r
+ return lReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vSerialPutString( long lPort, const signed char * const pcString, unsigned portSHORT usStringLength )\r
+long lSerialPutString( long lPort, const char * const pcString, unsigned long ulStringLength )\r
{\r
+long lReturn;\r
+unsigned long ul;\r
+\r
+ if( lPort < serNUM_COM_PORTS )\r
+ {\r
+ lReturn = pdPASS;\r
+\r
+ for( ul = 0; ul < ulStringLength; ul++ )\r
+ {\r
+ if( xQueueSend( xCharsForTx[ lPort ], &( pcString[ ul ] ), serPUT_STRING_CHAR_DELAY ) != pdPASS )\r
+ {\r
+ /* Cannot fit any more in the queue. Try turning the Tx on to \r
+ clear some space. */\r
+ USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE );\r
+ vTaskDelay( serPUT_STRING_CHAR_DELAY );\r
+\r
+ /* Go back and try again. */\r
+ continue;\r
+ }\r
+ }\r
+\r
+ USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE );\r
+ }\r
+ else\r
+ {\r
+ lReturn = pdFAIL;\r
+ }\r
+\r
+ return lReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
signed long xSerialPutChar( long lPort, signed char cOutChar, portTickType xBlockTime )\r
{\r
- return pdFALSE;\r
+long lReturn;\r
+\r
+ if( xQueueSend( xCharsForTx[ lPort ], &cOutChar, xBlockTime ) == pdPASS )\r
+ {\r
+ lReturn = pdPASS;\r
+ USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE );\r
+ }\r
+ else\r
+ {\r
+ lReturn = pdFAIL;\r
+ }\r
+\r
+ return lReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vUARTInterruptHandler( void )\r
+void USART1_IRQHandler( void )\r
{\r
long xHigherPriorityTaskWoken = pdFALSE;\r
char cChar;\r
{\r
/* The interrupt was caused by the THR becoming empty. Are there any\r
more characters to transmit? */\r
-if( 0 )// if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )\r
+ if( xQueueReceiveFromISR( xCharsForTx[ 0 ], &cChar, &xHigherPriorityTaskWoken ) )\r
{\r
- /* A character was retrieved from the queue so can be sent to the\r
+ /* A character was retrieved from the buffer so can be sent to the\r
THR now. */\r
USART_SendData( USART1, cChar );\r
}\r
if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET )\r
{\r
cChar = USART_ReceiveData( USART1 );\r
-// xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );\r
+ xQueueSendFromISR( xRxedChars[ 0 ], &cChar, &xHigherPriorityTaskWoken );\r
} \r
\r
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
}\r
+/*-----------------------------------------------------------*/\r
\r
+void USART2_IRQHandler( void )\r
+{\r
+}\r
\r
\r
\r