2 FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\r
11 * Purchasing FreeRTOS documentation will not only help you, by *
\r
12 * ensuring you get running as quickly as possible and with an *
\r
13 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
14 * the FreeRTOS project to continue with its mission of providing *
\r
15 * professional grade, cross platform, de facto standard solutions *
\r
16 * for microcontrollers - completely free of charge! *
\r
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
31 distribute a combined work that includes FreeRTOS without being obliged to
\r
32 provide the source code for proprietary components outside of the FreeRTOS
\r
33 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
34 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
35 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 ***************************************************************************
\r
46 * Having a problem? Start by reading the FAQ "My application does *
\r
47 * not run, what could be wrong? *
\r
49 * http://www.FreeRTOS.org/FAQHelp.html *
\r
51 ***************************************************************************
\r
54 http://www.FreeRTOS.org - Documentation, training, latest information,
\r
55 license and contact details.
\r
57 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
58 including FreeRTOS+Trace - an indispensable productivity tool.
\r
60 Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
\r
61 the code with commercial support, indemnification, and middleware, under
\r
62 the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
\r
63 provide a safety engineered and independently SIL3 certified version under
\r
64 the SafeRTOS brand: http://www.SafeRTOS.com.
\r
69 #include <embedded.h>
\r
70 #include "FreeRTOS.h"
\r
71 #include "portasm.h"
\r
76 #define serMAX_PORTS ( ( unsigned short ) 2 )
\r
78 #define serPORT_0_INT_REG ( 0xff44 )
\r
79 #define serPORT_0_BAUD_REG ( 0xff88 )
\r
80 #define serPORT_0_RX_REG ( 0xff86 )
\r
81 #define serPORT_0_TX_REG ( 0xff84 )
\r
82 #define serPORT_0_STATUS_REG ( 0xff82 )
\r
83 #define serPORT_0_CTRL_REG ( 0xff80 )
\r
84 #define serPORT_0_IRQ ( 0x14 )
\r
86 #define serPORT_1_INT_REG ( 0xff42 )
\r
87 #define serPORT_1_BAUD_REG ( 0xff18 )
\r
88 #define serPORT_1_RX_REG ( 0xff16 )
\r
89 #define serPORT_1_TX_REG ( 0xff14 )
\r
90 #define serPORT_1_STATUS_REG ( 0xff12 )
\r
91 #define serPORT_1_CTRL_REG ( 0xff10 )
\r
92 #define serPORT_1_IRQ ( 0x11 )
\r
94 #define serTX_EMPTY ( ( unsigned short ) 0x40 )
\r
95 #define serRX_READY ( ( unsigned short ) 0x80 )
\r
97 #define serRESET_PIC( usEOI_TYPE ) portOUTPUT_WORD( ( unsigned short ) 0xff22, usEOI_TYPE )
\r
98 #define serTX_HOLD_EMPTY_INT ( ( unsigned short ) 0x100 )
\r
100 #define serENABLE_INTERRUPTS ( ( unsigned short ) 0x80 )
\r
101 #define serMODE ( ( unsigned short ) 0x01 )
\r
102 #define serENABLE_TX_MACHINES ( ( unsigned short ) 0x40 )
\r
103 #define serENABLE_RX_MACHINES ( ( unsigned short ) 0x20 )
\r
104 #define serINTERRUPT_MASK ( ( unsigned short ) 0x08 )
\r
105 #define serCLEAR_ALL_STATUS_BITS ( ( unsigned short ) 0x00 )
\r
106 #define serINTERRUPT_PRIORITY ( ( unsigned short ) 0x01 ) /*< Just below the scheduler priority. */
\r
108 #define serDONT_BLOCK ( ( portTickType ) 0 )
\r
166 typedef struct xCOM_PORT
\r
168 /* Hardware parameters for this port. */
\r
169 short sTxInterruptOn;
\r
170 unsigned short usIntReg;
\r
171 unsigned short usBaudReg;
\r
172 unsigned short usRxReg;
\r
173 unsigned short usTxReg;
\r
174 unsigned short usStatusReg;
\r
175 unsigned short usCtrlReg;
\r
177 unsigned short usIRQVector;
\r
179 /* Queues used for communications with com test task. */
\r
180 xQueueHandle xRxedChars;
\r
181 xQueueHandle xCharsForTx;
\r
183 /* This semaphore does nothing useful except test a feature of the
\r
185 xSemaphoreHandle xTestSem;
\r
189 static xComPort xPorts[ serMAX_PORTS ] =
\r
191 { pdFALSE, serPORT_0_INT_REG, serPORT_0_BAUD_REG, serPORT_0_RX_REG, serPORT_0_TX_REG, serPORT_0_STATUS_REG, serPORT_0_CTRL_REG, serPORT_0_IRQ, NULL, NULL, NULL },
\r
192 { pdFALSE, serPORT_1_INT_REG, serPORT_1_BAUD_REG, serPORT_1_RX_REG, serPORT_1_TX_REG, serPORT_1_STATUS_REG, serPORT_1_CTRL_REG, serPORT_1_IRQ, NULL, NULL, NULL }
\r
195 typedef xComPort * xComPortHandle;
\r
198 * Lookup the baud rate from the enum.
\r
200 static unsigned long prvBaud( eBaud eWantedBaud );
\r
202 /* These prototypes are repeated here so we don't have to include the serial header. This allows
\r
203 the xComPortHandle structure details to be private to this file. */
\r
204 xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength );
\r
205 portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, char *pcRxedChar, portTickType xBlockTime );
\r
206 portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, char cOutChar, portTickType xBlockTime );
\r
207 void vSerialClose( xComPortHandle xPort );
\r
208 short sSerialWaitForSemaphore( xComPortHandle xPort );
\r
209 /*-----------------------------------------------------------*/
\r
211 static short xComPortISR( xComPort * const pxPort );
\r
213 #define vInterruptOn( pxPort, usInterrupt ) \
\r
215 unsigned short usIn; \
\r
217 portENTER_CRITICAL(); \
\r
219 if( pxPort->sTxInterruptOn == pdFALSE ) \
\r
221 usIn = portINPUT_WORD( pxPort->usCtrlReg ); \
\r
222 portOUTPUT_WORD( pxPort->usCtrlReg, usIn | usInterrupt ); \
\r
224 pxPort->sTxInterruptOn = pdTRUE; \
\r
227 portEXIT_CRITICAL(); \
\r
229 /*-----------------------------------------------------------*/
\r
231 #define vInterruptOff( pxPort, usInterrupt ) \
\r
233 unsigned short usIn = portINPUT_WORD( pxPort->usCtrlReg ); \
\r
234 if( usIn & usInterrupt ) \
\r
236 portOUTPUT_WORD( pxPort->usCtrlReg, usIn & ~usInterrupt); \
\r
237 pxPort->sTxInterruptOn = pdFALSE; \
\r
240 /*-----------------------------------------------------------*/
\r
243 /* Define an interrupt handler for each port */
\r
244 #define COM_IRQ_WRAPPER(N) \
\r
245 static void __interrupt COM_IRQ##N##_WRAPPER( void ) \
\r
247 if( xComPortISR( &( xPorts[##N##] ) ) ) \
\r
249 portEND_SWITCHING_ISR(); \
\r
255 COM_IRQ_WRAPPER( 0 )
\r
256 COM_IRQ_WRAPPER( 1 )
\r
258 static pxISR xISRs[ serMAX_PORTS ] =
\r
264 /*-----------------------------------------------------------*/
\r
266 static unsigned long prvBaud( eBaud eWantedBaud )
\r
268 switch( eWantedBaud )
\r
270 case ser50 : return 50UL;
\r
271 case ser75 : return 75UL;
\r
272 case ser110 : return 110UL;
\r
273 case ser134 : return 134UL;
\r
274 case ser150 : return 150UL;
\r
275 case ser200 : return 200UL;
\r
276 case ser300 : return 300UL;
\r
277 case ser600 : return 600UL;
\r
278 case ser1200 : return 1200UL;
\r
279 case ser1800 : return 1800UL;
\r
280 case ser2400 : return 2400UL;
\r
281 case ser4800 : return 4800UL;
\r
282 case ser19200 : return 19200UL;
\r
283 case ser38400 : return 38400UL;
\r
284 case ser57600 : return 57600UL;
\r
285 case ser115200 : return 115200UL;
\r
286 default : return 9600UL;
\r
290 /*-----------------------------------------------------------*/
\r
292 xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength )
\r
294 unsigned short usPort;
\r
295 xComPortHandle pxPort = NULL;
\r
296 unsigned long ulBaudDiv;
\r
298 /* BAUDDIV = ( Microprocessor Clock / Baud Rate ) / 16 */
\r
299 ulBaudDiv = ( configCPU_CLOCK_HZ / prvBaud( eWantedBaud ) ) / 16UL;
\r
301 /* Only n, 8, 1 is supported so these parameters are not required for this
\r
303 ( void ) eWantedParity;
\r
304 ( void ) eWantedDataBits;
\r
305 ( void ) eWantedStopBits;
\r
307 /* Currently only n,8,1 is supported. */
\r
309 usPort = ( unsigned short ) ePort;
\r
311 if( usPort < serMAX_PORTS )
\r
313 pxPort = &( xPorts[ usPort ] );
\r
315 portENTER_CRITICAL();
\r
317 unsigned short usInWord;
\r
319 /* Create the queues used by the com test task. */
\r
320 pxPort->xRxedChars = xQueueCreate( uxBufferLength, ( unsigned portBASE_TYPE ) sizeof( char ) );
\r
321 pxPort->xCharsForTx = xQueueCreate( uxBufferLength, ( unsigned portBASE_TYPE ) sizeof( char ) );
\r
323 /* Create the test semaphore. This does nothing useful except test a feature of the scheduler. */
\r
324 vSemaphoreCreateBinary( pxPort->xTestSem );
\r
326 /* There is no ISR here already to restore later. */
\r
327 setvect( ( short ) pxPort->usIRQVector, xISRs[ usPort ] );
\r
329 usInWord = portINPUT_WORD( pxPort->usIntReg );
\r
330 usInWord &= ~serINTERRUPT_MASK;
\r
331 usInWord |= serINTERRUPT_PRIORITY;
\r
332 portOUTPUT_WORD( pxPort->usIntReg, usInWord );
\r
334 portOUTPUT_WORD( pxPort->usBaudReg, ( unsigned short ) ulBaudDiv );
\r
335 portOUTPUT_WORD( pxPort->usCtrlReg, serENABLE_INTERRUPTS | serMODE | serENABLE_TX_MACHINES | serENABLE_RX_MACHINES );
\r
337 portOUTPUT_WORD( pxPort->usStatusReg, serCLEAR_ALL_STATUS_BITS );
\r
339 portEXIT_CRITICAL();
\r
343 } /*lint !e715 Some parameters are not used as only a subset of the serial port functionality is currently implemented. */
\r
344 /*-----------------------------------------------------------*/
\r
346 void vSerialPutString( xComPortHandle pxPort, const char * const pcString, unsigned short usStringLength )
\r
348 unsigned short usByte;
\r
351 pcNextChar = ( char * ) pcString;
\r
353 for( usByte = 0; usByte < usStringLength; usByte++ )
\r
355 xQueueSend( pxPort->xCharsForTx, pcNextChar, serDONT_BLOCK );
\r
359 vInterruptOn( pxPort, serTX_HOLD_EMPTY_INT );
\r
361 /*-----------------------------------------------------------*/
\r
363 portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, char *pcRxedChar, portTickType xBlockTime )
\r
365 /* Get the next character from the buffer, note that this routine is only
\r
366 called having checked that the is (at least) one to get */
\r
367 if( xQueueReceive( pxPort->xRxedChars, pcRxedChar, xBlockTime ) )
\r
376 /*-----------------------------------------------------------*/
\r
378 portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, char cOutChar, portTickType xBlockTime )
\r
380 if( xQueueSend( pxPort->xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
\r
385 vInterruptOn( pxPort, serTX_HOLD_EMPTY_INT );
\r
389 /*-----------------------------------------------------------*/
\r
391 portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort )
\r
393 const portTickType xBlockTime = ( portTickType ) 0xffff;
\r
395 /* This function does nothing interesting, but test the
\r
396 semaphore from ISR mechanism. */
\r
397 return xSemaphoreTake( xPort->xTestSem, xBlockTime );
\r
399 /*-----------------------------------------------------------*/
\r
401 void vSerialClose( xComPortHandle xPort )
\r
403 unsigned short usOutput;
\r
405 /* Turn off the interrupts. We may also want to delete the queues and/or
\r
406 re-install the original ISR. */
\r
408 portENTER_CRITICAL();
\r
410 usOutput = portINPUT_WORD( xPort->usCtrlReg );
\r
412 usOutput &= ~serENABLE_INTERRUPTS;
\r
413 usOutput &= ~serENABLE_TX_MACHINES;
\r
414 usOutput &= ~serENABLE_RX_MACHINES;
\r
415 portOUTPUT_WORD( xPort->usCtrlReg, usOutput );
\r
417 usOutput = portINPUT_WORD( xPort->usIntReg );
\r
418 usOutput |= serINTERRUPT_MASK;
\r
419 portOUTPUT_WORD( xPort->usIntReg, usOutput );
\r
421 portEXIT_CRITICAL();
\r
423 /*-----------------------------------------------------------*/
\r
424 unsigned short usStatus;
\r
425 static portBASE_TYPE xComPortISR( xComPort * const pxPort )
\r
427 unsigned short usStatusRegister;
\r
429 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
431 /* NOTE: THIS IS NOT AN EFFICIENT ISR AS IT IS DESIGNED SOLELY TO TEST
\r
432 THE SCHEDULER FUNCTIONALITY. REAL APPLICATIONS SHOULD NOT USE THIS
\r
435 usStatusRegister = portINPUT_WORD( pxPort->usStatusReg );
\r
437 if( usStatusRegister & serRX_READY )
\r
439 cChar = ( char ) portINPUT_WORD( pxPort->usRxReg );
\r
440 xQueueSendFromISR( pxPort->xRxedChars, &cChar, &xHigherPriorityTaskWoken );
\r
442 /* Also release the semaphore - this does nothing interesting and is just a test. */
\r
443 xSemaphoreGiveFromISR( pxPort->xTestSem, &xHigherPriorityTaskWoken );
\r
445 else if( pxPort->sTxInterruptOn && ( usStatusRegister & serTX_EMPTY ) )
\r
447 if( xQueueReceiveFromISR( pxPort->xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
\r
449 portOUTPUT_WORD( pxPort->usTxReg, ( unsigned short ) cChar );
\r
453 /* Queue empty, nothing to send */
\r
454 vInterruptOff( pxPort, serTX_HOLD_EMPTY_INT );
\r
458 serRESET_PIC( pxPort->usIRQVector );
\r
460 /* If posting to the queue woke a task that was blocked on the queue we may
\r
461 want to switch to the woken task - depending on its priority relative to
\r
462 the task interrupted by this ISR. */
\r
463 return xHigherPriorityTaskWoken;
\r