]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/H8S/RTOSDemo/serial/serial.c
feefedd79aac0b0ba03472472beea633eaa6c414
[freertos] / FreeRTOS / Demo / H8S / RTOSDemo / serial / serial.c
1 /*\r
2     FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd. \r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS provides completely free yet professionally developed,    *\r
10      *    robust, strictly quality controlled, supported, and cross          *\r
11      *    platform software that has become a de facto standard.             *\r
12      *                                                                       *\r
13      *    Help yourself get started quickly and support the FreeRTOS         *\r
14      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
15      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
16      *                                                                       *\r
17      *    Thank you!                                                         *\r
18      *                                                                       *\r
19     ***************************************************************************\r
20 \r
21     This file is part of the FreeRTOS distribution.\r
22 \r
23     FreeRTOS is free software; you can redistribute it and/or modify it under\r
24     the terms of the GNU General Public License (version 2) as published by the\r
25     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
26 \r
27     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
28     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
29     >>!   obliged to provide the source code for proprietary components     !<<\r
30     >>!   outside of the FreeRTOS kernel.                                   !<<\r
31 \r
32     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
33     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
34     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
35     link: http://www.freertos.org/a00114.html\r
36 \r
37     1 tab == 4 spaces!\r
38 \r
39     ***************************************************************************\r
40      *                                                                       *\r
41      *    Having a problem?  Start by reading the FAQ "My application does   *\r
42      *    not run, what could be wrong?"                                     *\r
43      *                                                                       *\r
44      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
49     license and Real Time Engineers Ltd. contact details.\r
50 \r
51     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
52     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
53     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
54 \r
55     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
56     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
57     licenses offer ticketed support, indemnification and middleware.\r
58 \r
59     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
60     engineered and independently SIL3 certified version for use in safety and\r
61     mission critical applications that require provable dependability.\r
62 \r
63     1 tab == 4 spaces!\r
64 */\r
65 \r
66 \r
67 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER for port 1.\r
68 \r
69 Note that this driver is written to test the RTOS port and is not intended\r
70 to represent an optimised solution.  In particular no use is made of the DMA\r
71 peripheral. */\r
72 \r
73 /* Standard include files. */\r
74 #include <stdlib.h>\r
75 \r
76 /* Scheduler include files. */\r
77 #include "FreeRTOS.h"\r
78 #include "queue.h"\r
79 #include "task.h"\r
80 \r
81 /* Demo application include files. */\r
82 #include "serial.h"\r
83 \r
84 /* The queues used to communicate between the task code and the interrupt\r
85 service routines. */\r
86 static QueueHandle_t xRxedChars; \r
87 static QueueHandle_t xCharsForTx; \r
88 \r
89 /* Hardware specific constants. */\r
90 #define serTX_INTERRUPT                         ( ( unsigned char ) 0x80 )\r
91 #define serRX_INTERRUPT                         ( ( unsigned char ) 0x40 )\r
92 #define serTX_ENABLE                            ( ( unsigned char ) 0x20 )\r
93 #define serRX_ENABLE                            ( ( unsigned char ) 0x10 )\r
94 \r
95 /* Macros to turn on and off the serial port THRE interrupt while leaving the\r
96 other register bits in their correct state.   The Rx interrupt is always \r
97 enabled. */\r
98 #define serTX_INTERRUPT_ON()            SCR1 = serTX_INTERRUPT | serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;                                                                 \r
99 #define serTX_INTERRUPT_OFF()           SCR1 =                                   serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;\r
100 \r
101 /* Bit used to switch on the channel 1 serial port in the module stop \r
102 register. */\r
103 #define serMSTP6                                        ( ( unsigned short ) 0x0040 )\r
104 \r
105 /* Interrupt service routines.  Note that the Rx and Tx service routines can \r
106 cause a context switch and are therefore defined with the saveall attribute in\r
107 addition to the interrupt_handler attribute.  See the FreeRTOS.org WEB site \r
108 documentation for a full explanation.*/\r
109 void vCOM_1_Rx_ISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );\r
110 void vCOM_1_Tx_ISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );\r
111 void vCOM_1_Error_ISR( void ) __attribute__ ( ( interrupt_handler ) );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /*\r
116  * Initialise port 1 for interrupt driven communications.\r
117  */\r
118 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
119 {\r
120         /* Create the queues used to communicate between the tasks and the\r
121         interrupt service routines. */\r
122         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
123         xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
124 \r
125         /* No parity, 8 data bits and 1 stop bit is the default so does not require \r
126         configuration - setup the remains of the hardware. */\r
127         portENTER_CRITICAL();\r
128         {\r
129                 /* Turn channel 1 on. */\r
130                 MSTPCR &= ~serMSTP6;\r
131 \r
132                 /* Enable the channels and the Rx interrupt.  The Tx interrupt is only \r
133                 enabled when data is being transmitted. */\r
134                 SCR1 = serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;\r
135 \r
136                 /* Bit rate settings for 22.1184MHz clock only!. */\r
137                 switch( ulWantedBaud )\r
138                 {\r
139                         case 4800       :       BRR1 = 143;\r
140                                                         break;\r
141                         case 9600       :       BRR1 = 71;\r
142                                                         break;\r
143                         case 19200      :       BRR1 = 35;\r
144                                                         break;\r
145                         case 38400      :       BRR1 = 17;\r
146                                                         break;\r
147                         case 57600      :       BRR1 = 11;\r
148                                                         break;\r
149                         case 115200     :       BRR1 = 5;\r
150                                                         break;\r
151                         default         :       BRR1 = 5;\r
152                                                         break;\r
153                 }\r
154         }\r
155         portEXIT_CRITICAL();    \r
156 \r
157         /* Unlike some ports, this driver code does not allow for more than one\r
158         com port.  We therefore don't return a pointer to a port structure and can\r
159         instead just return NULL. */\r
160         return NULL;\r
161 }\r
162 /*-----------------------------------------------------------*/\r
163 \r
164 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
165 {\r
166         /* Get the next character from the buffer queue.  Return false if no characters\r
167         are available, or arrive before xBlockTime expires. */\r
168         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
169         {\r
170                 return pdTRUE;\r
171         }\r
172         else\r
173         {\r
174                 return pdFALSE;\r
175         }\r
176 }\r
177 /*-----------------------------------------------------------*/\r
178 \r
179 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
180 {\r
181 signed portBASE_TYPE xReturn = pdPASS;\r
182 \r
183         /* Return false if after the block time there is no room on the Tx queue. */\r
184         portENTER_CRITICAL();\r
185         {\r
186                 /* Send a character to the queue of characters waiting transmission.\r
187                 The queue is serviced by the Tx ISR. */\r
188                 if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )\r
189                 {\r
190                         /* Could not post onto the queue. */\r
191                         xReturn = pdFAIL;\r
192                 }\r
193                 else\r
194                 {\r
195                         /* The message was posted onto the queue so we turn on the Tx\r
196                         interrupt to allow the Tx ISR to remove the character from the\r
197                         queue. */\r
198                         serTX_INTERRUPT_ON();\r
199                 }\r
200         }\r
201         portEXIT_CRITICAL();\r
202 \r
203         return xReturn;\r
204 }\r
205 /*-----------------------------------------------------------*/\r
206 \r
207 void vSerialClose( xComPortHandle xPort )\r
208 {       \r
209         /* Not supported. */\r
210         ( void ) xPort;\r
211 }\r
212 /*-----------------------------------------------------------*/\r
213 \r
214 void vCOM_1_Rx_ISR( void )\r
215 {\r
216         /* This can cause a context switch so this macro must be the first line\r
217         in the function. */\r
218         portENTER_SWITCHING_ISR();\r
219 \r
220         /* As this is a switching ISR the local variables must be declared as \r
221         static. */\r
222         static char cRxByte;\r
223         static portBASE_TYPE xHigherPriorityTaskWoken;\r
224 \r
225                 xHigherPriorityTaskWoken = pdFALSE;\r
226 \r
227                 /* Get the character. */\r
228                 cRxByte = RDR1;\r
229 \r
230                 /* Post the character onto the queue of received characters - noting\r
231                 whether or not this wakes a task. */\r
232                 xQueueSendFromISR( xRxedChars, &cRxByte, &xHigherPriorityTaskWoken );\r
233 \r
234                 /* Clear the interrupt. */\r
235                 SSR1 &= ~serRX_INTERRUPT;\r
236 \r
237         /* This must be the last line in the function.  We pass cTaskWokenByPost so \r
238         a context switch will occur if the received character woke a task that has\r
239         a priority higher than the task we interrupted. */\r
240         portEXIT_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
241 }\r
242 /*-----------------------------------------------------------*/\r
243 \r
244 void vCOM_1_Tx_ISR( void )\r
245 {\r
246         /* This can cause a context switch so this macro must be the first line\r
247         in the function. */\r
248         portENTER_SWITCHING_ISR();\r
249 \r
250         /* As this is a switching ISR the local variables must be declared as \r
251         static. */\r
252         static char cTxByte;\r
253         static signed portBASE_TYPE xTaskWokenByTx;\r
254 \r
255                 /* This variable is static so must be explicitly reinitialised each\r
256                 time the function executes. */\r
257                 xTaskWokenByTx = pdFALSE;\r
258 \r
259                 /* The interrupt was caused by the THR becoming empty.  Are there any\r
260                 more characters to transmit?  Note whether or not the Tx interrupt has\r
261                 woken a task. */\r
262                 if( xQueueReceiveFromISR( xCharsForTx, &cTxByte, &xTaskWokenByTx ) == pdTRUE )\r
263                 {\r
264                         /* A character was retrieved from the queue so can be sent to the\r
265                         THR now. */                                                     \r
266                         TDR1 = cTxByte;\r
267 \r
268                         /* Clear the interrupt. */\r
269                         SSR1 &= ~serTX_INTERRUPT;\r
270                 }\r
271                 else\r
272                 {\r
273                         /* Queue empty, nothing to send so turn off the Tx interrupt. */\r
274                         serTX_INTERRUPT_OFF();\r
275                 }               \r
276 \r
277         /* This must be the last line in the function.  We pass cTaskWokenByTx so \r
278         a context switch will occur if the Tx'ed character woke a task that has\r
279         a priority higher than the task we interrupted. */\r
280         portEXIT_SWITCHING_ISR( xTaskWokenByTx );\r
281 }\r
282 /*-----------------------------------------------------------*/\r
283 \r
284 /*\r
285  * This ISR cannot cause a context switch so requires no special \r
286  * considerations. \r
287  */\r
288 void vCOM_1_Error_ISR( void )\r
289 {\r
290 volatile unsigned char ucIn;\r
291 \r
292         ucIn = SSR1;\r
293         SSR1 = 0;\r
294 }\r
295 \r