]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Cygnal/serial/serial.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / Cygnal / 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 \r
29 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR DEMO PURPOSES */\r
30 #include <stdlib.h>\r
31 #include "FreeRTOS.h"\r
32 #include "queue.h"\r
33 #include "task.h"\r
34 #include "serial.h"\r
35 \r
36 /* Constants required to setup the serial control register. */\r
37 #define ser8_BIT_MODE                   ( ( unsigned char ) 0x40 )\r
38 #define serRX_ENABLE                    ( ( unsigned char ) 0x10 )\r
39 \r
40 /* Constants to setup the timer used to generate the baud rate. */\r
41 #define serCLOCK_DIV_48                 ( ( unsigned char ) 0x03 )\r
42 #define serUSE_PRESCALED_CLOCK  ( ( unsigned char ) 0x10 )\r
43 #define ser8BIT_WITH_RELOAD             ( ( unsigned char ) 0x20 )\r
44 #define serSMOD                                 ( ( unsigned char ) 0x10 )\r
45 \r
46 static QueueHandle_t xRxedChars; \r
47 static QueueHandle_t xCharsForTx; \r
48 \r
49 data static unsigned portBASE_TYPE uxTxEmpty;\r
50 \r
51 /*-----------------------------------------------------------*/\r
52 \r
53 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
54 {\r
55 unsigned long ulReloadValue;\r
56 const portFLOAT fBaudConst = ( portFLOAT ) configCPU_CLOCK_HZ * ( portFLOAT ) 2.0;\r
57 unsigned char ucOriginalSFRPage;\r
58 \r
59         portENTER_CRITICAL();\r
60         {\r
61                 ucOriginalSFRPage = SFRPAGE;\r
62                 SFRPAGE = 0;\r
63 \r
64                 uxTxEmpty = pdTRUE;\r
65 \r
66                 /* Create the queues used by the com test task. */\r
67                 xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( char ) );\r
68                 xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( char ) );\r
69         \r
70                 /* Calculate the baud rate to use timer 1. */\r
71                 ulReloadValue = ( unsigned long ) ( ( ( portFLOAT ) 256 - ( fBaudConst / ( portFLOAT ) ( 32 * ulWantedBaud ) ) ) + ( portFLOAT ) 0.5 );\r
72 \r
73                 /* Set timer one for desired mode of operation. */\r
74                 TMOD &= 0x08;\r
75                 TMOD |= ser8BIT_WITH_RELOAD;\r
76                 SSTA0 |= serSMOD;\r
77 \r
78                 /* Set the reload and start values for the time. */\r
79                 TL1 = ( unsigned char ) ulReloadValue;\r
80                 TH1 = ( unsigned char ) ulReloadValue;\r
81 \r
82                 /* Setup the control register for standard n, 8, 1 - variable baud rate. */\r
83                 SCON = ser8_BIT_MODE | serRX_ENABLE;\r
84 \r
85                 /* Enable the serial port interrupts */\r
86                 ES = 1;\r
87 \r
88                 /* Start the timer. */\r
89                 TR1 = 1;\r
90 \r
91                 SFRPAGE = ucOriginalSFRPage;\r
92         }\r
93         portEXIT_CRITICAL();\r
94         \r
95         /* Unlike some ports, this serial code does not allow for more than one\r
96         com port.  We therefore don't return a pointer to a port structure and can\r
97         instead just return NULL. */\r
98         return NULL;\r
99 }\r
100 /*-----------------------------------------------------------*/\r
101 \r
102 void vSerialISR( void ) interrupt 4\r
103 {\r
104 char cChar;\r
105 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
106 \r
107         /* 8051 port interrupt routines MUST be placed within a critical section\r
108         if taskYIELD() is used within the ISR! */\r
109 \r
110         portENTER_CRITICAL();\r
111         {\r
112                 if( RI ) \r
113                 {\r
114                         /* Get the character and post it on the queue of Rxed characters.\r
115                         If the post causes a task to wake force a context switch if the woken task\r
116                         has a higher priority than the task we have interrupted. */\r
117                         cChar = SBUF;\r
118                         RI = 0;\r
119 \r
120                         xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );\r
121                 }\r
122 \r
123                 if( TI ) \r
124                 {\r
125                         if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == ( portBASE_TYPE ) pdTRUE )\r
126                         {\r
127                                 /* Send the next character queued for Tx. */\r
128                                 SBUF = cChar;\r
129                         }\r
130                         else\r
131                         {\r
132                                 /* Queue empty, nothing to send. */\r
133                                 uxTxEmpty = pdTRUE;\r
134                         }\r
135 \r
136                         TI = 0;\r
137                 }\r
138         \r
139                 if( xHigherPriorityTaskWoken )\r
140                 {\r
141                         portYIELD();\r
142                 }\r
143         }\r
144         portEXIT_CRITICAL();\r
145 }\r
146 /*-----------------------------------------------------------*/\r
147 \r
148 portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
149 {\r
150         /* There is only one port supported. */\r
151         ( void ) pxPort;\r
152 \r
153         /* Get the next character from the buffer.  Return false if no characters\r
154         are available, or arrive before xBlockTime expires. */\r
155         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
156         {\r
157                 return ( portBASE_TYPE ) pdTRUE;\r
158         }\r
159         else\r
160         {\r
161                 return ( portBASE_TYPE ) pdFALSE;\r
162         }\r
163 }\r
164 /*-----------------------------------------------------------*/\r
165 \r
166 portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
167 {\r
168 portBASE_TYPE xReturn;\r
169 \r
170         /* There is only one port supported. */\r
171         ( void ) pxPort;\r
172 \r
173         portENTER_CRITICAL();\r
174         {\r
175                 if( uxTxEmpty == pdTRUE )\r
176                 {\r
177                         SBUF = cOutChar;\r
178                         uxTxEmpty = pdFALSE;\r
179                         xReturn = ( portBASE_TYPE ) pdTRUE;\r
180                 }\r
181                 else\r
182                 {\r
183                         xReturn = xQueueSend( xCharsForTx, &cOutChar, xBlockTime );\r
184 \r
185                         if( xReturn == ( portBASE_TYPE ) pdFALSE )\r
186                         {\r
187                                 xReturn = ( portBASE_TYPE ) pdTRUE;\r
188                         }\r
189                 }\r
190         }\r
191         portEXIT_CRITICAL();\r
192 \r
193         return xReturn;\r
194 }\r
195 /*-----------------------------------------------------------*/\r
196 \r
197 void vSerialClose( xComPortHandle xPort )\r
198 {\r
199         /* Not implemented in this port. */\r
200         ( void ) xPort;\r
201 }\r
202 /*-----------------------------------------------------------*/\r
203 \r
204 \r
205 \r
206 \r
207 \r