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