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