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