2 FreeRTOS MCF5235 port - Copyright (C) 2006 Christian Walter.
\r
4 This file is part of the FreeRTOS distribution.
\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
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
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
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
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
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
36 /* ------------------------ MCF523x includes ------------------------------ */
\r
37 #include "mcf5xxx.h"
\r
38 #include "mcf523x.h"
\r
40 /* ------------------------ FreeRTOS includes ----------------------------- */
\r
41 #include "FreeRTOS.h"
\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
53 /* ------------------------ Static functions ------------------------------ */
\r
54 static void prvSerialISR( void );
\r
56 /* ------------------------ Static variables ------------------------------ */
\r
59 portBASE_TYPE xInitialized;
\r
60 xQueueHandle xRXChars;
\r
61 xQueueHandle xTXChars;
\r
64 static xComPortIF_t xComPortIF[ COM_NIFACE ];
\r
66 /* ------------------------ Begin implementation -------------------------- */
\r
68 xSerialPortInitMinimal( unsigned portLONG ulWantedBaud,
\r
69 unsigned portBASE_TYPE uxQueueLength )
\r
71 extern void ( *__RAMVEC[] ) ( );
\r
72 xComPortHandle xReturn;
\r
73 portBASE_TYPE xOldIPL;
\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
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
84 xOldIPL = portSET_IPL( portIPL_MAX );
\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
91 /* Enable receive interrupts. */
\r
92 MCF_UART_UIMR0 = MCF_UART_UIMR_RXRDY_FU;
\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
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
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
107 /* UART 0 Miscellaneous */
\r
108 MCF_UART_UACR0 = 0;
\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
113 /* Enable the UART. */
\r
114 MCF_UART_UCR0 = MCF_UART_UCR_RXC( 0x1 ) | MCF_UART_UCR_TXC( 0x1 );
\r
116 xComPortIF[ 0 ].xInitialized = TRUE;
\r
117 xReturn = ( xComPortHandle ) &xComPortIF[ 0 ];
\r
119 ( void )portSET_IPL( xOldIPL );
\r
123 xReturn = ( xComPortHandle ) 0;
\r
129 signed portBASE_TYPE
\r
130 xSerialGetChar( xComPortHandle pxPort, signed portCHAR * pcRxedChar,
\r
131 portTickType xBlockTime )
\r
134 portBASE_TYPE xResult = pdFALSE;
\r
135 /* Lookup the correct interface. */
\r
136 for( i = 0; i < COM_NIFACE; i++ )
\r
138 if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )
\r
143 /* This COM port is available. */
\r
144 if( ( i != COM_NIFACE ) && xComPortIF[ i ].xInitialized )
\r
146 /* Get the next character from the buffer. Return false if no characters
\r
147 * are available, or arrive before xBlockTime expires.
\r
149 if( xQueueReceive( xComPortIF[ i ].xRXChars, pcRxedChar, xBlockTime ) )
\r
158 vSerialPutString( xComPortHandle pxPort, const signed portCHAR *
\r
159 const pcString, unsigned portSHORT usStringLength )
\r
162 signed portCHAR *pChNext;
\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
168 /* Block until character has been transmitted. */
\r
169 while( xSerialPutChar( pxPort, *pChNext, COM_BLOCK_RETRYTIME ) != pdTRUE ); pChNext++;
\r
173 signed portBASE_TYPE
\r
174 xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar,
\r
175 portTickType xBlockTime )
\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
183 if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )
\r
188 /* This COM port is available. */
\r
189 if( ( i != COM_NIFACE ) && xComPortIF[ i ].xInitialized )
\r
191 /* Place the character in the queue of characters to be transmitted. */
\r
192 if( xQueueSend( xComPortIF[ i ].xTXChars, &cOutChar, xBlockTime ) == pdPASS )
\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
203 signed portBASE_TYPE
\r
204 xSerialPutCharNOISR( xComPortHandle pxPort, signed portCHAR cOutChar )
\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
212 if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )
\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
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
226 ( void )portSET_IPL( xOldIPL );
\r
231 vSerialPutStringNOISR( xComPortHandle pxPort, const signed portCHAR *
\r
232 const pcString, unsigned portSHORT usStringLength )
\r
235 signed portCHAR *pChNext;
\r
236 portBASE_TYPE xOldIPL = portSET_IPL( portIPL_MAX );
\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
242 /* Block until character has been transmitted. */
\r
243 while( xSerialPutCharNOISR( pxPort, *pChNext ) != pdTRUE );
\r
246 ( void )portSET_IPL( xOldIPL );
\r
250 vSerialClose( xComPortHandle xPort )
\r
252 /* Not supported as not required by the demo application. */
\r
256 prvSerialISR( void )
\r
258 static signed portCHAR cChar;
\r
259 static portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;
\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
266 #if _GCC_USES_FP == 1
\r
267 asm volatile ( "unlk %fp\n\t" );
\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
273 portENTER_SWITCHING_ISR();
\r
275 /* Ready to send a character from the buffer. */
\r
276 if( MCF_UART_USR0 & MCF_UART_USR_TXRDY )
\r
278 /* Transmit buffer is ready. Test if there are characters available. */
\r
279 if( xQueueReceiveFromISR( xComPortIF[ 0 ].xTXChars, &cChar, &xTaskWokenByTx ) ==
\r
282 /* A character was retrieved from the queue so can be sent. */
\r
283 MCF_UART_UTB0 = cChar;
\r
287 /* Leave only receiver enabled. */
\r
288 MCF_UART_UIMR0 = MCF_UART_UIMR_RXRDY_FU;
\r
291 if( MCF_UART_USR0 & MCF_UART_USR_RXRDY )
\r
293 cChar = MCF_UART_URB0;
\r
295 xQueueSendFromISR( xComPortIF[ 0].xRXChars, &cChar, xTaskWokenByRx );
\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
300 portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );
\r