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