2 * Copyright (c) 2020-2022 Arm Limited. All rights reserved.
4 * SPDX-License-Identifier: Apache-2.0
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * -----------------------------------------------------------------------------
20 * Project: USART Server
21 * Title: USART Server application
23 * -----------------------------------------------------------------------------
32 #include "USART_Server_Config.h"
33 #include "USART_Server_HW.h"
34 #include "USART_Server.h"
36 #include "cmsis_os2.h"
37 #include "cmsis_compiler.h"
38 #include "cmsis_vio.h"
40 #include "Driver_USART.h" // ::CMSIS Driver:USART
42 #ifndef USART_SERVER_DEBUG
43 #define USART_SERVER_DEBUG 0
46 // Fixed USART Server settings (not available through USART_Server_Config.h)
47 #define USART_SERVER_BAUDRATE 115200 // Baudrate
48 #define USART_SERVER_DATA_BITS 8 // 8 data bits
49 #define USART_SERVER_PARITY 0 // None
50 #define USART_SERVER_STOP_BITS 0 // 1 stop bit
51 #define USART_SERVER_FLOW_CONTROL 0 // None
53 #define USART_RECEIVE_EVENTS_MASK (ARM_USART_EVENT_RECEIVE_COMPLETE | \
54 ARM_USART_EVENT_RX_OVERFLOW | \
55 ARM_USART_EVENT_RX_BREAK | \
56 ARM_USART_EVENT_RX_FRAMING_ERROR | \
57 ARM_USART_EVENT_RX_PARITY_ERROR)
58 #define USART_TRANSFER_EVENTS_MASK (ARM_USART_EVENT_TRANSFER_COMPLETE | \
59 ARM_USART_EVENT_TX_UNDERFLOW | \
60 ARM_USART_EVENT_RX_OVERFLOW)
62 #define DATA_BITS_TO_BYTES(data_bits) ((((data_bits) > 8) ? (2U) : (1U)))
63 #define BYTES_TO_ITEMS(bytes,data_bits) ((bytes + DATA_BITS_TO_BYTES(data_bits) - 1U) / DATA_BITS_TO_BYTES(data_bits))
65 /* Access to Driver_USART# */
66 #define USART_Driver_Aux(n) Driver_USART##n
67 #define USART_Driver_Name(n) USART_Driver_Aux(n)
68 extern ARM_DRIVER_USART USART_Driver_Name(USART_SERVER_DRV_NUM);
69 #define drvUSART (&USART_Driver_Name(USART_SERVER_DRV_NUM))
71 typedef struct { // USART Interface settings structure
76 uint32_t flow_control;
80 uint32_t smartcard_clock;
81 uint32_t smartcard_guard_time;
85 // Structure containing command string and pointer to command handling function
88 int32_t (*Command_Func) (const char *command);
93 // Main thread (reception and execution of command)
95 static void USART_Server_Thread (void *argument);
97 // USART Interface communication functions
98 static void USART_Com_Event (uint32_t event);
99 static int32_t USART_Com_Initialize (void);
100 static int32_t USART_Com_Uninitialize (void);
101 static int32_t USART_Com_PowerOn (void);
102 static int32_t USART_Com_PowerOff (void);
103 static int32_t USART_Com_Configure (const USART_COM_CONFIG_t *config);
104 static int32_t USART_Com_Receive ( void *data_in, uint32_t num, uint32_t timeout);
105 static int32_t USART_Com_Send (const void *data_out, uint32_t num, uint32_t timeout);
106 static int32_t USART_Com_Transfer (const void *data_out, void *data_in, uint32_t num, uint32_t timeout);
107 static int32_t USART_Com_Break (uint32_t val);
108 static int32_t USART_Com_SetModemControl(ARM_USART_MODEM_CONTROL control);
109 static int32_t USART_Com_Abort (void);
110 static uint32_t USART_Com_GetCnt (void);
111 static uint32_t USART_Com_GetMdm (void);
113 // Command handling functions
114 static int32_t USART_Cmd_GetVer (const char *cmd);
115 static int32_t USART_Cmd_GetCap (const char *cmd);
116 static int32_t USART_Cmd_SetBuf (const char *cmd);
117 static int32_t USART_Cmd_GetBuf (const char *cmd);
118 static int32_t USART_Cmd_SetCom (const char *cmd);
119 static int32_t USART_Cmd_Xfer (const char *cmd);
120 static int32_t USART_Cmd_GetCnt (const char *cmd);
121 static int32_t USART_Cmd_SetBrk (const char *cmd);
122 static int32_t USART_Cmd_GetBrk (const char *cmd);
123 static int32_t USART_Cmd_SetMdm (const char *cmd);
124 static int32_t USART_Cmd_GetMdm (const char *cmd);
127 static const uint32_t usart_baudrates[] = {
128 9600U, 19200U, 38400U, 57600U, 115200U, 230400U, 460800U, 921600U
131 static const char *str_mode[] = {
138 // Command specification (command string, command handling function)
139 static const USART_CMD_DESC_t usart_cmd_desc[] = {
140 { "GET VER" , USART_Cmd_GetVer },
141 { "GET CAP" , USART_Cmd_GetCap },
142 { "SET BUF" , USART_Cmd_SetBuf },
143 { "GET BUF" , USART_Cmd_GetBuf },
144 { "SET COM" , USART_Cmd_SetCom },
145 { "XFER" , USART_Cmd_Xfer },
146 { "GET CNT" , USART_Cmd_GetCnt },
147 { "SET BRK" , USART_Cmd_SetBrk },
148 { "GET BRK" , USART_Cmd_GetBrk },
149 { "SET MDM" , USART_Cmd_SetMdm },
150 { "GET MDM" , USART_Cmd_GetMdm }
153 static osThreadId_t usart_server_thread_id = NULL;
154 static osThreadAttr_t thread_attr = {
155 .name = "USART_Server_Thread",
159 static ARM_USART_CAPABILITIES drv_cap;
161 static uint8_t usart_server_state = USART_SERVER_STATE_RECEPTION;
162 static uint32_t usart_cmd_timeout = USART_SERVER_CMD_TIMEOUT;
163 static uint32_t usart_xfer_timeout = USART_SERVER_CMD_TIMEOUT;
164 static uint32_t usart_xfer_cnt = 0U;
165 static uint32_t usart_xfer_buf_size = USART_SERVER_BUF_SIZE;
166 static const USART_COM_CONFIG_t usart_com_config_default = {(USART_SERVER_MODE << ARM_USART_CONTROL_Pos) & ARM_USART_CONTROL_Msk,
167 #if (USART_SERVER_DATA_BITS == 8U)
168 ARM_USART_DATA_BITS_8,
170 (USART_SERVER_DATA_BITS << ARM_USART_DATA_BITS_Pos) & ARM_USART_DATA_BITS_Msk,
172 (USART_SERVER_PARITY << ARM_USART_PARITY_Pos) & ARM_USART_PARITY_Msk,
173 (USART_SERVER_STOP_BITS << ARM_USART_STOP_BITS_Pos) & ARM_USART_STOP_BITS_Msk,
174 (USART_SERVER_FLOW_CONTROL << ARM_USART_FLOW_CONTROL_Pos) & ARM_USART_FLOW_CONTROL_Msk,
180 USART_SERVER_BAUDRATE
182 static USART_COM_CONFIG_t usart_com_config_xfer;
183 static uint8_t usart_bytes_per_item = 1U;
184 static uint8_t usart_cmd_buf_rx[32] __ALIGNED(4);
185 static uint8_t usart_cmd_buf_tx[32] __ALIGNED(4);
186 static uint8_t *ptr_usart_xfer_buf_rx = NULL;
187 static uint8_t *ptr_usart_xfer_buf_tx = NULL;
188 static void *ptr_usart_xfer_buf_rx_alloc = NULL;
189 static void *ptr_usart_xfer_buf_tx_alloc = NULL;
191 static uint32_t break_status = 0U;
192 static uint32_t dcd_ri_mask = 3U;
196 // Default empty implementation if external functions are not provided,
197 // otherwise overridden by externally provided functions
198 __WEAK void USART_Server_Pins_Initialize (void) { dcd_ri_mask = 0U; }
199 __WEAK void USART_Server_Pins_Uninitialize (void) {}
200 __WEAK void USART_Server_Pin_DCD_SetState (uint32_t state) {}
201 __WEAK void USART_Server_Pin_RI_SetState (uint32_t state) {}
204 \fn int32_t USART_Server_Start (void)
205 \brief Initialize, power up, configure USART interface and start USART Server thread.
206 \return execution status
207 - EXIT_SUCCESS: Operation successful
208 - EXIT_FAILURE: Operation failed
210 int32_t USART_Server_Start (void) {
212 uint32_t mode, mode_disp;
214 mode = USART_SERVER_MODE;
231 (void)vioPrint(vioLevelHeading, "USART Server v%s\r\nMode: %s", USART_SERVER_VER, str_mode[mode_disp]);
233 // Initialize local variables
234 usart_server_state = USART_SERVER_STATE_RECEPTION;
235 usart_cmd_timeout = USART_SERVER_CMD_TIMEOUT;
236 usart_xfer_timeout = USART_SERVER_CMD_TIMEOUT;
238 usart_xfer_buf_size = USART_SERVER_BUF_SIZE;
239 usart_bytes_per_item = DATA_BITS_TO_BYTES(USART_SERVER_DATA_BITS);
240 memset(usart_cmd_buf_rx, 0, sizeof(usart_cmd_buf_rx));
241 memset(usart_cmd_buf_tx, 0, sizeof(usart_cmd_buf_tx));
242 memcpy(&usart_com_config_xfer, &usart_com_config_default, sizeof(USART_COM_CONFIG_t));
244 // Allocate buffers for data transmission and reception
245 // (maximum size is incremented by 4 bytes to ensure that buffer can be aligned to 4 bytes)
247 ptr_usart_xfer_buf_rx_alloc = malloc(USART_SERVER_BUF_SIZE + 4U);
248 if (((uint32_t)ptr_usart_xfer_buf_rx_alloc & 3U) != 0U) {
249 // If allocated memory is not 4 byte aligned, use next 4 byte aligned address for ptr_tx_buf
250 ptr_usart_xfer_buf_rx = (uint8_t *)((((uint32_t)ptr_usart_xfer_buf_rx_alloc) + 3U) & (~3U));
252 // If allocated memory is 4 byte aligned, use it directly
253 ptr_usart_xfer_buf_rx = (uint8_t *)ptr_usart_xfer_buf_rx_alloc;
255 ptr_usart_xfer_buf_tx_alloc = malloc(USART_SERVER_BUF_SIZE + 4U);
256 if (((uint32_t)ptr_usart_xfer_buf_tx_alloc & 3U) != 0U) {
257 // If allocated memory is not 4 byte aligned, use next 4 byte aligned address for ptr_tx_buf
258 ptr_usart_xfer_buf_tx = (uint8_t *)((((uint32_t)ptr_usart_xfer_buf_tx_alloc) + 3U) & (~3U));
260 // If allocated memory is 4 byte aligned, use it directly
261 ptr_usart_xfer_buf_tx = (uint8_t *)ptr_usart_xfer_buf_tx_alloc;
264 if ((ptr_usart_xfer_buf_rx != NULL) || (ptr_usart_xfer_buf_tx != NULL)) {
265 memset(ptr_usart_xfer_buf_rx, 0, USART_SERVER_BUF_SIZE);
266 memset(ptr_usart_xfer_buf_rx, 0, USART_SERVER_BUF_SIZE);
272 // Get driver capabilities
273 drv_cap = drvUSART->GetCapabilities();
275 if (ret == EXIT_SUCCESS) {
276 ret = USART_Com_Initialize();
279 if (ret == EXIT_SUCCESS) {
280 ret = USART_Com_PowerOn();
283 if (ret == EXIT_SUCCESS) {
284 ret = USART_Com_Configure(&usart_com_config_default);
287 USART_Server_Pins_Initialize();
289 if ((ret == EXIT_SUCCESS) && (usart_server_thread_id == NULL)) {
290 // Create USART_Server_Thread thread
291 usart_server_thread_id = osThreadNew(USART_Server_Thread, NULL, &thread_attr);
292 if (usart_server_thread_id == NULL) {
297 if (ret != EXIT_SUCCESS) {
298 vioPrint(vioLevelError, "Server Start failed!");
305 \fn int32_t USART_Server_Stop (void)
306 \brief Terminate USART Server thread, power down and uninitialize USART interface.
307 \return execution status
308 - EXIT_SUCCESS: Operation successful
309 - EXIT_FAILURE: Operation failed
311 int32_t USART_Server_Stop (void) {
317 if (usart_server_thread_id != NULL) {
318 usart_server_state = USART_SERVER_STATE_TERMINATE;
319 for (i = 0U; i < 10U; i++) {
320 if (osThreadGetState(usart_server_thread_id) == osThreadTerminated) {
321 usart_server_thread_id = NULL;
329 USART_Server_Pins_Uninitialize();
331 if (ret == EXIT_SUCCESS) {
332 ret = USART_Com_PowerOff();
335 if (ret == EXIT_SUCCESS) {
336 ret = USART_Com_Uninitialize();
339 if (ptr_usart_xfer_buf_rx_alloc != NULL) {
340 free(ptr_usart_xfer_buf_rx_alloc);
341 ptr_usart_xfer_buf_rx = NULL;
342 ptr_usart_xfer_buf_rx_alloc = NULL;
344 if (ptr_usart_xfer_buf_tx_alloc != NULL) {
345 free(ptr_usart_xfer_buf_tx_alloc);
346 ptr_usart_xfer_buf_tx = NULL;
347 ptr_usart_xfer_buf_tx_alloc = NULL;
350 if (ret != EXIT_SUCCESS) {
351 vioPrint(vioLevelError, "Server Stop failed! ");
361 \fn static void USART_Server_Thread (void *argument)
362 \brief USART Server thread function.
363 \detail This is a thread function that waits to receive a command from USART Client
364 (Driver Validation suite), and after command is received it is executed
365 and the process starts again by waiting to receive next command.
366 \param[in] argument Not used
369 static void USART_Server_Thread (void *argument) {
375 switch (usart_server_state) {
377 case USART_SERVER_STATE_RECEPTION: // Receive a command
378 if (USART_Com_Receive(usart_cmd_buf_rx, BYTES_TO_ITEMS(sizeof(usart_cmd_buf_rx),USART_SERVER_DATA_BITS), osWaitForever) == EXIT_SUCCESS) {
379 usart_server_state = USART_SERVER_STATE_EXECUTION;
381 // If 32 byte command was not received restart the reception of 32 byte command
384 case USART_SERVER_STATE_EXECUTION: // Execute a command
385 // Find the command and call handling function
386 for (i = 0U; i < (sizeof(usart_cmd_desc) / sizeof(USART_CMD_DESC_t)); i++) {
387 if (memcmp(usart_cmd_buf_rx, usart_cmd_desc[i].command, strlen(usart_cmd_desc[i].command)) == 0) {
388 (void)usart_cmd_desc[i].Command_Func((const char *)usart_cmd_buf_rx);
392 vioPrint(vioLevelMessage, "%.20s ", usart_cmd_buf_rx);
393 usart_server_state = USART_SERVER_STATE_RECEPTION;
396 case USART_SERVER_STATE_TERMINATE: // Self-terminate the thread
397 default: // Should never happen, processed as terminate request
398 vioPrint(vioLevelError, "Server stopped! ");
399 (void)USART_Com_Abort();
400 (void)osThreadTerminate(osThreadGetId());
407 \fn static void USART_Com_Event (uint32_t event)
408 \brief USART communication event callback (called from USART driver from IRQ context).
409 \detail This function dispatches event (flag) to USART Server thread.
410 \param[in] event USART event
411 - ARM_USART_EVENT_SEND_COMPLETE
412 - ARM_USART_EVENT_RECEIVE_COMPLETE
413 - ARM_USART_EVENT_TRANSFER_COMPLETE
414 - ARM_USART_EVENT_TX_COMPLETE
415 - ARM_USART_EVENT_TX_UNDERFLOW
416 - ARM_USART_EVENT_RX_OVERFLOW
417 - ARM_USART_EVENT_RX_TIMEOUT
418 - ARM_USART_EVENT_RX_BREAK
419 - ARM_USART_EVENT_RX_FRAMING_ERROR
420 - ARM_USART_EVENT_RX_PARITY_ERROR
421 - ARM_USART_EVENT_CTS
422 - ARM_USART_EVENT_DSR
423 - ARM_USART_EVENT_DCD
427 static void USART_Com_Event (uint32_t event) {
429 if ((event & ARM_USART_EVENT_RX_BREAK) != 0U) {
433 if (usart_server_thread_id != NULL) {
434 (void)osThreadFlagsSet(usart_server_thread_id, event);
439 \fn static int32_t USART_Com_Initialize (void)
440 \brief Initialize USART interface.
441 \return execution status
442 - EXIT_SUCCESS: Operation successful
443 - EXIT_FAILURE: Operation failed
445 static int32_t USART_Com_Initialize (void) {
450 if (drvUSART->Initialize(USART_Com_Event) == ARM_DRIVER_OK) {
458 \fn static int32_t USART_Com_Uninitialize (void)
459 \brief Uninitialize USART interface.
460 \return execution status
461 - EXIT_SUCCESS: Operation successful
462 - EXIT_FAILURE: Operation failed
464 static int32_t USART_Com_Uninitialize (void) {
469 if (drvUSART->Uninitialize() == ARM_DRIVER_OK) {
477 \fn static int32_t USART_Com_PowerOn (void)
478 \brief Power-up USART interface.
479 \return execution status
480 - EXIT_SUCCESS: Operation successful
481 - EXIT_FAILURE: Operation failed
483 static int32_t USART_Com_PowerOn (void) {
488 if (drvUSART->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK) {
496 \fn static int32_t USART_Com_PowerOff (void)
497 \brief Power-down USART interface.
498 \return execution status
499 - EXIT_SUCCESS: Operation successful
500 - EXIT_FAILURE: Operation failed
502 static int32_t USART_Com_PowerOff (void) {
507 if (drvUSART->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK) {
515 \fn static int32_t USART_Com_Configure (const USART_COM_CONFIG_t *config)
516 \brief Configure USART interface.
517 \param[in] config Pointer to structure containing USART interface configuration settings
518 \return execution status
519 - EXIT_SUCCESS: Operation successful
520 - EXIT_FAILURE: Operation failed
522 static int32_t USART_Com_Configure (const USART_COM_CONFIG_t *config) {
527 if (drvUSART->Control(config->mode |
531 config->flow_control |
535 config->smartcard_clock |
536 config->smartcard_guard_time,
537 config->baudrate ) == ARM_DRIVER_OK) {
538 usart_bytes_per_item = 1U;
539 if (config->data_bits == ARM_USART_DATA_BITS_9) {
540 usart_bytes_per_item = 2U;
544 if (ret == EXIT_SUCCESS) {
545 if (drvUSART->Control(ARM_USART_CONTROL_RX, 1U) == ARM_DRIVER_OK) {
549 if (ret == EXIT_SUCCESS) {
550 if (drvUSART->Control(ARM_USART_CONTROL_TX, 1U) == ARM_DRIVER_OK) {
559 \fn static int32_t USART_Com_Receive (void *data_in, uint32_t num, uint32_t timeout)
560 \brief Receive data (command) over USART interface.
561 \param[out] data_in Pointer to memory where data will be received
562 \param[in] num Number of data items to be received
563 \param[in] timeout Timeout for reception (in ms)
564 \return execution status
565 - EXIT_SUCCESS: Operation successful
566 - EXIT_FAILURE: Operation failed
568 static int32_t USART_Com_Receive (void *data_in, uint32_t num, uint32_t timeout) {
574 if (usart_server_thread_id != NULL) {
575 memset(data_in, (int32_t)'?', usart_bytes_per_item * num);
576 vioSetSignal (vioLED0, vioLEDon);
577 osThreadFlagsClear(0x7FFFFFFFU);
578 if (drvUSART->Control(ARM_USART_CONTROL_RX, 1U) == ARM_DRIVER_OK) {
579 if (drvUSART->Receive(data_in, num) == ARM_DRIVER_OK) {
580 if (timeout == osWaitForever) { // Reception of next command
582 flags = osThreadFlagsWait(USART_RECEIVE_EVENTS_MASK, osFlagsWaitAny, 1U);
583 if ((flags & 0x80000000U) != 0U) { // If timeout
584 if (drvUSART->GetRxCount() != 0U) {
585 // If something was received, wait and try to receive complete command
586 flags = osThreadFlagsWait(USART_RECEIVE_EVENTS_MASK, osFlagsWaitAny, USART_SERVER_CMD_TIMEOUT);
587 if ((flags & (0x80000000U | ARM_USART_EVENT_RECEIVE_COMPLETE)) == ARM_USART_EVENT_RECEIVE_COMPLETE) {
588 // If completed event was signaled
592 // In all other cases exit with failed status
598 } else { // Reception during XFER
599 flags = osThreadFlagsWait(ARM_USART_EVENT_RECEIVE_COMPLETE, osFlagsWaitAny, timeout);
600 if ((flags & (0x80000000U | ARM_USART_EVENT_RECEIVE_COMPLETE)) == ARM_USART_EVENT_RECEIVE_COMPLETE) {
601 // If completed event was signaled
605 if (ret != EXIT_SUCCESS) {
606 // If receive was activated but failed to receive expected data then abort the reception
607 (void)drvUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
610 (void)drvUSART->Control(ARM_USART_CONTROL_RX, 0U);
612 vioSetSignal (vioLED0, vioLEDoff);
619 \fn static int32_t USART_Com_Send (const void *data_out, uint32_t num, uint32_t timeout)
620 \brief Send data (response) over USART interface.
621 \param[out] data_out Pointer to memory containing data to be sent
622 \param[in] num Number of data items to be sent
623 \param[in] timeout Timeout for send (in ms)
624 \return execution status
625 - EXIT_SUCCESS: Operation successful
626 - EXIT_FAILURE: Operation failed
628 static int32_t USART_Com_Send (const void *data_out, uint32_t num, uint32_t timeout) {
635 if (usart_server_thread_id != NULL) {
636 vioSetSignal (vioLED1, vioLEDon);
637 osThreadFlagsClear(0x7FFFFFFFU);
638 if (drvUSART->Control(ARM_USART_CONTROL_TX, 1U) == ARM_DRIVER_OK) {
639 if (drvUSART->Send(data_out, num) == ARM_DRIVER_OK) {
640 if (drv_cap.event_tx_complete != 0U) {
641 // If ARM_USART_EVENT_TX_COMPLETE is supported, wait for it
642 flags = osThreadFlagsWait(ARM_USART_EVENT_TX_COMPLETE, osFlagsWaitAny, timeout);
643 if ((flags & (0x80000000U | ARM_USART_EVENT_TX_COMPLETE)) == ARM_USART_EVENT_TX_COMPLETE) {
644 // If completed event was signaled
648 // Otherwise wait for ARM_USART_EVENT_SEND_COMPLETE flag
649 flags = osThreadFlagsWait(ARM_USART_EVENT_SEND_COMPLETE, osFlagsWaitAny, timeout);
650 if ((flags & (0x80000000U | ARM_USART_EVENT_SEND_COMPLETE)) == ARM_USART_EVENT_SEND_COMPLETE) {
651 // Wait for data to be transmitted on the Tx wire, up to 10 ms.
652 // Send complete signals when data was consumed by FIFO not when it was actually
654 for (tcnt = 0U; tcnt < 10U; tcnt ++) {
655 if (drvUSART->GetStatus().tx_busy == 0U) {
663 if (ret != EXIT_SUCCESS) {
664 // If send was activated but failed to send all of the expected data then abort the send
665 (void)drvUSART->Control(ARM_USART_ABORT_SEND, 0U);
668 (void)drvUSART->Control(ARM_USART_CONTROL_TX, 0U);
670 vioSetSignal (vioLED1, vioLEDoff);
677 \fn static int32_t USART_Com_Transfer (const void *data_out, void *data_in, uint32_t num, uint32_t timeout)
678 \brief Transfer (send/receive) data over USART interface.
679 \param[in] data_out Pointer to memory containing data to be sent
680 \param[out] data_in Pointer to memory where data will be received
681 \param[in] num Number of data items to be transferred
682 \param[in] timeout Timeout for transfer (in ms)
683 \return execution status
684 - EXIT_SUCCESS: Operation successful
685 - EXIT_FAILURE: Operation failed
687 static int32_t USART_Com_Transfer (const void *data_out, void *data_in, uint32_t num, uint32_t timeout) {
693 if (usart_server_thread_id != NULL) {
694 vioSetSignal (vioLED2, vioLEDon);
695 osThreadFlagsClear(0x7FFFFFFFU);
696 if (drvUSART->Transfer(data_out, data_in, num) == ARM_DRIVER_OK) {
697 flags = osThreadFlagsWait(USART_TRANSFER_EVENTS_MASK, osFlagsWaitAny, timeout);
698 usart_xfer_cnt = drvUSART->GetTxCount();
699 vioSetSignal (vioLED2, vioLEDoff);
700 if ((flags & (0x80000000U | ARM_USART_EVENT_TRANSFER_COMPLETE)) == ARM_USART_EVENT_TRANSFER_COMPLETE) {
701 // If completed event was signaled
704 // If error or timeout
705 (void)drvUSART->Control(ARM_USART_ABORT_TRANSFER, 0U);
714 \fn static int32_t USART_Com_Break (uint32_t val)
715 \brief Control USART Break signaling.
716 \return execution status
717 - EXIT_SUCCESS: Operation successful
718 - EXIT_FAILURE: Operation failed
720 static int32_t USART_Com_Break (uint32_t val) {
725 if (drvUSART->Control(ARM_USART_CONTROL_BREAK, val) == ARM_DRIVER_OK) {
733 \fn static int32_t USART_Com_SetModemControl (ARM_USART_MODEM_CONTROL control)
734 \brief Set USART Modem Control line state.
735 \return execution status
736 - EXIT_SUCCESS: Operation successful
737 - EXIT_FAILURE: Operation failed
739 static int32_t USART_Com_SetModemControl (ARM_USART_MODEM_CONTROL control) {
744 if (drvUSART->SetModemControl(control) == ARM_DRIVER_OK) {
752 \fn static int32_t USART_Com_Abort (void)
753 \brief Abort current transfer on USART interface.
754 \return execution status
755 - EXIT_SUCCESS: Operation successful
756 - EXIT_FAILURE: Operation failed
758 static int32_t USART_Com_Abort (void) {
763 if (drvUSART->Control(ARM_USART_ABORT_TRANSFER, 0U) == ARM_DRIVER_OK) {
771 \fn static uint32_t USART_Com_GetCnt (void)
772 \brief Get number of data items transferred over USART interface in last transfer.
773 \return number of data items transferred
775 static uint32_t USART_Com_GetCnt (void) {
776 return usart_xfer_cnt;
780 // Command handling functions
783 \fn static int32_t USART_Cmd_GetVer (const char *cmd)
784 \brief Handle command "GET VER".
785 \detail Return USART Server version over USART interface (16 bytes).
786 \param[in] cmd Pointer to null-terminated command string
787 \return execution status
788 - EXIT_SUCCESS: Operation successful
789 - EXIT_FAILURE: Operation failed
791 static int32_t USART_Cmd_GetVer (const char *cmd) {
795 memset(usart_cmd_buf_tx, 0, 16);
796 memcpy(usart_cmd_buf_tx, USART_SERVER_VER, sizeof(USART_SERVER_VER));
798 (void)osDelay(10U); // Give client time to start the reception
800 return (USART_Com_Send(usart_cmd_buf_tx, BYTES_TO_ITEMS(16U, USART_SERVER_DATA_BITS), usart_cmd_timeout));
804 \fn static int32_t USART_Cmd_GetCap (const char *cmd)
805 \brief Handle command "GET CAP".
806 \detail Return USART Server capabilities over USART interface (32 bytes).
807 \param[in] cmd Pointer to null-terminated command string
808 \return execution status
809 - EXIT_SUCCESS: Operation successful
810 - EXIT_FAILURE: Operation failed
812 static int32_t USART_Cmd_GetCap (const char *cmd) {
814 uint32_t mode_mask, data_bits_mask, parity_mask, stop_bits_mask;
815 uint32_t flow_control_mask, modem_lines_mask, min_baudrate, max_baudrate;
819 // Disable Rx and Tx during capabilities detection
820 drvUSART->Control(ARM_USART_CONTROL_RX, 0U);
821 drvUSART->Control(ARM_USART_CONTROL_TX, 0U);
827 def_br = usart_com_config_default.baudrate;
829 // Determine supported minimum baudrate
830 // Find minimum baudrate setting at which Control function succeeds
831 for (i = 0; i < (sizeof(usart_baudrates) / sizeof(uint32_t)); i++) {
832 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, usart_baudrates[i]) == ARM_DRIVER_OK) {
836 if (i == (sizeof(usart_baudrates) / sizeof(uint32_t))) {
839 min_baudrate = usart_baudrates[i];
841 // Determine supported maximum baudrate
842 // Find maximum baudrate setting at which Control function succeeds
843 for (i = ((sizeof(usart_baudrates) / sizeof(uint32_t))) - 1; i >= 0U; i--) {
844 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, usart_baudrates[i]) == ARM_DRIVER_OK) {
851 max_baudrate = usart_baudrates[i];
853 // Check baudrate values which are power of 10 for maximum supported baudrate
856 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br) == ARM_DRIVER_OK) {
859 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br / 2U) == ARM_DRIVER_OK) {
863 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br / 5U) == ARM_DRIVER_OK) {
868 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br) == ARM_DRIVER_OK) {
871 } while (br > 10000U);
872 if (br > max_baudrate) {
876 // Determine supported modes
878 if (drv_cap.asynchronous != 0U) {
881 if (drv_cap.synchronous_master != 0U) {
882 mode_mask |= 1U << 1;
884 if (drv_cap.synchronous_slave != 0U) {
885 mode_mask |= 1U << 2;
887 if (drv_cap.single_wire != 0U) {
888 mode_mask |= 1U << 3;
890 if (drv_cap.irda != 0U) {
891 mode_mask |= 1U << 4;
893 if (drv_cap.smart_card != 0U) {
894 mode_mask |= 1U << 5;
897 // Determine supported data bits
899 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_5, def_br) == ARM_DRIVER_OK) {
900 data_bits_mask |= 1U;
902 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_6, def_br) == ARM_DRIVER_OK) {
903 data_bits_mask |= 1U << 1;
905 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_7, def_br) == ARM_DRIVER_OK) {
906 data_bits_mask |= 1U << 2;
908 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_8, def_br) == ARM_DRIVER_OK) {
909 data_bits_mask |= 1U << 3;
911 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_9, def_br) == ARM_DRIVER_OK) {
912 data_bits_mask |= 1U << 4;
915 // Determine supported parity options
917 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_PARITY_NONE, def_br) == ARM_DRIVER_OK) {
920 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_PARITY_EVEN, def_br) == ARM_DRIVER_OK) {
921 parity_mask |= 1U << 1;
923 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_PARITY_ODD, def_br) == ARM_DRIVER_OK) {
924 parity_mask |= 1U << 2;
927 // Determine supported stop bits
929 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_1, def_br) == ARM_DRIVER_OK) {
930 stop_bits_mask |= 1U;
932 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_2, def_br) == ARM_DRIVER_OK) {
933 stop_bits_mask |= 1U << 1;
935 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_1_5, def_br) == ARM_DRIVER_OK) {
936 stop_bits_mask |= 1U << 2;
938 if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_0_5, def_br) == ARM_DRIVER_OK) {
939 stop_bits_mask |= 1U << 3;
942 // Determine supported flow control options
943 flow_control_mask = 1U; // No flow control is always supported
944 if ((drv_cap.cts != 0U) && (drv_cap.flow_control_cts != 0U)) {
945 flow_control_mask |= 1U << 1;
947 if (drv_cap.rts != 0U) {
948 flow_control_mask |= 1U << 2;
950 if ((drv_cap.rts != 0U) && (drv_cap.cts != 0U) && (drv_cap.flow_control_cts != 0U)) {
951 flow_control_mask |= 1U << 3;
954 // Determine available modem lines
955 modem_lines_mask = 0U;
956 if (drv_cap.rts != 0U) {
957 modem_lines_mask |= 1U;
959 if (drv_cap.cts != 0U) {
960 modem_lines_mask |= 1U << 1;
962 if (drv_cap.dtr != 0U) {
963 modem_lines_mask |= 1U << 2;
965 if (drv_cap.dsr != 0U) {
966 modem_lines_mask |= 1U << 3;
968 if ((dcd_ri_mask & 1U) != 0U) {
969 modem_lines_mask |= 1U << 4;
971 if ((dcd_ri_mask & 2U) != 0U) {
972 modem_lines_mask |= 1U << 5;
975 // Revert communication settings to default because they were changed during auto-detection of capabilities
976 (void)USART_Com_Configure(&usart_com_config_default);
978 (void)osDelay(25U); // Give client time to start the reception
980 memset(usart_cmd_buf_tx, 0, 32);
981 if (snprintf((char *)usart_cmd_buf_tx, 32, "%02X,%02X,%01X,%01X,%01X,%01X,%i,%i",
989 max_baudrate) <= 32) {
990 ret = USART_Com_Send(usart_cmd_buf_tx, BYTES_TO_ITEMS(32U, USART_SERVER_DATA_BITS), usart_cmd_timeout);
997 \fn static int32_t USART_Cmd_SetBuf (const char *cmd)
998 \brief Handle command "SET BUF RX/TX,len[,pattern]".
999 \detail Initialize content of the buffer in the following way:
1000 - fill whole buffer with 'pattern' value if it is specified, and 'len' is 0
1001 - fill whole buffer with 0 if 'pattern' is not provided and 'len' is 0
1002 - load 'len' bytes from start of the buffer with content
1003 received in IN data phase
1004 \param[in] cmd Pointer to null-terminated command string
1005 \return execution status
1006 - EXIT_SUCCESS: Operation successful
1007 - EXIT_FAILURE: Operation failed
1009 static int32_t USART_Cmd_SetBuf (const char *cmd) {
1010 const char *ptr_str;
1023 // Parse 'RX' or 'TX' selection
1024 if (strstr(cmd, "RX") != NULL) {
1025 ptr_buf = ptr_usart_xfer_buf_rx;
1026 } else if (strstr(cmd, "TX") != NULL) {
1027 ptr_buf = ptr_usart_xfer_buf_tx;
1032 if (ret == EXIT_SUCCESS) {
1034 ptr_str = strstr(cmd, ","); // Find ','
1035 if (ptr_str != NULL) { // If ',' was found
1036 ptr_str++; // Skip ','
1037 while (*ptr_str == ' ') { // Skip whitespaces after ','
1040 if (sscanf(ptr_str, "%u", &val) == 1) {
1041 if (val <= usart_xfer_buf_size) {
1054 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1055 // Parse optional 'pattern'
1056 ptr_str = strstr(ptr_str, ","); // Find ','
1057 if (ptr_str != NULL) { // If ',' was found
1058 ptr_str++; // Skip ','
1059 while (*ptr_str == ' ') { // Skip whitespaces after ','
1062 if (sscanf(ptr_str, "%x", &val) == 1) {
1063 pattern = (uint8_t)val;
1070 if ((ret == EXIT_SUCCESS) && (ptr_buf != NULL)) {
1071 // Fill the whole buffer with 'pattern', if 'pattern' was not specified
1072 // in the command then the whole buffer will be filled with 0
1073 memset(ptr_buf, (int32_t)pattern, usart_xfer_buf_size);
1076 if ((ret == EXIT_SUCCESS) && (ptr_buf != NULL) && (len != 0U)) {
1077 // Load 'len' bytes from start of buffer with content received in IN data phase
1078 ret = USART_Com_Receive(ptr_buf, BYTES_TO_ITEMS(len, USART_SERVER_DATA_BITS), usart_cmd_timeout);
1085 \fn static int32_t USART_Cmd_GetBuf (const char *cmd)
1086 \brief Handle command "GET BUF RX/TX,len".
1087 \detail Send content of buffer over USART interface.
1088 \param[in] cmd Pointer to null-terminated command string
1089 \return execution status
1090 - EXIT_SUCCESS: Operation successful
1091 - EXIT_FAILURE: Operation failed
1093 static int32_t USART_Cmd_GetBuf (const char *cmd) {
1094 const char *ptr_str;
1095 const uint8_t *ptr_buf;
1105 // Parse 'RX' or 'TX' selection
1106 if (strstr(cmd, "RX") != NULL) {
1107 ptr_buf = ptr_usart_xfer_buf_rx;
1108 } else if (strstr(cmd, "TX") != NULL) {
1109 ptr_buf = ptr_usart_xfer_buf_tx;
1114 if (ret == EXIT_SUCCESS) {
1116 ptr_str = strstr(cmd, ","); // Find ','
1117 if (ptr_str != NULL) { // If ',' was found
1118 ptr_str++; // Skip ','
1119 while (*ptr_str == ' ') { // Skip whitespaces after ','
1122 if (sscanf(ptr_str, "%u", &val) == 1) {
1123 if ((val > 0U) && (val <= usart_xfer_buf_size)) {
1136 (void)osDelay(10U); // Give client time to start the reception
1138 if ((ret == EXIT_SUCCESS) && (ptr_buf != NULL) && (len != 0U)) {
1139 ret = USART_Com_Send(ptr_buf, BYTES_TO_ITEMS(len, USART_SERVER_DATA_BITS), usart_cmd_timeout);
1146 \fn static int32_t USART_Cmd_SetCom (const char *cmd)
1147 \brief Handle command "SET COM mode,data_bits,parity,stop_bits,flow_ctrl,cpol,cpha,baudrate".
1148 \detail Set communication configuration settings used for transfers (XFER commands).
1149 \param[in] cmd Pointer to null-terminated command string
1150 \return execution status
1151 - EXIT_SUCCESS: Operation successful
1152 - EXIT_FAILURE: Operation failed
1154 static int32_t USART_Cmd_SetCom (const char *cmd) {
1155 const char *ptr_str;
1162 ptr_str = &cmd[7]; // Skip "SET COM"
1163 while (*ptr_str == ' ') { // Skip whitespaces
1168 if (sscanf(ptr_str, "%u", &val) == 1) {
1170 case 1U: // Asynchronous mode
1171 usart_com_config_xfer.mode = ARM_USART_MODE_ASYNCHRONOUS;
1173 case 2U: // Synchronous Master mode
1174 usart_com_config_xfer.mode = ARM_USART_MODE_SYNCHRONOUS_MASTER;
1176 case 3U: // Synchronous Slave mode
1177 usart_com_config_xfer.mode = ARM_USART_MODE_SYNCHRONOUS_SLAVE;
1179 case 4U: // Single Wire mode
1180 usart_com_config_xfer.mode = ARM_USART_MODE_SINGLE_WIRE;
1182 case 5U: // IrDA mode
1183 usart_com_config_xfer.mode = ARM_USART_MODE_IRDA;
1185 case 6U: // Smart Card mode
1186 usart_com_config_xfer.mode = ARM_USART_MODE_SMART_CARD;
1196 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1197 // Parse 'data_bits'
1198 ptr_str = strstr(ptr_str, ","); // Find ','
1199 if (ptr_str != NULL) { // If ',' was found
1200 ptr_str++; // Skip ','
1201 while (*ptr_str == ' ') { // Skip whitespaces after ','
1204 if (sscanf(ptr_str, "%u", &val) == 1) {
1206 case 5U: // 5 data bits
1207 usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_5;
1209 case 6U: // 6 data bits
1210 usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_6;
1212 case 7U: // 7 data bits
1213 usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_7;
1215 case 8U: // 8 data bits
1216 usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_8;
1218 case 9U: // 9 data bits
1219 usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_9;
1231 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1233 ptr_str = strstr(ptr_str, ","); // Find ','
1234 if (ptr_str != NULL) { // If ',' was found
1235 ptr_str++; // Skip ','
1236 while (*ptr_str == ' ') { // Skip whitespaces after ','
1239 if (sscanf(ptr_str, "%u", &val) == 1) {
1241 case 0U: // No parity
1242 usart_com_config_xfer.parity = ARM_USART_PARITY_NONE;
1244 case 1U: // Even parity
1245 usart_com_config_xfer.parity = ARM_USART_PARITY_EVEN;
1247 case 2U: // Odd parity
1248 usart_com_config_xfer.parity = ARM_USART_PARITY_ODD;
1260 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1261 // Parse 'stop_bits'
1262 ptr_str = strstr(ptr_str, ","); // Find ','
1263 if (ptr_str != NULL) { // If ',' was found
1264 ptr_str++; // Skip ','
1265 while (*ptr_str == ' ') { // Skip whitespaces after ','
1268 if (sscanf(ptr_str, "%u", &val) == 1) {
1270 case 0U: // 1 stop bit
1271 usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_1;
1273 case 1U: // 2 stop bits
1274 usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_2;
1276 case 2U: // 1.5 stop bits
1277 usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_1_5;
1279 case 3U: // 0.5 stop bits
1280 usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_0_5;
1292 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1293 // Parse 'flow_ctrl'
1294 ptr_str = strstr(ptr_str, ","); // Find ','
1295 if (ptr_str != NULL) { // If ',' was found
1296 ptr_str++; // Skip ','
1297 while (*ptr_str == ' ') { // Skip whitespaces after ','
1300 if (sscanf(ptr_str, "%u", &val) == 1) {
1302 case 0U: // No flow control
1303 usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_NONE;
1306 usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_RTS;
1309 usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_CTS;
1312 usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_RTS_CTS;
1324 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1326 ptr_str = strstr(ptr_str, ","); // Find ','
1327 if (ptr_str != NULL) { // If ',' was found
1328 ptr_str++; // Skip ','
1329 while (*ptr_str == ' ') { // Skip whitespaces after ','
1332 if (sscanf(ptr_str, "%u", &val) == 1) {
1334 case 0U: // Data are captured on rising edge
1335 usart_com_config_xfer.cpol = ARM_USART_CPOL0;
1337 case 1U: // Data are captured on falling edge
1338 usart_com_config_xfer.cpol = ARM_USART_CPOL1;
1350 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1352 ptr_str = strstr(ptr_str, ","); // Find ','
1353 if (ptr_str != NULL) { // If ',' was found
1354 ptr_str++; // Skip ','
1355 while (*ptr_str == ' ') { // Skip whitespaces after ','
1358 if (sscanf(ptr_str, "%u", &val) == 1) {
1360 case 0U: // Sample on first (leading) edge
1361 usart_com_config_xfer.cpha = ARM_USART_CPHA0;
1363 case 1U: // Sample on second (trailing) edge
1364 usart_com_config_xfer.cpha = ARM_USART_CPHA1;
1376 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1378 ptr_str = strstr(ptr_str, ","); // Find ','
1379 if (ptr_str != NULL) { // If ',' was found
1380 ptr_str++; // Skip ','
1381 while (*ptr_str == ' ') { // Skip whitespaces after ','
1384 if (sscanf(ptr_str, "%u", &val) == 1) {
1385 usart_com_config_xfer.baudrate = val;
1396 \fn static int32_t USART_Cmd_Xfer (const char *cmd)
1397 \brief Handle command "XFER dir,num[,delay][,timeout][,num_rts]".
1398 \detail Send data from USART TX buffer if dir = 0, receive data to USART RX buffer
1399 if dir = 1, or do both if dir = 2.
1400 (buffers must be set with "SET BUF" command before this command).
1401 Transfer start is delayed by optional parameter 'delay' in milliseconds.
1402 \param[in] cmd Pointer to null-terminated command string
1403 \return execution status
1404 - EXIT_SUCCESS: Operation successful
1405 - EXIT_FAILURE: Operation failed
1407 static int32_t USART_Cmd_Xfer (const char *cmd) {
1408 const char *ptr_str;
1409 uint32_t val, dir, num, delay, num_rts;
1411 uint8_t num_rts_provided;
1419 num_rts_provided = 0U;
1421 ptr_str = &cmd[4]; // Skip "XFER"
1422 while (*ptr_str == ' ') { // Skip whitespaces
1427 if (sscanf(ptr_str, "%u", &val) == 1) {
1428 if ((val >= 0U) && (val <= 2U)) {
1437 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1439 ptr_str = strstr(ptr_str, ","); // Find ','
1440 if (ptr_str != NULL) { // If ',' was found
1441 ptr_str++; // Skip ','
1442 while (*ptr_str == ' ') { // Skip whitespaces after ','
1445 if (sscanf(ptr_str, "%u", &val) == 1) {
1446 if ((val > 0U) && (val <= usart_xfer_buf_size)) {
1459 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1460 // Parse optional 'delay'
1461 ptr_str = strstr(ptr_str, ","); // Find ','
1462 if (ptr_str != NULL) { // If ',' was found
1463 ptr_str++; // Skip ','
1464 while (*ptr_str == ' ') { // Skip whitespaces after ','
1467 if (sscanf(ptr_str, "%u", &val) == 1) {
1468 if (val != osWaitForever) {
1479 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1480 // Parse optional 'timeout'
1481 ptr_str = strstr(ptr_str, ","); // Find ','
1482 if (ptr_str != NULL) { // If ',' was found
1483 ptr_str++; // Skip ','
1484 while (*ptr_str == ' ') { // Skip whitespaces after ','
1487 if (sscanf(ptr_str, "%u", &val) == 1) {
1488 if (val != osWaitForever) {
1489 usart_xfer_timeout = val;
1499 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1500 // Parse optional 'num_rts'
1501 ptr_str = strstr(ptr_str, ","); // Find ','
1502 if (ptr_str != NULL) { // If ',' was found
1503 ptr_str++; // Skip ','
1504 while (*ptr_str == ' ') { // Skip whitespaces after ','
1507 if (sscanf(ptr_str, "%u", &val) == 1) {
1510 num_rts_provided = 1U;
1520 if ((ret == EXIT_SUCCESS) && (delay != 0U)) {
1521 (void)osDelay(delay);
1524 if (ret == EXIT_SUCCESS) {
1525 // Configure communication settings before transfer
1526 ret = USART_Com_Configure(&usart_com_config_xfer);
1528 if (ret == EXIT_SUCCESS) {
1531 ret = USART_Com_Send(ptr_usart_xfer_buf_tx, num, usart_xfer_timeout);
1532 usart_xfer_cnt = drvUSART->GetTxCount();
1535 if (num_rts_provided == 0U) { // Normal Receive
1536 ret = USART_Com_Receive(ptr_usart_xfer_buf_rx, num, usart_xfer_timeout);
1537 usart_xfer_cnt = drvUSART->GetRxCount();
1538 } else { // Special handling for activation of Server's RTS line => Client's CTS line
1539 USART_Com_SetModemControl(ARM_USART_RTS_SET);
1540 ret = USART_Com_Receive(ptr_usart_xfer_buf_rx, num_rts, (usart_xfer_timeout * num_rts) / num);
1541 usart_xfer_cnt = drvUSART->GetRxCount();
1542 USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1544 USART_Com_Receive(ptr_usart_xfer_buf_rx + num_rts, num - num_rts, (usart_xfer_timeout * (num - num_rts)) / num);
1545 usart_xfer_cnt += drvUSART->GetRxCount();
1548 case 2U: // Transfer
1549 ret = USART_Com_Transfer(ptr_usart_xfer_buf_tx, ptr_usart_xfer_buf_rx, num, usart_xfer_timeout);
1550 usart_xfer_cnt = drvUSART->GetRxCount();
1559 // Revert communication settings to default
1560 (void)USART_Com_Configure(&usart_com_config_default);
1566 \fn static int32_t USART_Cmd_GetCnt (const char *cmd)
1567 \brief Handle command "GET CNT".
1568 \detail Return number of items transferred (sent/received/transferred) in last transfer
1569 (requested by last XFER command).
1570 \param[in] cmd Pointer to null-terminated command string
1571 \return execution status
1572 - EXIT_SUCCESS: Operation successful
1573 - EXIT_FAILURE: Operation failed
1575 static int32_t USART_Cmd_GetCnt (const char *cmd) {
1582 (void)osDelay(10U); // Give client time to start the reception
1584 memset(usart_cmd_buf_tx, 0, 16);
1585 if (snprintf((char *)usart_cmd_buf_tx, 16, "%u", USART_Com_GetCnt()) < 16) {
1586 ret = USART_Com_Send(usart_cmd_buf_tx, BYTES_TO_ITEMS(16U, USART_SERVER_DATA_BITS), usart_cmd_timeout);
1593 \fn static int32_t USART_Cmd_SetBrk (const char *cmd)
1594 \brief Handle command "SET BRK delay,duration".
1595 \detail Control break signal.
1596 After specified delay time activate break signal
1597 and hold it for specified duration.
1598 \param[in] cmd Pointer to null-terminated command string
1599 \return execution status
1600 - EXIT_SUCCESS: Operation successful
1601 - EXIT_FAILURE: Operation failed
1603 static int32_t USART_Cmd_SetBrk (const char *cmd) {
1604 const char *ptr_str;
1605 uint32_t val, delay, duration;
1613 ptr_str = &cmd[7]; // Skip "SET BRK"
1614 while (*ptr_str == ' ') { // Skip whitespaces
1619 if (sscanf(ptr_str, "%u", &val) == 1) {
1620 if (val != osWaitForever) {
1629 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1631 ptr_str = strstr(ptr_str, ","); // Find ','
1632 if (ptr_str != NULL) { // If ',' was found
1633 ptr_str++; // Skip ','
1634 while (*ptr_str == ' ') { // Skip whitespaces after ','
1637 if (sscanf(ptr_str, "%u", &val) == 1) {
1638 if (val != osWaitForever) {
1649 if ((ret == EXIT_SUCCESS) && (delay != 0U)) {
1650 (void)osDelay(delay);
1653 if (ret == EXIT_SUCCESS) {
1654 ret = USART_Com_Configure(&usart_com_config_default);
1657 if (ret == EXIT_SUCCESS) {
1658 ret = USART_Com_Break(1U);
1661 if ((ret == EXIT_SUCCESS) && (duration != 0U)) {
1662 (void)osDelay(duration);
1665 USART_Com_Break(0U);
1671 \fn static int32_t USART_Cmd_GetBrk (const char *cmd)
1672 \brief Handle command "GET BRK".
1673 \detail Return break status. Status is updated upon break event and cleared
1674 after this command is executed.
1675 \param[in] cmd Pointer to null-terminated command string
1676 \return execution status
1677 - EXIT_SUCCESS: Operation successful
1678 - EXIT_FAILURE: Operation failed
1680 static int32_t USART_Cmd_GetBrk (const char *cmd) {
1687 usart_cmd_buf_tx[0] = '0' + break_status;
1690 (void)osDelay(10U); // Give client time to start the reception
1692 ret = USART_Com_Send(usart_cmd_buf_tx, 1U, usart_cmd_timeout);
1698 \fn static int32_t USART_Cmd_SetMdm (const char *cmd)
1699 \brief Handle command "SET MDM mdm_ctrl,delay,duration".
1700 \detail Control modem lines.
1701 After specified delay time activate requested line states
1702 and hold it for specified duration.
1703 \param[in] cmd Pointer to null-terminated command string
1704 \return execution status
1705 - EXIT_SUCCESS: Operation successful
1706 - EXIT_FAILURE: Operation failed
1708 static int32_t USART_Cmd_SetMdm (const char *cmd) {
1709 const char *ptr_str;
1710 uint32_t val, mdm_ctrl, delay, duration, control;
1720 ptr_str = &cmd[7]; // Skip "SET MDM"
1721 while (*ptr_str == ' ') { // Skip whitespaces
1726 if (sscanf(ptr_str, "%x", &val) == 1) {
1732 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1734 ptr_str = strstr(ptr_str, ","); // Find ','
1735 if (ptr_str != NULL) { // If ',' was found
1736 ptr_str++; // Skip ','
1737 while (*ptr_str == ' ') { // Skip whitespaces after ','
1740 if (sscanf(ptr_str, "%u", &val) == 1) {
1741 if (val != osWaitForever) {
1754 if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1756 ptr_str = strstr(ptr_str, ","); // Find ','
1757 if (ptr_str != NULL) { // If ',' was found
1758 ptr_str++; // Skip ','
1759 while (*ptr_str == ' ') { // Skip whitespaces after ','
1762 if (sscanf(ptr_str, "%u", &val) == 1) {
1763 if (val != osWaitForever) {
1774 if (ret == EXIT_SUCCESS) {
1775 // Deactivate all lines initially
1776 if (drv_cap.rts == 1U) {
1777 (void)USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1779 if (drv_cap.dtr == 1U) {
1780 (void)USART_Com_SetModemControl(ARM_USART_DTR_CLEAR);
1782 USART_Server_Pin_DCD_SetState(0U);
1783 USART_Server_Pin_RI_SetState (0U);
1786 (void)osDelay(delay);
1790 // Lower 4 bits are same as in USART ARM_USART_MODEM_CONTROL
1791 // bit 0. = RTS state
1792 // bit 1. = DTR state
1793 // bit 2. = DCD state
1794 // bit 3. = RI state
1795 if (ret == EXIT_SUCCESS) {
1796 if (drv_cap.rts == 1U) {
1797 if ((mdm_ctrl & (1U )) != 0U) {
1798 ret = USART_Com_SetModemControl(ARM_USART_RTS_SET);
1800 ret = USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1804 if (ret == EXIT_SUCCESS) {
1805 if (drv_cap.dtr == 1U) {
1806 if ((mdm_ctrl & (1U << 1)) != 0U) {
1807 ret = USART_Com_SetModemControl(ARM_USART_DTR_SET);
1809 ret = USART_Com_SetModemControl(ARM_USART_DTR_CLEAR);
1814 if (ret == EXIT_SUCCESS) {
1815 if ((mdm_ctrl >> 2) & 1) {
1816 // If pin to DCD should be set to active state
1817 USART_Server_Pin_DCD_SetState(1U);
1819 if ((mdm_ctrl >> 3) & 1) {
1820 // If pin to RI should be set to active state
1821 USART_Server_Pin_RI_SetState(1U);
1824 if (duration != 0U) {
1825 (void)osDelay(duration);
1829 if (drv_cap.rts == 1U) {
1830 (void)USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1832 if (drv_cap.dtr == 1U) {
1833 (void)USART_Com_SetModemControl(ARM_USART_DTR_CLEAR);
1835 USART_Server_Pin_DCD_SetState(0U);
1836 USART_Server_Pin_RI_SetState (0U);
1842 \fn static int32_t USART_Cmd_GetMdm (const char *cmd)
1843 \brief Handle command "GET MDM".
1844 \detail Return modem lines current status.
1845 \param[in] cmd Pointer to null-terminated command string
1846 \return execution status
1847 - EXIT_SUCCESS: Operation successful
1848 - EXIT_FAILURE: Operation failed
1850 static int32_t USART_Cmd_GetMdm (const char *cmd) {
1852 ARM_USART_MODEM_STATUS val;
1858 val = drvUSART->GetModemStatus();
1860 usart_cmd_buf_tx[0] = '0' + (val.cts) + (2U * val.dsr);
1862 (void)osDelay(10U); // Give client time to start the reception
1864 ret = USART_Com_Send(usart_cmd_buf_tx, 1U, usart_cmd_timeout);