]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/H8S/RTOSDemo/serial/serial.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / H8S / RTOSDemo / serial / serial.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 \r
30 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER for port 1.\r
31 \r
32 Note that this driver is written to test the RTOS port and is not intended\r
33 to represent an optimised solution.  In particular no use is made of the DMA\r
34 peripheral. */\r
35 \r
36 /* Standard include files. */\r
37 #include <stdlib.h>\r
38 \r
39 /* Scheduler include files. */\r
40 #include "FreeRTOS.h"\r
41 #include "queue.h"\r
42 #include "task.h"\r
43 \r
44 /* Demo application include files. */\r
45 #include "serial.h"\r
46 \r
47 /* The queues used to communicate between the task code and the interrupt\r
48 service routines. */\r
49 static QueueHandle_t xRxedChars; \r
50 static QueueHandle_t xCharsForTx; \r
51 \r
52 /* Hardware specific constants. */\r
53 #define serTX_INTERRUPT                         ( ( unsigned char ) 0x80 )\r
54 #define serRX_INTERRUPT                         ( ( unsigned char ) 0x40 )\r
55 #define serTX_ENABLE                            ( ( unsigned char ) 0x20 )\r
56 #define serRX_ENABLE                            ( ( unsigned char ) 0x10 )\r
57 \r
58 /* Macros to turn on and off the serial port THRE interrupt while leaving the\r
59 other register bits in their correct state.   The Rx interrupt is always \r
60 enabled. */\r
61 #define serTX_INTERRUPT_ON()            SCR1 = serTX_INTERRUPT | serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;                                                                 \r
62 #define serTX_INTERRUPT_OFF()           SCR1 =                                   serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;\r
63 \r
64 /* Bit used to switch on the channel 1 serial port in the module stop \r
65 register. */\r
66 #define serMSTP6                                        ( ( unsigned short ) 0x0040 )\r
67 \r
68 /* Interrupt service routines.  Note that the Rx and Tx service routines can \r
69 cause a context switch and are therefore defined with the saveall attribute in\r
70 addition to the interrupt_handler attribute.  See the FreeRTOS.org WEB site \r
71 documentation for a full explanation.*/\r
72 void vCOM_1_Rx_ISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );\r
73 void vCOM_1_Tx_ISR( void ) __attribute__ ( ( saveall, interrupt_handler ) );\r
74 void vCOM_1_Error_ISR( void ) __attribute__ ( ( interrupt_handler ) );\r
75 \r
76 /*-----------------------------------------------------------*/\r
77 \r
78 /*\r
79  * Initialise port 1 for interrupt driven communications.\r
80  */\r
81 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
82 {\r
83         /* Create the queues used to communicate between the tasks and the\r
84         interrupt service routines. */\r
85         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
86         xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
87 \r
88         /* No parity, 8 data bits and 1 stop bit is the default so does not require \r
89         configuration - setup the remains of the hardware. */\r
90         portENTER_CRITICAL();\r
91         {\r
92                 /* Turn channel 1 on. */\r
93                 MSTPCR &= ~serMSTP6;\r
94 \r
95                 /* Enable the channels and the Rx interrupt.  The Tx interrupt is only \r
96                 enabled when data is being transmitted. */\r
97                 SCR1 = serRX_INTERRUPT | serTX_ENABLE | serRX_ENABLE;\r
98 \r
99                 /* Bit rate settings for 22.1184MHz clock only!. */\r
100                 switch( ulWantedBaud )\r
101                 {\r
102                         case 4800       :       BRR1 = 143;\r
103                                                         break;\r
104                         case 9600       :       BRR1 = 71;\r
105                                                         break;\r
106                         case 19200      :       BRR1 = 35;\r
107                                                         break;\r
108                         case 38400      :       BRR1 = 17;\r
109                                                         break;\r
110                         case 57600      :       BRR1 = 11;\r
111                                                         break;\r
112                         case 115200     :       BRR1 = 5;\r
113                                                         break;\r
114                         default         :       BRR1 = 5;\r
115                                                         break;\r
116                 }\r
117         }\r
118         portEXIT_CRITICAL();    \r
119 \r
120         /* Unlike some ports, this driver code does not allow for more than one\r
121         com port.  We therefore don't return a pointer to a port structure and can\r
122         instead just return NULL. */\r
123         return NULL;\r
124 }\r
125 /*-----------------------------------------------------------*/\r
126 \r
127 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
128 {\r
129         /* Get the next character from the buffer queue.  Return false if no characters\r
130         are available, or arrive before xBlockTime expires. */\r
131         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
132         {\r
133                 return pdTRUE;\r
134         }\r
135         else\r
136         {\r
137                 return pdFALSE;\r
138         }\r
139 }\r
140 /*-----------------------------------------------------------*/\r
141 \r
142 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
143 {\r
144 signed portBASE_TYPE xReturn = pdPASS;\r
145 \r
146         /* Return false if after the block time there is no room on the Tx queue. */\r
147         portENTER_CRITICAL();\r
148         {\r
149                 /* Send a character to the queue of characters waiting transmission.\r
150                 The queue is serviced by the Tx ISR. */\r
151                 if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )\r
152                 {\r
153                         /* Could not post onto the queue. */\r
154                         xReturn = pdFAIL;\r
155                 }\r
156                 else\r
157                 {\r
158                         /* The message was posted onto the queue so we turn on the Tx\r
159                         interrupt to allow the Tx ISR to remove the character from the\r
160                         queue. */\r
161                         serTX_INTERRUPT_ON();\r
162                 }\r
163         }\r
164         portEXIT_CRITICAL();\r
165 \r
166         return xReturn;\r
167 }\r
168 /*-----------------------------------------------------------*/\r
169 \r
170 void vSerialClose( xComPortHandle xPort )\r
171 {       \r
172         /* Not supported. */\r
173         ( void ) xPort;\r
174 }\r
175 /*-----------------------------------------------------------*/\r
176 \r
177 void vCOM_1_Rx_ISR( void )\r
178 {\r
179         /* This can cause a context switch so this macro must be the first line\r
180         in the function. */\r
181         portENTER_SWITCHING_ISR();\r
182 \r
183         /* As this is a switching ISR the local variables must be declared as \r
184         static. */\r
185         static char cRxByte;\r
186         static portBASE_TYPE xHigherPriorityTaskWoken;\r
187 \r
188                 xHigherPriorityTaskWoken = pdFALSE;\r
189 \r
190                 /* Get the character. */\r
191                 cRxByte = RDR1;\r
192 \r
193                 /* Post the character onto the queue of received characters - noting\r
194                 whether or not this wakes a task. */\r
195                 xQueueSendFromISR( xRxedChars, &cRxByte, &xHigherPriorityTaskWoken );\r
196 \r
197                 /* Clear the interrupt. */\r
198                 SSR1 &= ~serRX_INTERRUPT;\r
199 \r
200         /* This must be the last line in the function.  We pass cTaskWokenByPost so \r
201         a context switch will occur if the received character woke a task that has\r
202         a priority higher than the task we interrupted. */\r
203         portEXIT_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
204 }\r
205 /*-----------------------------------------------------------*/\r
206 \r
207 void vCOM_1_Tx_ISR( void )\r
208 {\r
209         /* This can cause a context switch so this macro must be the first line\r
210         in the function. */\r
211         portENTER_SWITCHING_ISR();\r
212 \r
213         /* As this is a switching ISR the local variables must be declared as \r
214         static. */\r
215         static char cTxByte;\r
216         static signed portBASE_TYPE xTaskWokenByTx;\r
217 \r
218                 /* This variable is static so must be explicitly reinitialised each\r
219                 time the function executes. */\r
220                 xTaskWokenByTx = pdFALSE;\r
221 \r
222                 /* The interrupt was caused by the THR becoming empty.  Are there any\r
223                 more characters to transmit?  Note whether or not the Tx interrupt has\r
224                 woken a task. */\r
225                 if( xQueueReceiveFromISR( xCharsForTx, &cTxByte, &xTaskWokenByTx ) == pdTRUE )\r
226                 {\r
227                         /* A character was retrieved from the queue so can be sent to the\r
228                         THR now. */                                                     \r
229                         TDR1 = cTxByte;\r
230 \r
231                         /* Clear the interrupt. */\r
232                         SSR1 &= ~serTX_INTERRUPT;\r
233                 }\r
234                 else\r
235                 {\r
236                         /* Queue empty, nothing to send so turn off the Tx interrupt. */\r
237                         serTX_INTERRUPT_OFF();\r
238                 }               \r
239 \r
240         /* This must be the last line in the function.  We pass cTaskWokenByTx so \r
241         a context switch will occur if the Tx'ed character woke a task that has\r
242         a priority higher than the task we interrupted. */\r
243         portEXIT_SWITCHING_ISR( xTaskWokenByTx );\r
244 }\r
245 /*-----------------------------------------------------------*/\r
246 \r
247 /*\r
248  * This ISR cannot cause a context switch so requires no special \r
249  * considerations. \r
250  */\r
251 void vCOM_1_Error_ISR( void )\r
252 {\r
253 volatile unsigned char ucIn;\r
254 \r
255         ucIn = SSR1;\r
256         SSR1 = 0;\r
257 }\r
258 \r