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