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