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