]> git.sur5r.net Git - freertos/blob - Demo/MCF5235_GCC/system/serial.c
Small mods, and update file headers.
[freertos] / Demo / MCF5235_GCC / system / serial.c
1 /*\r
2     FreeRTOS MCF5235 port - Copyright (C) 2006 Christian Walter.\r
3 \r
4     This file is part of the FreeRTOS distribution.\r
5 \r
6     FreeRTOS is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     FreeRTOS is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with FreeRTOS; if not, write to the Free Software\r
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20     A special exception to the GPL can be applied should you wish to distribute\r
21     a combined work that includes FreeRTOS, without being obliged to provide\r
22     the source code for any proprietary components.  See the licensing section\r
23     of http://www.FreeRTOS.org for full details of how and when the exception\r
24     can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
30     * and even write all or part of your application on your behalf.          *\r
31     * See http://www.OpenRTOS.com for details of the services we provide to   *\r
32     * expedite your project.                                                  *\r
33     *                                                                         *\r
34     ***************************************************************************\r
35     ***************************************************************************\r
36 \r
37         Please ensure to read the configuration and relevant port sections of the\r
38         online documentation.\r
39 \r
40         http://www.FreeRTOS.org - Documentation, latest information, license and \r
41         contact details.\r
42 \r
43         http://www.SafeRTOS.com - A version that is certified for use in safety \r
44         critical systems.\r
45 \r
46         http://www.OpenRTOS.com - Commercial support, development, porting, \r
47         licensing and training services.\r
48 */\r
49 \r
50 /* ------------------------ MCF523x includes ------------------------------ */\r
51 #include "mcf5xxx.h"\r
52 #include "mcf523x.h"\r
53 \r
54 /* ------------------------ FreeRTOS includes ----------------------------- */\r
55 #include "FreeRTOS.h"\r
56 #include "queue.h"\r
57 #include "task.h"\r
58 \r
59 #include "serial.h"\r
60 \r
61 /* ----------------------- Defines ----------------------------------------- */\r
62 #define BAUDRATE_VALUE(fsys, baud)      ( ( fsys )/(32UL * baud) )\r
63 #define MCF_UART_VECTOR                 ( 64 + 13 )\r
64 #define COM_NIFACE                      1\r
65 #define COM_BLOCK_RETRYTIME             10\r
66 \r
67 /* ------------------------ Static functions ------------------------------ */\r
68 static void     prvSerialISR( void );\r
69 \r
70 /* ------------------------ Static variables ------------------------------ */\r
71 typedef struct\r
72 {\r
73     portBASE_TYPE xInitialized;\r
74     xQueueHandle xRXChars;\r
75     xQueueHandle xTXChars;\r
76 } xComPortIF_t;\r
77 \r
78 static xComPortIF_t xComPortIF[ COM_NIFACE ];\r
79 \r
80 /* ------------------------ Begin implementation -------------------------- */\r
81 xComPortHandle\r
82 xSerialPortInitMinimal( unsigned portLONG ulWantedBaud,\r
83                         unsigned portBASE_TYPE uxQueueLength )\r
84 {\r
85     extern void     ( *__RAMVEC[] ) (  );\r
86     xComPortHandle xReturn;\r
87     portBASE_TYPE xOldIPL;\r
88 \r
89     /* Create the queues used to hold Rx and Tx characters. */\r
90     xComPortIF[ 0 ].xRXChars =\r
91         xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE )sizeof( signed portCHAR ) );\r
92     xComPortIF[ 0 ].xTXChars =\r
93         xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE )sizeof( signed portCHAR ) );\r
94 \r
95     /* If the queues were created correctly then setup the serial port hardware. */\r
96     if( ( xComPortIF[ 0 ].xRXChars != 0 ) && ( xComPortIF[ 0 ].xTXChars != 0 ) )\r
97     {\r
98         xOldIPL = portSET_IPL( portIPL_MAX );\r
99 \r
100         /* UART 0: Reset transmitter, receiver and mode register pointer */\r
101         MCF_UART_UCR0 = MCF_UART_UCR_MISC( 0x3 );\r
102         MCF_UART_UCR0 = MCF_UART_UCR_MISC( 0x2 );\r
103         MCF_UART_UCR0 = MCF_UART_UCR_MISC( 0x1 );\r
104 \r
105         /* Enable receive interrupts. */\r
106         MCF_UART_UIMR0 = MCF_UART_UIMR_RXRDY_FU;\r
107 \r
108         /* 8 Databits, 1 Stopbit and no parity */\r
109         MCF_UART_UMR0 = MCF_UART_UMR_PM( 0x3 ) | MCF_UART_UMR_SB( 0x7 ) | MCF_UART_UMR_BC( 0x3 );\r
110 \r
111         /* UART 0 Clocking */\r
112         MCF_UART_UCSR0 = MCF_UART_UCSR_RCS( 0xd ) | MCF_UART_UCSR_TCS( 0xd );\r
113         MCF_UART_UBG10 = BAUDRATE_VALUE( FSYS_2, ulWantedBaud ) >> 8U;\r
114         MCF_UART_UBG20 = BAUDRATE_VALUE( FSYS_2, ulWantedBaud ) & 0xFFU;\r
115 \r
116         /* UART 0: Enable interrupts */\r
117         __RAMVEC[MCF_UART_VECTOR] = prvSerialISR;\r
118         MCF_INTC0_ICR13 = MCF_INTC0_ICRn_IL( 0x2 ) | MCF_INTC0_ICRn_IP( 0x1 );\r
119         MCF_INTC0_IMRL &= ~MCF_INTC0_IMRL_INT_MASK13;\r
120 \r
121         /* UART 0 Miscellaneous */\r
122         MCF_UART_UACR0 = 0;\r
123 \r
124         /* UART 0: Enable pins */\r
125         MCF_GPIO_PAR_UART = MCF_GPIO_PAR_UART_PAR_U0RXD | MCF_GPIO_PAR_UART_PAR_U0TXD;\r
126 \r
127         /* Enable the UART. */\r
128         MCF_UART_UCR0 = MCF_UART_UCR_RXC( 0x1 ) | MCF_UART_UCR_TXC( 0x1 );\r
129 \r
130         xComPortIF[ 0 ].xInitialized = TRUE;\r
131         xReturn = ( xComPortHandle ) &xComPortIF[ 0 ];\r
132 \r
133         ( void )portSET_IPL( xOldIPL );\r
134     }\r
135     else\r
136     {\r
137         xReturn = ( xComPortHandle ) 0;\r
138     }\r
139 \r
140     return xReturn;\r
141 }\r
142 \r
143 signed          portBASE_TYPE\r
144 xSerialGetChar( xComPortHandle pxPort, signed portCHAR * pcRxedChar,\r
145                 portTickType xBlockTime )\r
146 {\r
147     int i;\r
148     portBASE_TYPE xResult = pdFALSE;\r
149     /* Lookup the correct interface. */\r
150     for( i = 0; i < COM_NIFACE; i++ )\r
151     {\r
152         if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )\r
153         {\r
154             break;\r
155         }\r
156     }\r
157     /* This COM port is available. */\r
158     if( ( i != COM_NIFACE ) && xComPortIF[ i ].xInitialized )\r
159     {\r
160         /* Get the next character from the buffer.  Return false if no characters\r
161          * are available, or arrive before xBlockTime expires.\r
162          */\r
163         if( xQueueReceive( xComPortIF[ i ].xRXChars, pcRxedChar, xBlockTime ) )\r
164         {\r
165             xResult = pdTRUE;\r
166         }\r
167     }\r
168     return xResult;\r
169 }\r
170 \r
171 void\r
172 vSerialPutString( xComPortHandle pxPort, const signed portCHAR *\r
173                   const pcString, unsigned portSHORT usStringLength )\r
174 {\r
175     int i;\r
176     signed portCHAR *pChNext;\r
177 \r
178     /* Send each character in the string, one at a time. */\r
179     pChNext = ( signed portCHAR * )pcString;\r
180     for( i = 0; i < usStringLength; i++ )\r
181     {\r
182         /* Block until character has been transmitted. */\r
183         while( xSerialPutChar( pxPort, *pChNext, COM_BLOCK_RETRYTIME ) != pdTRUE ); pChNext++;\r
184     }\r
185 }\r
186 \r
187 signed          portBASE_TYPE\r
188 xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar,\r
189                 portTickType xBlockTime )\r
190 {\r
191     int i;\r
192     portBASE_TYPE xResult = pdFALSE;\r
193     portBASE_TYPE xOldIPL;\r
194     /* Lookup the correct interface. */\r
195     for( i = 0; i < COM_NIFACE; i++ )\r
196     {\r
197         if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )\r
198         {\r
199             break;\r
200         }\r
201     }\r
202     /* This COM port is available. */\r
203     if( ( i != COM_NIFACE ) && xComPortIF[ i ].xInitialized )\r
204     {\r
205         /* Place the character in the queue of characters to be transmitted. */\r
206         if( xQueueSend( xComPortIF[ i ].xTXChars, &cOutChar, xBlockTime ) == pdPASS )\r
207         {\r
208             /* Turn on the Tx interrupt so the ISR will remove the character from the\r
209              * queue and send it. */\r
210             MCF_UART_UIMR0 = MCF_UART_UIMR_TXRDY | MCF_UART_UIMR_RXRDY_FU;\r
211             xResult = pdTRUE;\r
212         }\r
213     }\r
214     return xResult;\r
215 }\r
216 \r
217 signed          portBASE_TYPE\r
218 xSerialPutCharNOISR( xComPortHandle pxPort, signed portCHAR cOutChar )\r
219 {\r
220     int i;\r
221     portBASE_TYPE xResult = pdFALSE;\r
222     portBASE_TYPE xOldIPL = portSET_IPL( portIPL_MAX );\r
223     /* Lookup the correct interface. */\r
224     for( i = 0; i < COM_NIFACE; i++ )\r
225     {\r
226         if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )\r
227         {\r
228             break;\r
229         }\r
230     }\r
231     /* This COM port is available. Support for this only available for COM1 right now. */\r
232     if( ( i != COM_NIFACE ) && ( i == 0 ) )\r
233     {\r
234         /* Wait until the transmit buffer is ready. */\r
235         while( !( MCF_UART_USR0 & MCF_UART_USR_TXRDY ) );\r
236         /* Place the character in the transmit buffer. */\r
237         MCF_UART_UTB0 = cOutChar;\r
238         xResult = pdTRUE;\r
239     }\r
240     ( void )portSET_IPL( xOldIPL );\r
241     return xResult;\r
242 }\r
243 \r
244 void\r
245 vSerialPutStringNOISR( xComPortHandle pxPort, const signed portCHAR *\r
246                        const pcString, unsigned portSHORT usStringLength )\r
247 {\r
248     int i;\r
249     signed portCHAR *pChNext;\r
250     portBASE_TYPE xOldIPL = portSET_IPL( portIPL_MAX );\r
251 \r
252     /* Send each character in the string, one at a time. */\r
253     pChNext = ( signed portCHAR * )pcString;\r
254     for( i = 0; i < usStringLength; i++ )\r
255     {\r
256         /* Block until character has been transmitted. */\r
257         while( xSerialPutCharNOISR( pxPort, *pChNext ) != pdTRUE );\r
258         pChNext++;\r
259     }\r
260     ( void )portSET_IPL( xOldIPL );\r
261 }\r
262 \r
263 void\r
264 vSerialClose( xComPortHandle xPort )\r
265 {\r
266     /* Not supported as not required by the demo application. */\r
267 }\r
268 \r
269 void\r
270 prvSerialISR( void )\r
271 {\r
272     static signed portCHAR cChar;\r
273     static portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;\r
274 \r
275     /* We have to remvoe the effect of the GCC. Please note that the\r
276      * __attribute__ ((interrupt_handler)) does not work here because we\r
277      * have to do the storing of the registers ourself. Another problem\r
278      * is the usage of a frame pointer which is unlinked on entry.\r
279      */\r
280 #if _GCC_USES_FP == 1\r
281     asm volatile ( "unlk %fp\n\t" );\r
282 #endif\r
283     /* This ISR can cause a context switch, so the first statement must be\r
284      * a call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any\r
285      * variable declarations.\r
286      */\r
287     portENTER_SWITCHING_ISR();\r
288 \r
289     /* Ready to send a character from the buffer. */\r
290     if( MCF_UART_USR0 & MCF_UART_USR_TXRDY )\r
291     {\r
292         /* Transmit buffer is ready. Test if there are characters available. */\r
293         if( xQueueReceiveFromISR( xComPortIF[ 0 ].xTXChars, &cChar, &xTaskWokenByTx ) ==\r
294             pdTRUE )\r
295         {\r
296             /* A character was retrieved from the queue so can be sent. */\r
297             MCF_UART_UTB0 = cChar;\r
298         }\r
299         else\r
300         {\r
301             /* Leave only receiver enabled. */\r
302             MCF_UART_UIMR0 = MCF_UART_UIMR_RXRDY_FU;\r
303         }\r
304     }\r
305     if( MCF_UART_USR0 & MCF_UART_USR_RXRDY )\r
306     {\r
307         cChar = MCF_UART_URB0;\r
308         xTaskWokenByRx =\r
309             xQueueSendFromISR( xComPortIF[ 0].xRXChars, &cChar, xTaskWokenByRx );\r
310     }\r
311     /* Exit the ISR.  If a task was woken by either a character being\r
312      * or transmitted then a context switch will occur.\r
313      */\r
314     portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );\r
315 }\r