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 a version that has been certified for use
\r
32 in safety critical systems, plus commercial licensing, development and
\r
34 ***************************************************************************
\r
37 /* ------------------------ MCF523x includes ------------------------------ */
\r
38 #include "mcf5xxx.h"
\r
39 #include "mcf523x.h"
\r
41 /* ------------------------ FreeRTOS includes ----------------------------- */
\r
42 #include "FreeRTOS.h"
\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
54 /* ------------------------ Static functions ------------------------------ */
\r
55 static void prvSerialISR( void );
\r
57 /* ------------------------ Static variables ------------------------------ */
\r
60 portBASE_TYPE xInitialized;
\r
61 xQueueHandle xRXChars;
\r
62 xQueueHandle xTXChars;
\r
65 static xComPortIF_t xComPortIF[ COM_NIFACE ];
\r
67 /* ------------------------ Begin implementation -------------------------- */
\r
69 xSerialPortInitMinimal( unsigned portLONG ulWantedBaud,
\r
70 unsigned portBASE_TYPE uxQueueLength )
\r
72 extern void ( *__RAMVEC[] ) ( );
\r
73 xComPortHandle xReturn;
\r
74 portBASE_TYPE xOldIPL;
\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
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
85 xOldIPL = portSET_IPL( portIPL_MAX );
\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
92 /* Enable receive interrupts. */
\r
93 MCF_UART_UIMR0 = MCF_UART_UIMR_RXRDY_FU;
\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
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
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
108 /* UART 0 Miscellaneous */
\r
109 MCF_UART_UACR0 = 0;
\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
114 /* Enable the UART. */
\r
115 MCF_UART_UCR0 = MCF_UART_UCR_RXC( 0x1 ) | MCF_UART_UCR_TXC( 0x1 );
\r
117 xComPortIF[ 0 ].xInitialized = TRUE;
\r
118 xReturn = ( xComPortHandle ) &xComPortIF[ 0 ];
\r
120 ( void )portSET_IPL( xOldIPL );
\r
124 xReturn = ( xComPortHandle ) 0;
\r
130 signed portBASE_TYPE
\r
131 xSerialGetChar( xComPortHandle pxPort, signed portCHAR * pcRxedChar,
\r
132 portTickType xBlockTime )
\r
135 portBASE_TYPE xResult = pdFALSE;
\r
136 /* Lookup the correct interface. */
\r
137 for( i = 0; i < COM_NIFACE; i++ )
\r
139 if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )
\r
144 /* This COM port is available. */
\r
145 if( ( i != COM_NIFACE ) && xComPortIF[ i ].xInitialized )
\r
147 /* Get the next character from the buffer. Return false if no characters
\r
148 * are available, or arrive before xBlockTime expires.
\r
150 if( xQueueReceive( xComPortIF[ i ].xRXChars, pcRxedChar, xBlockTime ) )
\r
159 vSerialPutString( xComPortHandle pxPort, const signed portCHAR *
\r
160 const pcString, unsigned portSHORT usStringLength )
\r
163 signed portCHAR *pChNext;
\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
169 /* Block until character has been transmitted. */
\r
170 while( xSerialPutChar( pxPort, *pChNext, COM_BLOCK_RETRYTIME ) != pdTRUE ); pChNext++;
\r
174 signed portBASE_TYPE
\r
175 xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar,
\r
176 portTickType xBlockTime )
\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
184 if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )
\r
189 /* This COM port is available. */
\r
190 if( ( i != COM_NIFACE ) && xComPortIF[ i ].xInitialized )
\r
192 /* Place the character in the queue of characters to be transmitted. */
\r
193 if( xQueueSend( xComPortIF[ i ].xTXChars, &cOutChar, xBlockTime ) == pdPASS )
\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
204 signed portBASE_TYPE
\r
205 xSerialPutCharNOISR( xComPortHandle pxPort, signed portCHAR cOutChar )
\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
213 if( pxPort == ( xComPortHandle ) &xComPortIF[ i ] )
\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
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
227 ( void )portSET_IPL( xOldIPL );
\r
232 vSerialPutStringNOISR( xComPortHandle pxPort, const signed portCHAR *
\r
233 const pcString, unsigned portSHORT usStringLength )
\r
236 signed portCHAR *pChNext;
\r
237 portBASE_TYPE xOldIPL = portSET_IPL( portIPL_MAX );
\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
243 /* Block until character has been transmitted. */
\r
244 while( xSerialPutCharNOISR( pxPort, *pChNext ) != pdTRUE );
\r
247 ( void )portSET_IPL( xOldIPL );
\r
251 vSerialClose( xComPortHandle xPort )
\r
253 /* Not supported as not required by the demo application. */
\r
257 prvSerialISR( void )
\r
259 static signed portCHAR cChar;
\r
260 static portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;
\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
267 #if _GCC_USES_FP == 1
\r
268 asm volatile ( "unlk %fp\n\t" );
\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
274 portENTER_SWITCHING_ISR();
\r
276 /* Ready to send a character from the buffer. */
\r
277 if( MCF_UART_USR0 & MCF_UART_USR_TXRDY )
\r
279 /* Transmit buffer is ready. Test if there are characters available. */
\r
280 if( xQueueReceiveFromISR( xComPortIF[ 0 ].xTXChars, &cChar, &xTaskWokenByTx ) ==
\r
283 /* A character was retrieved from the queue so can be sent. */
\r
284 MCF_UART_UTB0 = cChar;
\r
288 /* Leave only receiver enabled. */
\r
289 MCF_UART_UIMR0 = MCF_UART_UIMR_RXRDY_FU;
\r
292 if( MCF_UART_USR0 & MCF_UART_USR_RXRDY )
\r
294 cChar = MCF_UART_URB0;
\r
296 xQueueSendFromISR( xComPortIF[ 0].xRXChars, &cChar, xTaskWokenByRx );
\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
301 portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );
\r