1 /*
2 * Copyright (c) 2013-2024, Arm Limited. All rights reserved.
3 * Copyright (c) 2019-2020 Cypress Semiconductor Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the License); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 /* This is a modified copy of the ref_twincpu version at
21 * platform/ext/target/ref_twincpu/CMSIS_Driver/Driver_USART.c
22 */
23
24 #include "Driver_USART.h"
25 #include "tfm_hal_device_header.h"
26 #include "cmsis_driver_config.h"
27 #include "RTE_Device.h"
28
29 #include "cycfg.h"
30 #include "cy_device.h"
31 #include "cy_scb_uart.h"
32
33 #ifndef ARG_UNUSED
34 #define ARG_UNUSED(arg) (void)arg
35 #endif
36
37 /* Driver version */
38 #define ARM_USART_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 2)
39
40 /* Driver Version */
41 static const ARM_DRIVER_VERSION DriverVersion = {
42 ARM_USART_API_VERSION,
43 ARM_USART_DRV_VERSION
44 };
45
46 /* Driver Capabilities */
47 static const ARM_USART_CAPABILITIES DriverCapabilities = {
48 1, /* supports UART (Asynchronous) mode */
49 0, /* supports Synchronous Master mode */
50 0, /* supports Synchronous Slave mode */
51 0, /* supports UART Single-wire mode */
52 0, /* supports UART IrDA mode */
53 0, /* supports UART Smart Card mode */
54 0, /* Smart Card Clock generator available */
55 0, /* RTS Flow Control available */
56 0, /* CTS Flow Control available */
57 0, /* Transmit completed event: \ref ARM_USARTx_EVENT_TX_COMPLETE */
58 0, /* Signal receive character timeout event: \ref ARM_USARTx_EVENT_RX_TIMEOUT */
59 0, /* RTS Line: 0=not available, 1=available */
60 0, /* CTS Line: 0=not available, 1=available */
61 0, /* DTR Line: 0=not available, 1=available */
62 0, /* DSR Line: 0=not available, 1=available */
63 0, /* DCD Line: 0=not available, 1=available */
64 0, /* RI Line: 0=not available, 1=available */
65 0, /* Signal CTS change event: \ref ARM_USARTx_EVENT_CTS */
66 0, /* Signal DSR change event: \ref ARM_USARTx_EVENT_DSR */
67 0, /* Signal DCD change event: \ref ARM_USARTx_EVENT_DCD */
68 0, /* Signal RI change event: \ref ARM_USARTx_EVENT_RI */
69 0 /* Reserved */
70 };
71
ARM_USART_GetVersion(void)72 static ARM_DRIVER_VERSION ARM_USART_GetVersion(void)
73 {
74 return DriverVersion;
75 }
76
ARM_USART_GetCapabilities(void)77 static ARM_USART_CAPABILITIES ARM_USART_GetCapabilities(void)
78 {
79 return DriverCapabilities;
80 }
81
82 typedef struct {
83 CySCB_Type* base; /* UART device structure */
84 uint32_t tx_nbr_bytes; /* Number of bytes transfered */
85 uint32_t rx_nbr_bytes; /* Number of bytes recevied */
86 ARM_USART_SignalEvent_t cb_event; /* Callback function for events */
87 } UARTx_Resources;
88
USARTx_convert_retval(cy_en_scb_uart_status_t val)89 static int32_t USARTx_convert_retval(cy_en_scb_uart_status_t val)
90 {
91 switch (val) {
92 case CY_SCB_UART_SUCCESS:
93 return ARM_DRIVER_OK;
94 case CY_SCB_UART_BAD_PARAM:
95 return ARM_DRIVER_ERROR_PARAMETER;
96 case CY_SCB_UART_RECEIVE_BUSY:
97 case CY_SCB_UART_TRANSMIT_BUSY:
98 return ARM_DRIVER_ERROR_BUSY;
99 }
100 }
101
ARM_USARTx_Initialize(UARTx_Resources * uart_dev)102 static int32_t ARM_USARTx_Initialize(UARTx_Resources* uart_dev)
103 {
104 cy_en_scb_uart_status_t retval;
105
106 #if CY_SYSTEM_CPU_CM0P
107 cy_stc_scb_uart_config_t config = KITPROG_UART_config;
108
109 /* Assign and configure pins, assign clock divider */
110 retval = Cy_SCB_UART_Init(uart_dev->base, &config, NULL);
111
112 Cy_SCB_UART_ClearRxFifo(uart_dev->base);
113 Cy_SCB_UART_ClearTxFifo(uart_dev->base);
114
115 if (retval == CY_SCB_UART_SUCCESS)
116 Cy_SCB_UART_Enable(uart_dev->base);
117 #else
118 // all hw initializations is done on the cm0p side
119 retval = CY_SCB_UART_SUCCESS;
120
121 #endif
122 return USARTx_convert_retval(retval);
123 }
124
ARM_USARTx_Uninitialize(UARTx_Resources * uart_dev)125 static uint32_t ARM_USARTx_Uninitialize(UARTx_Resources* uart_dev)
126 {
127 Cy_SCB_UART_Disable(uart_dev->base, NULL);
128
129 Cy_SCB_UART_DeInit(uart_dev->base);
130
131 return ARM_DRIVER_OK;
132 }
133
134
ARM_USARTx_PowerControl(UARTx_Resources * uart_dev,ARM_POWER_STATE state)135 static int32_t ARM_USARTx_PowerControl(UARTx_Resources* uart_dev,
136 ARM_POWER_STATE state)
137 {
138 ARG_UNUSED(uart_dev);
139
140 switch (state) {
141 case ARM_POWER_OFF:
142 case ARM_POWER_LOW:
143 return ARM_DRIVER_ERROR_UNSUPPORTED;
144 case ARM_POWER_FULL:
145 /* Nothing to be done */
146 return ARM_DRIVER_OK;
147 /* default: The default is not defined intentionally to force the
148 * compiler to check that all the enumeration values are
149 * covered in the switch.*/
150 }
151 }
152
ARM_USARTx_Send(UARTx_Resources * uart_dev,const void * data,uint32_t num)153 static int32_t ARM_USARTx_Send(UARTx_Resources* uart_dev, const void *data,
154 uint32_t num)
155 {
156 void *p_data = (void *)data;
157
158 if ((data == NULL) || (num == 0U)) {
159 /* Invalid parameters */
160 return ARM_DRIVER_ERROR_PARAMETER;
161 }
162
163 Cy_SCB_UART_PutArrayBlocking(uart_dev->base, p_data, num);
164
165 while (!Cy_SCB_UART_IsTxComplete(uart_dev->base))
166 ;
167
168 uart_dev->tx_nbr_bytes = num;
169
170 return ARM_DRIVER_OK;
171 }
172
ARM_USARTx_Receive(UARTx_Resources * uart_dev,void * data,uint32_t num)173 static int32_t ARM_USARTx_Receive(UARTx_Resources* uart_dev,
174 void *data, uint32_t num)
175 {
176 if ((data == NULL) || (num == 0U)) {
177 // Invalid parameters
178 return ARM_DRIVER_ERROR_PARAMETER;
179 }
180
181 Cy_SCB_UART_GetArrayBlocking(uart_dev->base, data, num);
182
183 uart_dev->rx_nbr_bytes = num;
184
185 return ARM_DRIVER_OK;
186 }
187
ARM_USARTx_Transfer(UARTx_Resources * uart_dev,const void * data_out,void * data_in,uint32_t num)188 static int32_t ARM_USARTx_Transfer(UARTx_Resources* uart_dev,
189 const void *data_out, void *data_in,
190 uint32_t num)
191 {
192 ARG_UNUSED(uart_dev);
193 ARG_UNUSED(data_out);
194 ARG_UNUSED(data_in);
195 ARG_UNUSED(num);
196
197 return ARM_DRIVER_ERROR_UNSUPPORTED;
198 }
199
ARM_USARTx_GetTxCount(UARTx_Resources * uart_dev)200 static uint32_t ARM_USARTx_GetTxCount(UARTx_Resources* uart_dev)
201 {
202 return uart_dev->tx_nbr_bytes;
203 }
204
ARM_USARTx_GetRxCount(UARTx_Resources * uart_dev)205 static uint32_t ARM_USARTx_GetRxCount(UARTx_Resources* uart_dev)
206 {
207 return uart_dev->rx_nbr_bytes;
208 }
209
USARTx_SetDataBits(uint32_t control,cy_stc_scb_uart_config_t * config)210 static int32_t USARTx_SetDataBits(uint32_t control,
211 cy_stc_scb_uart_config_t *config)
212 {
213 switch (control & ARM_USART_DATA_BITS_Msk) {
214 case ARM_USART_DATA_BITS_5:
215 config->dataWidth = 5;
216 break;
217
218 case ARM_USART_DATA_BITS_6:
219 config->dataWidth = 6;
220 break;
221
222 case ARM_USART_DATA_BITS_7:
223 config->dataWidth = 7;
224 break;
225
226 case ARM_USART_DATA_BITS_8:
227 config->dataWidth = 8;
228 break;
229
230 case ARM_USART_DATA_BITS_9:
231 config->dataWidth = 9;
232 break;
233
234 default:
235 return ARM_DRIVER_ERROR_UNSUPPORTED;
236 }
237
238 return ARM_DRIVER_OK;
239 }
240
USARTx_SetParity(uint32_t control,cy_stc_scb_uart_config_t * config)241 static int32_t USARTx_SetParity(uint32_t control,
242 cy_stc_scb_uart_config_t *config)
243 {
244 switch (control & ARM_USART_PARITY_Msk) {
245 case ARM_USART_PARITY_NONE:
246 config->parity = CY_SCB_UART_PARITY_NONE;
247 break;
248
249 case ARM_USART_PARITY_EVEN:
250 config->parity = CY_SCB_UART_PARITY_EVEN;
251 break;
252
253 case ARM_USART_PARITY_ODD:
254 config->parity = CY_SCB_UART_PARITY_ODD;
255 break;
256
257 default:
258 return ARM_DRIVER_ERROR_UNSUPPORTED;
259 }
260
261 return ARM_DRIVER_OK;
262 }
263
USARTx_SetStopBits(uint32_t control,cy_stc_scb_uart_config_t * config)264 static int32_t USARTx_SetStopBits(uint32_t control,
265 cy_stc_scb_uart_config_t *config)
266 {
267 switch (control & ARM_USART_STOP_BITS_Msk) {
268 case ARM_USART_STOP_BITS_1:
269 config->stopBits = CY_SCB_UART_STOP_BITS_1;
270 break;
271
272 case ARM_USART_STOP_BITS_2:
273 config->stopBits = CY_SCB_UART_STOP_BITS_2;
274 break;
275
276 case ARM_USART_STOP_BITS_1_5:
277 config->stopBits = CY_SCB_UART_STOP_BITS_1_5;
278 break;
279
280 default:
281 return ARM_DRIVER_ERROR_UNSUPPORTED;
282 }
283
284 return ARM_DRIVER_OK;
285 }
286
USARTx_SetFlowControl(uint32_t control,cy_stc_scb_uart_config_t * config)287 static void USARTx_SetFlowControl(uint32_t control,
288 cy_stc_scb_uart_config_t *config)
289 {
290 /* First, deal with CTS */
291 switch (control & ARM_USART_FLOW_CONTROL_Msk) {
292 case ARM_USART_FLOW_CONTROL_NONE:
293 case ARM_USART_FLOW_CONTROL_RTS:
294 config->enableCts = false;
295 config->ctsPolarity = CY_SCB_UART_ACTIVE_LOW;
296 break;
297
298 case ARM_USART_FLOW_CONTROL_CTS:
299 case ARM_USART_FLOW_CONTROL_RTS_CTS:
300 config->enableCts = true;
301 config->ctsPolarity = CY_SCB_UART_ACTIVE_LOW;
302 break;
303 }
304
305 /* Then RTS */
306 switch (control & ARM_USART_FLOW_CONTROL_Msk) {
307 case ARM_USART_FLOW_CONTROL_NONE:
308 case ARM_USART_FLOW_CONTROL_CTS:
309 config->rtsRxFifoLevel = 0;
310 config->rtsPolarity = CY_SCB_UART_ACTIVE_LOW;
311 break;
312
313 case ARM_USART_FLOW_CONTROL_RTS:
314 case ARM_USART_FLOW_CONTROL_RTS_CTS:
315 config->rtsRxFifoLevel = 8; /* TODO What's a sensible value ? */
316 config->rtsPolarity = CY_SCB_UART_ACTIVE_LOW;
317 break;
318 }
319 }
320
ARM_USARTx_Control(UARTx_Resources * uart_dev,uint32_t control,uint32_t arg)321 static int32_t ARM_USARTx_Control(UARTx_Resources* uart_dev, uint32_t control,
322 uint32_t arg)
323 {
324 cy_stc_scb_uart_config_t config = KITPROG_UART_config;
325 uint32_t retval;
326
327 switch (control & ARM_USART_CONTROL_Msk) {
328 case ARM_USART_MODE_ASYNCHRONOUS:
329 /* TODO Default values work for 115200 baud,
330 * but we should set config.oversample to
331 * a value derived from the divider
332 */
333 break;
334 /* Unsupported command */
335 default:
336 return ARM_DRIVER_ERROR_UNSUPPORTED;
337 }
338
339 Cy_SCB_UART_Disable(uart_dev->base, NULL);
340
341 /* UART Data bits */
342 retval = USARTx_SetDataBits(control, &config);
343 if (retval != ARM_DRIVER_OK)
344 return retval;
345
346 /* UART Parity */
347 retval = USARTx_SetParity(control, &config);
348 if (retval != ARM_DRIVER_OK)
349 return retval;
350
351 /* USART Stop bits */
352 retval = USARTx_SetStopBits(control, &config);
353 if (retval != ARM_DRIVER_OK)
354 return retval;
355
356 /* USART Flow Control */
357 USARTx_SetFlowControl(control, &config);
358
359 Cy_SCB_UART_ClearRxFifo(uart_dev->base);
360 Cy_SCB_UART_ClearTxFifo(uart_dev->base);
361
362 Cy_SCB_UART_Enable(uart_dev->base);
363
364 return ARM_DRIVER_OK;
365 }
366
ARM_USARTx_GetStatus(UARTx_Resources * uart_dev)367 static ARM_USART_STATUS ARM_USARTx_GetStatus(UARTx_Resources* uart_dev)
368 {
369 ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0};
370 return status;
371 }
372
ARM_USARTx_SetModemControl(UARTx_Resources * uart_dev,ARM_USART_MODEM_CONTROL control)373 static int32_t ARM_USARTx_SetModemControl(UARTx_Resources* uart_dev,
374 ARM_USART_MODEM_CONTROL control)
375 {
376 ARG_UNUSED(control);
377 return ARM_DRIVER_ERROR_UNSUPPORTED;
378 }
379
ARM_USARTx_GetModemStatus(UARTx_Resources * uart_dev)380 static ARM_USART_MODEM_STATUS ARM_USARTx_GetModemStatus(UARTx_Resources* uart_dev)
381 {
382 ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0};
383 return modem_status;
384 }
385
386 /* Per-UART macros */
387 #define DEFINE_UARTX(N) static UARTx_Resources USART##N##_DEV = { \
388 .base = SCB##N, \
389 .tx_nbr_bytes = 0, \
390 .rx_nbr_bytes = 0, \
391 .cb_event = NULL, \
392 }; \
393 \
394 static int32_t ARM_USART##N##_Initialize(ARM_USART_SignalEvent_t cb_event) \
395 { \
396 USART##N##_DEV.cb_event = cb_event; \
397 return ARM_USARTx_Initialize(&USART##N##_DEV); \
398 } \
399 \
400 static int32_t ARM_USART##N##_Uninitialize(void) \
401 { \
402 return ARM_USARTx_Uninitialize(&USART##N##_DEV); \
403 } \
404 \
405 static int32_t ARM_USART##N##_PowerControl(ARM_POWER_STATE state) \
406 { \
407 return ARM_USARTx_PowerControl(&USART##N##_DEV, state); \
408 } \
409 \
410 static int32_t ARM_USART##N##_Send(const void *data, uint32_t num) \
411 { \
412 return ARM_USARTx_Send(&USART##N##_DEV, data, num); \
413 } \
414 \
415 static int32_t ARM_USART##N##_Receive(void *data, uint32_t num) \
416 { \
417 return ARM_USARTx_Receive(&USART##N##_DEV, data, num); \
418 } \
419 \
420 static int32_t ARM_USART##N##_Transfer(const void *data_out, void *data_in, \
421 uint32_t num) \
422 { \
423 return ARM_USARTx_Transfer(&USART##N##_DEV, data_out, data_in, num); \
424 } \
425 \
426 static uint32_t ARM_USART##N##_GetTxCount(void) \
427 { \
428 return ARM_USARTx_GetTxCount(&USART##N##_DEV); \
429 } \
430 \
431 static uint32_t ARM_USART##N##_GetRxCount(void) \
432 { \
433 return ARM_USARTx_GetRxCount(&USART##N##_DEV); \
434 } \
435 static int32_t ARM_USART##N##_Control(uint32_t control, uint32_t arg) \
436 { \
437 return ARM_USARTx_Control(&USART##N##_DEV, control, arg); \
438 } \
439 \
440 static ARM_USART_STATUS ARM_USART##N##_GetStatus(void) \
441 { \
442 return ARM_USARTx_GetStatus(&USART##N##_DEV); \
443 } \
444 \
445 static int32_t ARM_USART##N##_SetModemControl(ARM_USART_MODEM_CONTROL control) \
446 { \
447 return ARM_USARTx_SetModemControl(&USART##N##_DEV, control); \
448 } \
449 \
450 static ARM_USART_MODEM_STATUS ARM_USART##N##_GetModemStatus(void) \
451 { \
452 return ARM_USARTx_GetModemStatus(&USART##N##_DEV); \
453 } \
454 \
455 extern ARM_DRIVER_USART Driver_USART##N; \
456 ARM_DRIVER_USART Driver_USART##N = { \
457 ARM_USART_GetVersion, \
458 ARM_USART_GetCapabilities, \
459 ARM_USART##N##_Initialize, \
460 ARM_USART##N##_Uninitialize, \
461 ARM_USART##N##_PowerControl, \
462 ARM_USART##N##_Send, \
463 ARM_USART##N##_Receive, \
464 ARM_USART##N##_Transfer, \
465 ARM_USART##N##_GetTxCount, \
466 ARM_USART##N##_GetRxCount, \
467 ARM_USART##N##_Control, \
468 ARM_USART##N##_GetStatus, \
469 ARM_USART##N##_SetModemControl, \
470 ARM_USART##N##_GetModemStatus \
471 };
472
473 #if (RTE_USART0)
474 DEFINE_UARTX(0)
475 #endif
476
477 #if (RTE_USART1)
478 DEFINE_UARTX(1)
479 #endif
480
481 #if (RTE_USART2)
482 DEFINE_UARTX(2)
483 #endif
484
485 #if (RTE_USART3)
486 DEFINE_UARTX(3)
487 #endif
488
489 #if (RTE_USART4)
490 DEFINE_UARTX(4)
491 #endif
492
493 #if (RTE_USART5)
494 DEFINE_UARTX(5)
495 #endif
496
497 #if (RTE_USART6)
498 DEFINE_UARTX(6)
499 #endif
500
501 #if (RTE_USART7)
502 DEFINE_UARTX(7)
503 #endif
504