]> begriffs open source - cmsis-freertos/blob - Demo/HCS12_GCC_banked/serial.c
Update README.md - branch main is now the base branch
[cmsis-freertos] / Demo / HCS12_GCC_banked / serial.c
1 /*
2         serial.c  for using FreeRTOS
3         Copyright (C) 2005  Robotronics Inc.
4 */
5
6
7 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER for port 1.
8
9    GCC demo modifications by Jeff Smith, Robotronics Inc. 2005
10 */
11
12 #include "cpu.h"
13 #include <sys/sio.h>
14
15 /* Scheduler include files. */
16 #include "FreeRTOS.h"
17 #include "queue.h"
18 #include "task.h"
19
20 /* Demo application include files. */
21 #include "sci.h"
22 #include "serial.h"
23
24 /* The queues used to communicate between the task code and the interrupt
25 service routines. */
26 static QueueHandle_t xRxedChars; 
27 static QueueHandle_t xCharsForTx; 
28
29 /* Interrupt identification bits. */
30 #define serOVERRUN_INTERRUPT            ( '\x08' )
31 #define serRX_INTERRUPT                         ( 0x20 )
32 #define serTX_INTERRUPT                         ( 0x80 )
33
34 /*-----------------------------------------------------------*/
35
36
37 /*
38  * Initialise port for interrupt driven communications.
39  */
40 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
41 {
42         /* Hardware setup is performed by the Processor Expert generated code.  
43         This function just creates the queues used to communicate between the 
44         interrupt code and the task code - then sets the required baud rate. */
45
46         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
47         xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
48
49         SCI_SetBaudRateMode( ( char ) ulWantedBaud );
50
51         return NULL;
52 }
53 /*-----------------------------------------------------------*/
54
55 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )
56 {
57         /* Get the next character from the buffer queue.  Return false if no characters
58         are available, or arrive before xBlockTime expires. */
59         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
60         {
61                 return pdTRUE;
62         }
63         else
64         {
65                 return pdFALSE;
66         }
67 }
68 /*-----------------------------------------------------------*/
69
70 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
71 {
72         /* Place the character in the queue of characters to be transmitted. */
73         if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
74         {
75                 return pdFAIL;
76         }
77
78         /* Turn on the Tx interrupt so the ISR will remove the character from the
79         queue and send it.   This does not need to be in a critical section as
80         if the interrupt has already removed the character the next interrupt
81         will simply turn off the Tx interrupt again. */
82         SCICR2 |= 0x80;                         // TIE
83
84         return pdPASS;
85 }
86 /*-----------------------------------------------------------*/
87
88 void vSerialClose( xComPortHandle xPort )
89 {       
90         /* Not supported. */
91         //( void ) xPort;
92 }
93 /*-----------------------------------------------------------*/
94
95
96 /* 
97  * Interrupt service routine for the serial port.  Must be in non-banked
98  * memory. 
99  */
100
101 void ATTR_INT ATTR_NEAR vCOM_ISR( void );
102
103 void vCOM_ISR( void )
104 {
105 volatile unsigned char ucByte, ucStatus;
106 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
107
108         /* What caused the interrupt? */
109         ucStatus = SCISR1;
110         
111         if( ucStatus & serOVERRUN_INTERRUPT )
112         {
113                 /* The interrupt was caused by an overrun.  Clear the error by reading
114                 the data register. */
115                 ucByte = SCIDRL;
116         }
117         else
118         if( ucStatus & serRX_INTERRUPT )
119         {
120                 /* The interrupt was caused by a character being received.
121                 Read the received byte. */
122                 ucByte = SCIDRL;
123
124                 /* Post the character onto the queue of received characters - noting
125                 whether or not this wakes a task. */
126                 xQueueSendFromISR( xRxedChars, ( void * ) &ucByte, &xHigherPriorityTaskWoken );
127         }
128         
129         if( ( ucStatus & serTX_INTERRUPT ) && ( SCICR2 & 0x80 ) )
130         {       
131                 /* The interrupt was caused by a character being transmitted. */
132                 if( xQueueReceiveFromISR( xCharsForTx, ( void * ) &ucByte, &xHigherPriorityTaskWoken ) == pdTRUE )
133                 {
134                         /* Clear the SCRF bit. */
135                         SCIDRL = ucByte;
136                 }
137                 else
138                 {
139                         /* Disable transmit interrupt */
140                         SCICR2 &= ~0x80;                        // TIE
141                 }
142         }
143
144         if( xHigherPriorityTaskWoken )
145         {
146                 portYIELD();
147         }
148 }
149