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