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