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