]> git.sur5r.net Git - freertos/blobdiff - Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c
Add in a basic USART driver and echo test task.
[freertos] / Demo / CORTEX_STM32F103_GCC_Rowley / Drivers / STM32_USART.c
index 20c0c5d46e52738ff54c79442284fd34f6b49718..8e978afd68b7a3ceb62ba5d1c4ecd252edd97ed7 100644 (file)
 \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
@@ -141,26 +141,13 @@ GPIO_InitTypeDef GPIO_InitStructure;
                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
@@ -182,26 +169,17 @@ GPIO_InitTypeDef GPIO_InitStructure;
                        \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
@@ -225,34 +203,89 @@ GPIO_InitTypeDef GPIO_InitStructure;
                        \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
@@ -261,9 +294,9 @@ char cChar;
        {\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
@@ -276,12 +309,16 @@ if( 0 )//         if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWo
        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