]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/NiosII_CycloneIII_DBC3C40_GCC/RTOSDemo/serial.c
9d56e4fa1733683921167489bcae7f561d031bfd
[freertos] / FreeRTOS / Demo / NiosII_CycloneIII_DBC3C40_GCC / RTOSDemo / serial.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /* NOTE:  This is just a test file and not intended to be a generic \r
29 COM driver. */\r
30 \r
31 #include "altera_avalon_uart.h"\r
32 #include "altera_avalon_uart_regs.h"\r
33 #include "sys/alt_irq.h"\r
34 \r
35 #include "FreeRTOS.h"\r
36 #include "queue.h"\r
37 #include "system.h"\r
38 #include "Serial.h"\r
39 /*---------------------------------------------------------------------------*/\r
40 \r
41 #define serINVALID_QUEUE                                ( ( QueueHandle_t ) 0 )\r
42 #define serNO_BLOCK                                             ( ( TickType_t ) 0 )\r
43 /*---------------------------------------------------------------------------*/\r
44 \r
45 static QueueHandle_t xRxedChars; \r
46 static QueueHandle_t xCharsForTx; \r
47 \r
48 alt_u32 uartControl;\r
49 /*---------------------------------------------------------------------------*/\r
50 \r
51 static void vUARTInterruptHandler( void* context, alt_u32 id );\r
52 static void vUARTReceiveHandler( alt_u32 status );\r
53 static void vUARTTransmitHandler( alt_u32 status );\r
54 /*---------------------------------------------------------------------------*/\r
55 \r
56 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
57 {\r
58         /* Create the queues used to hold Rx and Tx characters. */\r
59         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
60         xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
61 \r
62         /* If the queues were created correctly then setup the serial port hardware. */\r
63         if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) )\r
64         {\r
65                 portENTER_CRITICAL();\r
66                 {\r
67                         uartControl = ALTERA_AVALON_UART_CONTROL_RTS_MSK | ALTERA_AVALON_UART_CONTROL_RRDY_MSK | ALTERA_AVALON_UART_CONTROL_DCTS_MSK;\r
68                         IOWR_ALTERA_AVALON_UART_CONTROL( UART_BASE, uartControl ); \r
69                   \r
70                     /* register the interrupt handler */\r
71                         alt_irq_register ( UART_IRQ, NULL, vUARTInterruptHandler );\r
72                 }\r
73                 portEXIT_CRITICAL();\r
74         }\r
75         else\r
76         {\r
77                 return ( xComPortHandle ) 0;\r
78         }\r
79     return ( xComPortHandle ) 1;\r
80 }\r
81 /*---------------------------------------------------------------------------*/\r
82 \r
83 void vSerialClose( xComPortHandle xPort )\r
84 {\r
85     /* Never used. */\r
86 }\r
87 /*---------------------------------------------------------------------------*/\r
88 \r
89 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
90 {\r
91         /* The port handle is not required as this driver only supports one port. */\r
92         ( void ) pxPort;\r
93 \r
94 \r
95         /* Get the next character from the buffer.  Return false if no characters\r
96         are available, or arrive before xBlockTime expires. */\r
97         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
98         {\r
99                 return pdTRUE;\r
100         }\r
101         else\r
102         {\r
103                 uartControl |= ALTERA_AVALON_UART_CONTROL_RRDY_MSK;\r
104                 IOWR_ALTERA_AVALON_UART_CONTROL( UART_BASE, uartControl );\r
105                 return pdFALSE;\r
106         }\r
107 }\r
108 /*---------------------------------------------------------------------------*/\r
109 \r
110 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
111 {\r
112 signed portBASE_TYPE lReturn = pdPASS;\r
113 \r
114         /* Place the character in the queue of characters to be transmitted. */\r
115         if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS )\r
116         {\r
117         /*Triggers an interrupt on every character or (down) when queue is full. */\r
118         uartControl |= ALTERA_AVALON_UART_CONTROL_TRDY_MSK; \r
119         IOWR_ALTERA_AVALON_UART_CONTROL( UART_BASE, uartControl );\r
120         lReturn = pdPASS;\r
121     }\r
122     else\r
123     {   \r
124                 lReturn = pdFAIL;\r
125         }\r
126         return lReturn;\r
127 }\r
128 /*---------------------------------------------------------------------------*/\r
129 \r
130 void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )\r
131 {\r
132 signed char *pxNext;\r
133 \r
134         /* A couple of parameters that this port does not use. */\r
135         ( void ) usStringLength;\r
136         ( void ) pxPort;\r
137 \r
138         /* NOTE: This implementation does not handle the queue being full as no block time is used! */\r
139 \r
140         /* The port handle is not required as this driver only supports UART0. */\r
141         ( void ) pxPort;\r
142 \r
143         /* Send each character in the string, one at a time. */\r
144         pxNext = ( signed char * ) pcString;\r
145         while( *pxNext )\r
146         {\r
147                 xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );\r
148                 pxNext++;\r
149         }\r
150 }\r
151 /*-----------------------------------------------------------*/\r
152 \r
153 static void vUARTInterruptHandler( void* context, alt_u32 id )\r
154 {\r
155         alt_u32 status;\r
156 \r
157         /* Read the status register in order to determine the cause of the \r
158     interrupt. */\r
159         status = IORD_ALTERA_AVALON_UART_STATUS( UART_BASE );\r
160         \r
161         /* Clear any error flags set at the device */\r
162         IOWR_ALTERA_AVALON_UART_STATUS( UART_BASE, 0 );\r
163         \r
164         /* process a read irq */\r
165         if ( status & ALTERA_AVALON_UART_STATUS_RRDY_MSK )\r
166         {\r
167                 vUARTReceiveHandler( status );\r
168         }\r
169         \r
170         /* process a write irq */\r
171         if ( status & ( ALTERA_AVALON_UART_STATUS_TRDY_MSK  ) )\r
172         {\r
173                 vUARTTransmitHandler( status );\r
174         }\r
175 }\r
176 /*---------------------------------------------------------------------------*/\r
177 \r
178 static void vUARTReceiveHandler( alt_u32 status )\r
179 {\r
180 signed char cChar;\r
181 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
182 \r
183         /* If there was an error, discard the data */\r
184         if ( status & ( ALTERA_AVALON_UART_STATUS_PE_MSK | ALTERA_AVALON_UART_STATUS_FE_MSK ) )\r
185         {\r
186         asm("break");\r
187                 return;\r
188         }\r
189 \r
190         /* Transfer data from the device to the circular buffer */\r
191         cChar = IORD_ALTERA_AVALON_UART_RXDATA( UART_BASE );\r
192         if ( pdTRUE != xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken ) )\r
193         {\r
194                 /* If the circular buffer was full, disable interrupts. Interrupts will \r
195         be re-enabled when data is removed from the buffer. */\r
196                 uartControl &= ~ALTERA_AVALON_UART_CONTROL_RRDY_MSK;\r
197                 IOWR_ALTERA_AVALON_UART_CONTROL( UART_BASE, uartControl );\r
198         }\r
199     \r
200         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
201 }\r
202 /*---------------------------------------------------------------------------*/\r
203 \r
204 static void vUARTTransmitHandler( alt_u32 status )\r
205 {\r
206 signed char cChar;\r
207 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
208         /* Transfer data if there is some ready to be transferred */\r
209         if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )\r
210         {\r
211                 IOWR_ALTERA_AVALON_UART_TXDATA( UART_BASE, cChar );\r
212     }\r
213     else\r
214     {\r
215                 uartControl &= ~ALTERA_AVALON_UART_CONTROL_TRDY_MSK;\r
216     }\r
217         \r
218         IOWR_ALTERA_AVALON_UART_CONTROL( UART_BASE, uartControl );\r
219     portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );    \r
220 }    \r
221 /*---------------------------------------------------------------------------*/\r