]> begriffs open source - freertos/blob - Demo/H8S/RTOSDemo/serial/serial.c
Ready for V6.0.3 release.
[freertos] / Demo / H8S / RTOSDemo / serial / serial.c
1 /*\r
2     FreeRTOS V6.0.3 - Copyright (C) 2010 Real Time Engineers Ltd.\r
3 \r
4     ***************************************************************************\r
5     *                                                                         *\r
6     * If you are:                                                             *\r
7     *                                                                         *\r
8     *    + New to FreeRTOS,                                                   *\r
9     *    + Wanting to learn FreeRTOS or multitasking in general quickly       *\r
10     *    + Looking for basic training,                                        *\r
11     *    + Wanting to improve your FreeRTOS skills and productivity           *\r
12     *                                                                         *\r
13     * then take a look at the FreeRTOS eBook                                  *\r
14     *                                                                         *\r
15     *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *\r
16     *                  http://www.FreeRTOS.org/Documentation                  *\r
17     *                                                                         *\r
18     * A pdf reference manual is also available.  Both are usually delivered   *\r
19     * to your inbox within 20 minutes to two hours when purchased between 8am *\r
20     * and 8pm GMT (although please allow up to 24 hours in case of            *\r
21     * exceptional circumstances).  Thank you for your support!                *\r
22     *                                                                         *\r
23     ***************************************************************************\r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \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 exception to the GPL is included to allow you to distribute\r
31     a combined work that includes FreeRTOS without being obliged to provide the\r
32     source code for proprietary components outside of the FreeRTOS kernel.\r
33     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
34     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
35     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
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 \r
55 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER for port 1.\r
56 \r
57 Note that this driver is written to test the RTOS port and is not intended\r
58 to represent an optimised solution.  In particular no use is made of the DMA\r
59 peripheral. */\r
60 \r
61 /* Standard include files. */\r
62 #include <stdlib.h>\r
63 \r
64 /* Scheduler include files. */\r
65 #include "FreeRTOS.h"\r
66 #include "queue.h"\r
67 #include "task.h"\r
68 \r
69 /* Demo application include files. */\r
70 #include "serial.h"\r
71 \r
72 /* The queues used to communicate between the task code and the interrupt\r
73 service routines. */\r
74 static xQueueHandle xRxedChars; \r
75 static xQueueHandle xCharsForTx; \r
76 \r
77 /* Hardware specific constants. */\r
78 #define serTX_INTERRUPT                         ( ( unsigned char ) 0x80 )\r
79 #define serRX_INTERRUPT                         ( ( unsigned char ) 0x40 )\r
80 #define serTX_ENABLE                            ( ( unsigned char ) 0x20 )\r
81 #define serRX_ENABLE                            ( ( unsigned char ) 0x10 )\r
82 \r
83 /* Macros to turn on and off the serial port THRE interrupt while leaving the\r
84 other register bits in their correct state.   The Rx interrupt is always \r
85 enabled. */\r
86 #define serTX_INTERRUPT_ON()            SCR1 = serTX_INTERRUPT | serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;                                                                 \r
87 #define serTX_INTERRUPT_OFF()           SCR1 =                                   serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;\r
88 \r
89 /* Bit used to switch on the channel 1 serial port in the module stop \r
90 register. */\r
91 #define serMSTP6                                        ( ( unsigned short ) 0x0040 )\r
92 \r
93 /* Interrupt service routines.  Note that the Rx and Tx service routines can \r
94 cause a context switch and are therefore defined with the saveall attribute in\r
95 addition to the interrupt_handler attribute.  See the FreeRTOS.org WEB site \r
96 documentation for a full explanation.*/\r
97 void vCOM_1_Rx_ISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );\r
98 void vCOM_1_Tx_ISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );\r
99 void vCOM_1_Error_ISR( void ) __attribute__ ( ( interrupt_handler ) );\r
100 \r
101 /*-----------------------------------------------------------*/\r
102 \r
103 /*\r
104  * Initialise port 1 for interrupt driven communications.\r
105  */\r
106 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
107 {\r
108         /* Create the queues used to communicate between the tasks and the\r
109         interrupt service routines. */\r
110         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
111         xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
112 \r
113         /* No parity, 8 data bits and 1 stop bit is the default so does not require \r
114         configuration - setup the remains of the hardware. */\r
115         portENTER_CRITICAL();\r
116         {\r
117                 /* Turn channel 1 on. */\r
118                 MSTPCR &= ~serMSTP6;\r
119 \r
120                 /* Enable the channels and the Rx interrupt.  The Tx interrupt is only \r
121                 enabled when data is being transmitted. */\r
122                 SCR1 = serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;\r
123 \r
124                 /* Bit rate settings for 22.1184MHz clock only!. */\r
125                 switch( ulWantedBaud )\r
126                 {\r
127                         case 4800       :       BRR1 = 143;\r
128                                                         break;\r
129                         case 9600       :       BRR1 = 71;\r
130                                                         break;\r
131                         case 19200      :       BRR1 = 35;\r
132                                                         break;\r
133                         case 38400      :       BRR1 = 17;\r
134                                                         break;\r
135                         case 57600      :       BRR1 = 11;\r
136                                                         break;\r
137                         case 115200     :       BRR1 = 5;\r
138                                                         break;\r
139                         default         :       BRR1 = 5;\r
140                                                         break;\r
141                 }\r
142         }\r
143         portEXIT_CRITICAL();    \r
144 \r
145         /* Unlike some ports, this driver code does not allow for more than one\r
146         com port.  We therefore don't return a pointer to a port structure and can\r
147         instead just return NULL. */\r
148         return NULL;\r
149 }\r
150 /*-----------------------------------------------------------*/\r
151 \r
152 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, portTickType xBlockTime )\r
153 {\r
154         /* Get the next character from the buffer queue.  Return false if no characters\r
155         are available, or arrive before xBlockTime expires. */\r
156         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
157         {\r
158                 return pdTRUE;\r
159         }\r
160         else\r
161         {\r
162                 return pdFALSE;\r
163         }\r
164 }\r
165 /*-----------------------------------------------------------*/\r
166 \r
167 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, portTickType xBlockTime )\r
168 {\r
169 signed portBASE_TYPE xReturn = pdPASS;\r
170 \r
171         /* Return false if after the block time there is no room on the Tx queue. */\r
172         portENTER_CRITICAL();\r
173         {\r
174                 /* Send a character to the queue of characters waiting transmission.\r
175                 The queue is serviced by the Tx ISR. */\r
176                 if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )\r
177                 {\r
178                         /* Could not post onto the queue. */\r
179                         xReturn = pdFAIL;\r
180                 }\r
181                 else\r
182                 {\r
183                         /* The message was posted onto the queue so we turn on the Tx\r
184                         interrupt to allow the Tx ISR to remove the character from the\r
185                         queue. */\r
186                         serTX_INTERRUPT_ON();\r
187                 }\r
188         }\r
189         portEXIT_CRITICAL();\r
190 \r
191         return xReturn;\r
192 }\r
193 /*-----------------------------------------------------------*/\r
194 \r
195 void vSerialClose( xComPortHandle xPort )\r
196 {       \r
197         /* Not supported. */\r
198         ( void ) xPort;\r
199 }\r
200 /*-----------------------------------------------------------*/\r
201 \r
202 void vCOM_1_Rx_ISR( void )\r
203 {\r
204         /* This can cause a context switch so this macro must be the first line\r
205         in the function. */\r
206         portENTER_SWITCHING_ISR();\r
207 \r
208         /* As this is a switching ISR the local variables must be declared as \r
209         static. */\r
210         static char cRxByte;\r
211         static portBASE_TYPE xHigherPriorityTaskWoken;\r
212 \r
213                 xHigherPriorityTaskWoken = pdFALSE;\r
214 \r
215                 /* Get the character. */\r
216                 cRxByte = RDR1;\r
217 \r
218                 /* Post the character onto the queue of received characters - noting\r
219                 whether or not this wakes a task. */\r
220                 xQueueSendFromISR( xRxedChars, &cRxByte, &xHigherPriorityTaskWoken );\r
221 \r
222                 /* Clear the interrupt. */\r
223                 SSR1 &= ~serRX_INTERRUPT;\r
224 \r
225         /* This must be the last line in the function.  We pass cTaskWokenByPost so \r
226         a context switch will occur if the received character woke a task that has\r
227         a priority higher than the task we interrupted. */\r
228         portEXIT_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
229 }\r
230 /*-----------------------------------------------------------*/\r
231 \r
232 void vCOM_1_Tx_ISR( void )\r
233 {\r
234         /* This can cause a context switch so this macro must be the first line\r
235         in the function. */\r
236         portENTER_SWITCHING_ISR();\r
237 \r
238         /* As this is a switching ISR the local variables must be declared as \r
239         static. */\r
240         static char cTxByte;\r
241         static signed portBASE_TYPE xTaskWokenByTx;\r
242 \r
243                 /* This variable is static so must be explicitly reinitialised each\r
244                 time the function executes. */\r
245                 xTaskWokenByTx = pdFALSE;\r
246 \r
247                 /* The interrupt was caused by the THR becoming empty.  Are there any\r
248                 more characters to transmit?  Note whether or not the Tx interrupt has\r
249                 woken a task. */\r
250                 if( xQueueReceiveFromISR( xCharsForTx, &cTxByte, &xTaskWokenByTx ) == pdTRUE )\r
251                 {\r
252                         /* A character was retrieved from the queue so can be sent to the\r
253                         THR now. */                                                     \r
254                         TDR1 = cTxByte;\r
255 \r
256                         /* Clear the interrupt. */\r
257                         SSR1 &= ~serTX_INTERRUPT;\r
258                 }\r
259                 else\r
260                 {\r
261                         /* Queue empty, nothing to send so turn off the Tx interrupt. */\r
262                         serTX_INTERRUPT_OFF();\r
263                 }               \r
264 \r
265         /* This must be the last line in the function.  We pass cTaskWokenByTx so \r
266         a context switch will occur if the Tx'ed character woke a task that has\r
267         a priority higher than the task we interrupted. */\r
268         portEXIT_SWITCHING_ISR( xTaskWokenByTx );\r
269 }\r
270 /*-----------------------------------------------------------*/\r
271 \r
272 /*\r
273  * This ISR cannot cause a context switch so requires no special \r
274  * considerations. \r
275  */\r
276 void vCOM_1_Error_ISR( void )\r
277 {\r
278 volatile unsigned char ucIn;\r
279 \r
280         ucIn = SSR1;\r
281         SSR1 = 0;\r
282 }\r
283 \r