]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MB96340_Softune/FreeRTOS_96348hs_SK16FX100PMC/Src/serial/serial.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / MB96340_Softune / FreeRTOS_96348hs_SK16FX100PMC / Src / 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 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER.   \r
30  * \r
31  * This file only supports UART 0\r
32  */\r
33 \r
34 /* Standard includes. */\r
35 #include <stdlib.h>\r
36 \r
37 /* Scheduler includes. */\r
38 #include "FreeRTOS.h"\r
39 #include "queue.h"\r
40 #include "task.h"\r
41 \r
42 /* Demo application includes. */\r
43 #include "serial.h"\r
44 \r
45 /* The queue used to hold received characters. */\r
46 static QueueHandle_t                    xRxedChars;\r
47 \r
48 /* The queue used to hold characters waiting transmission. */\r
49 static QueueHandle_t                    xCharsForTx;\r
50 \r
51 static volatile short   sTHREEmpty;\r
52 \r
53 static volatile short   queueFail = pdFALSE;\r
54 \r
55 /*-----------------------------------------------------------*/\r
56 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
57 {\r
58         /* Initialise the hardware. */\r
59         portENTER_CRITICAL();\r
60         {\r
61                 /* Create the queues used by the com test task. */\r
62                 xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof(signed char) );\r
63                 xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof(signed char) );\r
64 \r
65                 if( xRxedChars == 0 )\r
66                 {\r
67                         queueFail = pdTRUE;\r
68                 }\r
69 \r
70                 if( xCharsForTx == 0 )\r
71                 {\r
72                         queueFail = pdTRUE;\r
73                 }\r
74 \r
75                 /* Initialize UART asynchronous mode */\r
76                 BGR0 = configCLKP1_CLOCK_HZ / ulWantedBaud;\r
77 \r
78                 SCR0 = 0x17;    /* 8N1 */\r
79                 SMR0 = 0x0d;    /* enable SOT3, Reset, normal mode */\r
80                 SSR0 = 0x02;    /* LSB first, enable receive interrupts */\r
81 \r
82                 PIER08_IE2 = 1; /* enable input */\r
83                 DDR08_D2 = 0;   /* switch P08_2 to input */\r
84                 DDR08_D3 = 1;   /* switch P08_3 to output */\r
85         }\r
86         portEXIT_CRITICAL();\r
87 \r
88         /* Unlike other ports, this serial code does not allow for more than one\r
89         com port.  We therefore don't return a pointer to a port structure and can\r
90         instead just return NULL. */\r
91         return NULL;\r
92 }\r
93 /*-----------------------------------------------------------*/\r
94 \r
95 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
96 {\r
97         /* Get the next character from the buffer.  Return false if no characters\r
98         are available, or arrive before xBlockTime expires. */\r
99         if( xQueueReceive(xRxedChars, pcRxedChar, xBlockTime) )\r
100         {\r
101                 return pdTRUE;\r
102         }\r
103         else\r
104         {\r
105                 return pdFALSE;\r
106         }\r
107 }\r
108 /*-----------------------------------------------------------*/\r
109 \r
110 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
111 {\r
112 signed portBASE_TYPE    xReturn;\r
113 \r
114         /* Transmit a character. */\r
115         portENTER_CRITICAL();\r
116         {\r
117                 if( sTHREEmpty == pdTRUE )\r
118                 {\r
119                         /* If sTHREEmpty is true then the UART Tx ISR has indicated that \r
120                         there are no characters queued to be transmitted - so we can\r
121                         write the character directly to the shift Tx register. */\r
122                         sTHREEmpty = pdFALSE;\r
123                         TDR0 = cOutChar;\r
124                         xReturn = pdPASS;\r
125                 }\r
126                 else\r
127                 {\r
128                         /* sTHREEmpty is false, so there are still characters waiting to be\r
129                         transmitted.  We have to queue this character so it gets \r
130                         transmitted     in turn. */\r
131 \r
132                         /* Return false if after the block time there is no room on the Tx \r
133                         queue.  It is ok to block inside a critical section as each task\r
134                         maintains it's own critical section status. */\r
135                         if( xQueueSend(xCharsForTx, &cOutChar, xBlockTime) == pdTRUE )\r
136                         {\r
137                                 xReturn = pdPASS;\r
138                         }\r
139                         else\r
140                         {\r
141                                 xReturn = pdFAIL;\r
142                         }\r
143                 }\r
144 \r
145                 if( pdPASS == xReturn )\r
146                 {\r
147                         /* Turn on the Tx interrupt so the ISR will remove the character from the\r
148                         queue and send it.   This does not need to be in a critical section as\r
149                         if the interrupt has already removed the character the next interrupt\r
150                         will simply turn off the Tx interrupt again. */\r
151                         SSR0_TIE = 1;\r
152                 }\r
153         }\r
154         portEXIT_CRITICAL();\r
155 \r
156         return pdPASS;\r
157 }\r
158 /*-----------------------------------------------------------*/\r
159 \r
160 /*\r
161  * UART RX interrupt service routine.\r
162  */\r
163 __interrupt void UART0_RxISR( void )\r
164 {\r
165 volatile signed char    cChar;\r
166 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
167 \r
168         /* Get the character from the UART and post it on the queue of Rxed \r
169         characters. */\r
170         cChar = RDR0;\r
171 \r
172         xQueueSendFromISR( xRxedChars, ( const void *const ) &cChar, &xHigherPriorityTaskWoken );\r
173 \r
174         if( xHigherPriorityTaskWoken )\r
175         {\r
176                 /*If the post causes a task to wake force a context switch \r
177                 as the woken task may have a higher priority than the task we have \r
178                 interrupted. */\r
179                 portYIELD_FROM_ISR();\r
180         }\r
181 }\r
182 /*-----------------------------------------------------------*/\r
183 \r
184 /*\r
185  * UART Tx interrupt service routine.\r
186  */\r
187 __interrupt void UART0_TxISR( void )\r
188 {\r
189 signed char                     cChar;\r
190 signed portBASE_TYPE    xTaskWoken = pdFALSE;\r
191 \r
192         /* The previous character has been transmitted.  See if there are any\r
193         further characters waiting transmission. */\r
194         if( xQueueReceiveFromISR(xCharsForTx, &cChar, &xTaskWoken) == pdTRUE )\r
195         {\r
196                 /* There was another character queued - transmit it now. */\r
197                 TDR0 = cChar;\r
198         }\r
199         else\r
200         {\r
201                 /* There were no other characters to transmit. */\r
202                 sTHREEmpty = pdTRUE;\r
203 \r
204                 /* Disable transmit interrupts */\r
205                 SSR0_TIE = 0;\r
206         }\r
207 }\r