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