/ Drivers / CMSIS / DAP / Firmware / Source / UART.c
UART.c
  1  /*
  2   * Copyright (c) 2021 ARM Limited. All rights reserved.
  3   *
  4   * SPDX-License-Identifier: Apache-2.0
  5   *
  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
  9   *
 10   * www.apache.org/licenses/LICENSE-2.0
 11   *
 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.
 17   *
 18   * ----------------------------------------------------------------------
 19   *
 20   * $Date:        1. March 2021
 21   * $Revision:    V1.0.0
 22   *
 23   * Project:      CMSIS-DAP Source
 24   * Title:        UART.c CMSIS-DAP UART
 25   *
 26   *---------------------------------------------------------------------------*/
 27  
 28  #include "DAP_config.h"
 29  #include "DAP.h"
 30  
 31  #if (DAP_UART != 0)
 32  
 33  #ifdef DAP_FW_V1
 34  #error "UART Communication Port not supported in DAP V1!"
 35  #endif
 36  
 37  #include "Driver_USART.h"
 38  
 39  #include "cmsis_os2.h"
 40  #include <string.h>
 41  
 42  #define UART_RX_BLOCK_SIZE    32U   /* Uart Rx Block Size (must be 2^n) */
 43  
 44  // USART Driver
 45  #define _USART_Driver_(n)  Driver_USART##n
 46  #define  USART_Driver_(n) _USART_Driver_(n)
 47  extern ARM_DRIVER_USART    USART_Driver_(DAP_UART_DRIVER);
 48  #define pUSART           (&USART_Driver_(DAP_UART_DRIVER))
 49  
 50  // UART Configuration
 51  #if (DAP_UART_USB_COM_PORT != 0)
 52  static uint8_t  UartTransport = DAP_UART_TRANSPORT_USB_COM_PORT;
 53  #else
 54  static uint8_t  UartTransport = DAP_UART_TRANSPORT_NONE;
 55  #endif
 56  
 57  // UART Flags
 58  static uint8_t  UartConfigured = 0U;
 59  static uint8_t  UartReceiveEnabled = 0U;
 60  static uint8_t  UartTransmitEnabled = 0U;
 61  static uint8_t  UartTransmitActive = 0U;
 62  
 63  // UART TX Buffer
 64  static uint8_t  UartTxBuf[DAP_UART_TX_BUFFER_SIZE];
 65  static volatile uint32_t UartTxIndexI = 0U;
 66  static volatile uint32_t UartTxIndexO = 0U;
 67  
 68  // UART RX Buffer
 69  static uint8_t  UartRxBuf[DAP_UART_RX_BUFFER_SIZE];
 70  static volatile uint32_t UartRxIndexI = 0U;
 71  static volatile uint32_t UartRxIndexO = 0U;
 72  
 73  // Uart Errors
 74  static volatile uint8_t  UartErrorRxDataLost = 0U;
 75  static volatile uint8_t  UartErrorFraming = 0U;
 76  static volatile uint8_t  UartErrorParity = 0U;
 77  
 78  // UART Transmit
 79  static uint32_t UartTxNum = 0U;
 80  
 81  // Function prototypes
 82  static uint8_t  UART_Init (void);
 83  static void     UART_Uninit (void);
 84  static uint8_t  UART_Get_Status (void);
 85  static uint8_t  UART_Receive_Enable (void);
 86  static uint8_t  UART_Transmit_Enable (void);
 87  static void     UART_Receive_Disable (void);
 88  static void     UART_Transmit_Disable (void);
 89  static void     UART_Receive_Flush (void);
 90  static void     UART_Transmit_Flush (void);
 91  static void     UART_Receive (void);
 92  static void     UART_Transmit (void);
 93  
 94  
 95  // USART Driver Callback function
 96  //   event: event mask
 97  static void USART_Callback (uint32_t event) {
 98    if (event &  ARM_USART_EVENT_SEND_COMPLETE) {
 99      UartTxIndexO += UartTxNum;
100      UartTransmitActive = 0U;
101      UART_Transmit();
102    }
103    if (event &  ARM_USART_EVENT_RECEIVE_COMPLETE) {
104      UartRxIndexI += UART_RX_BLOCK_SIZE;
105      UART_Receive();
106    }
107    if (event &  ARM_USART_EVENT_RX_OVERFLOW) {
108      UartErrorRxDataLost = 1U;
109    }
110    if (event &  ARM_USART_EVENT_RX_FRAMING_ERROR) {
111      UartErrorFraming = 1U;
112    }
113    if (event &  ARM_USART_EVENT_RX_PARITY_ERROR) {
114      UartErrorParity = 1U;
115    }
116  }
117  
118  // Init UART
119  //   return: DAP_OK or DAP_ERROR
120  static uint8_t UART_Init (void) {
121    int32_t status;
122    uint8_t ret = DAP_ERROR;
123  
124    UartConfigured = 0U;
125    UartReceiveEnabled = 0U;
126    UartTransmitEnabled = 0U;
127    UartTransmitActive = 0U;
128    UartErrorRxDataLost = 0U;
129    UartErrorFraming = 0U;
130    UartErrorParity = 0U;
131    UartTxIndexI = 0U;
132    UartTxIndexO = 0U;
133    UartRxIndexI = 0U;
134    UartRxIndexO = 0U;
135    UartTxNum = 0U;
136  
137    status = pUSART->Initialize(USART_Callback);
138    if (status == ARM_DRIVER_OK) {
139      status = pUSART->PowerControl(ARM_POWER_FULL);
140    }
141    if (status == ARM_DRIVER_OK) {
142      ret = DAP_OK;
143    }
144  
145    return (ret);
146  }
147  
148  // Un-Init UART
149  static void UART_Uninit (void) {
150    UartConfigured = 0U;
151  
152    pUSART->PowerControl(ARM_POWER_OFF);
153    pUSART->Uninitialize();
154  }
155  
156  // Get UART Status
157  //   return: status
158  static uint8_t UART_Get_Status (void) {
159    uint8_t status = 0U;
160  
161    if (UartReceiveEnabled != 0U) {
162      status |= DAP_UART_STATUS_RX_ENABLED;
163    }
164    if (UartErrorRxDataLost != 0U) {
165      UartErrorRxDataLost = 0U;
166      status |= DAP_UART_STATUS_RX_DATA_LOST;
167    }
168    if (UartErrorFraming != 0U) {
169      UartErrorFraming = 0U;
170      status |= DAP_UART_STATUS_FRAMING_ERROR;
171    }
172    if (UartErrorParity != 0U) {
173      UartErrorParity = 0U;
174      status |= DAP_UART_STATUS_PARITY_ERROR;
175    }
176    if (UartTransmitEnabled != 0U) {
177      status |= DAP_UART_STATUS_TX_ENABLED;
178    }
179  
180    return (status);
181  }
182  
183  // Enable UART Receive
184  //   return: DAP_OK or DAP_ERROR
185  static uint8_t UART_Receive_Enable (void) {
186    int32_t status;
187    uint8_t ret = DAP_ERROR;
188  
189    if (UartReceiveEnabled == 0U) {
190      // Flush Buffers
191      UartRxIndexI = 0U;
192      UartRxIndexO = 0U;
193  
194      UART_Receive();
195      status = pUSART->Control(ARM_USART_CONTROL_RX, 1U);
196      if (status == ARM_DRIVER_OK) {
197        UartReceiveEnabled = 1U;
198        ret = DAP_OK;
199      }
200    } else {
201      ret = DAP_OK;
202    }
203  
204    return (ret);
205  }
206  
207  // Enable UART Transmit
208  //   return: DAP_OK or DAP_ERROR
209  static uint8_t UART_Transmit_Enable (void) {
210    int32_t status;
211    uint8_t ret = DAP_ERROR;
212  
213    if (UartTransmitEnabled == 0U) {
214      // Flush Buffers
215      UartTransmitActive = 0U;
216      UartTxIndexI = 0U;
217      UartTxIndexO = 0U;
218      UartTxNum = 0U;
219  
220      status = pUSART->Control(ARM_USART_CONTROL_TX, 1U);
221      if (status == ARM_DRIVER_OK) {
222        UartTransmitEnabled = 1U;
223        ret = DAP_OK;
224      }
225    } else {
226      ret = DAP_OK;
227    }
228  
229    return (ret);
230  }
231  
232  // Disable UART Receive
233  static void UART_Receive_Disable (void) {
234    if (UartReceiveEnabled != 0U) {
235      pUSART->Control(ARM_USART_CONTROL_RX, 0U);
236      pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
237      UartReceiveEnabled = 0U;
238    }
239  }
240  
241  // Disable UART Transmit
242  static void UART_Transmit_Disable (void) {
243    if (UartTransmitEnabled != 0U) {
244      pUSART->Control(ARM_USART_ABORT_SEND, 0U);
245      pUSART->Control(ARM_USART_CONTROL_TX, 0U);
246      UartTransmitActive = 0U;
247      UartTransmitEnabled = 0U;
248    }
249  }
250  
251  // Flush UART Receive buffer
252  static void UART_Receive_Flush (void) {
253    pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
254    UartRxIndexI = 0U;
255    UartRxIndexO = 0U;
256    if (UartReceiveEnabled != 0U) {
257      UART_Receive();
258    }
259  }
260  
261  // Flush UART Transmit buffer
262  static void UART_Transmit_Flush (void) {
263    pUSART->Control(ARM_USART_ABORT_SEND, 0U);
264    UartTransmitActive = 0U;
265    UartTxIndexI = 0U;
266    UartTxIndexO = 0U;
267    UartTxNum = 0U;
268  }
269  
270  // Receive data from target via UART
271  static void UART_Receive (void) {
272    uint32_t index;
273  
274    index = UartRxIndexI & (DAP_UART_RX_BUFFER_SIZE - 1U);
275    pUSART->Receive(&UartRxBuf[index], UART_RX_BLOCK_SIZE);
276  }
277  
278  // Transmit available data to target via UART
279  static void UART_Transmit (void) {
280    uint32_t count;
281    uint32_t index;
282  
283    count = UartTxIndexI - UartTxIndexO;
284    index = UartTxIndexO & (DAP_UART_TX_BUFFER_SIZE - 1U);
285  
286    if (count != 0U) {
287      if ((index + count) <= DAP_UART_TX_BUFFER_SIZE) {
288        UartTxNum = count;
289      } else {
290        UartTxNum = DAP_UART_TX_BUFFER_SIZE - index;
291      }
292      UartTransmitActive = 1U;
293      pUSART->Send(&UartTxBuf[index], UartTxNum);
294    }
295  }
296  
297  // Process UART Transport command and prepare response
298  //   request:  pointer to request data
299  //   response: pointer to response data
300  //   return:   number of bytes in response (lower 16 bits)
301  //             number of bytes in request (upper 16 bits)
302  uint32_t UART_Transport (const uint8_t *request, uint8_t *response) {
303    uint8_t  transport;
304    uint8_t  ret = DAP_ERROR;
305  
306    transport = *request;
307    switch (transport) {
308      case DAP_UART_TRANSPORT_NONE:
309        switch (UartTransport) {
310          case DAP_UART_TRANSPORT_NONE:
311            ret = DAP_OK;
312            break;
313          case DAP_UART_TRANSPORT_USB_COM_PORT:
314  #if (DAP_UART_USB_COM_PORT != 0)
315            USB_COM_PORT_Activate(0U);
316            UartTransport = DAP_UART_TRANSPORT_NONE;
317            ret = DAP_OK;
318  #endif
319            break;
320          case DAP_UART_TRANSPORT_DAP_COMMAND:
321            UART_Receive_Disable();
322            UART_Transmit_Disable();
323            UART_Uninit();
324            UartTransport = DAP_UART_TRANSPORT_NONE;
325            ret= DAP_OK;
326            break;
327        }
328        break;
329      case DAP_UART_TRANSPORT_USB_COM_PORT:
330        switch (UartTransport) {
331          case DAP_UART_TRANSPORT_NONE:
332  #if (DAP_UART_USB_COM_PORT != 0)
333            if (USB_COM_PORT_Activate(1U) == 0U) {
334              UartTransport = DAP_UART_TRANSPORT_USB_COM_PORT;
335              ret = DAP_OK;
336            }
337  #endif
338            break;
339          case DAP_UART_TRANSPORT_USB_COM_PORT:
340            ret = DAP_OK;
341            break;
342          case DAP_UART_TRANSPORT_DAP_COMMAND:
343            UART_Receive_Disable();
344            UART_Transmit_Disable();
345            UART_Uninit();
346            UartTransport = DAP_UART_TRANSPORT_NONE;
347  #if (DAP_UART_USB_COM_PORT != 0)
348            if (USB_COM_PORT_Activate(1U) == 0U) {
349              UartTransport = DAP_UART_TRANSPORT_USB_COM_PORT;
350              ret = DAP_OK;
351            }
352  #endif
353            break;
354        }
355        break;
356      case DAP_UART_TRANSPORT_DAP_COMMAND:
357        switch (UartTransport) {
358          case DAP_UART_TRANSPORT_NONE:
359            ret = UART_Init();
360            if (ret == DAP_OK) {
361              UartTransport = DAP_UART_TRANSPORT_DAP_COMMAND;
362            }
363            break;
364          case DAP_UART_TRANSPORT_USB_COM_PORT:
365  #if (DAP_UART_USB_COM_PORT != 0)
366            USB_COM_PORT_Activate(0U);
367            UartTransport = DAP_UART_TRANSPORT_NONE;
368  #endif
369            ret = UART_Init();
370            if (ret == DAP_OK) {
371              UartTransport = DAP_UART_TRANSPORT_DAP_COMMAND;
372            }
373            break;
374          case DAP_UART_TRANSPORT_DAP_COMMAND:
375            ret = DAP_OK;
376            break;
377        }
378        break;
379      default:
380        break;
381    }
382  
383    *response = ret;
384  
385    return ((1U << 16) | 1U);
386  }
387  
388  // Process UART Configure command and prepare response
389  //   request:  pointer to request data
390  //   response: pointer to response data
391  //   return:   number of bytes in response (lower 16 bits)
392  //             number of bytes in request (upper 16 bits)
393  uint32_t UART_Configure (const uint8_t *request, uint8_t *response) {
394    uint8_t  control, status;
395    uint32_t baudrate;
396    int32_t  result;
397  
398    if (UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) {
399      status = DAP_UART_CFG_ERROR_DATA_BITS |
400               DAP_UART_CFG_ERROR_PARITY    |
401               DAP_UART_CFG_ERROR_STOP_BITS;
402      baudrate = 0U;  // baudrate error
403    } else {
404  
405      status   = 0U;
406      control  = *request;
407      baudrate = (uint32_t)(*(request+1) <<  0) |
408                 (uint32_t)(*(request+2) <<  8) |
409                 (uint32_t)(*(request+3) << 16) |
410                 (uint32_t)(*(request+4) << 24);
411  
412      result = pUSART->Control(control |
413                               ARM_USART_MODE_ASYNCHRONOUS |
414                               ARM_USART_FLOW_CONTROL_NONE,
415                               baudrate);
416      if (result == ARM_DRIVER_OK) {
417        UartConfigured = 1U;
418      } else {
419        UartConfigured = 0U;
420        switch (result) {
421          case ARM_USART_ERROR_BAUDRATE:
422            status = 0U;
423            baudrate = 0U;
424            break;
425          case ARM_USART_ERROR_DATA_BITS:
426            status = DAP_UART_CFG_ERROR_DATA_BITS;
427            break;
428          case ARM_USART_ERROR_PARITY:
429            status = DAP_UART_CFG_ERROR_PARITY;
430            break;
431          case ARM_USART_ERROR_STOP_BITS:
432            status = DAP_UART_CFG_ERROR_STOP_BITS;
433            break;
434          default:
435            status = DAP_UART_CFG_ERROR_DATA_BITS |
436                     DAP_UART_CFG_ERROR_PARITY    |
437                     DAP_UART_CFG_ERROR_STOP_BITS;
438            baudrate = 0U;
439            break;
440        }
441      }
442    }
443  
444    *response++ = status;
445    *response++ = (uint8_t)(baudrate >>  0);
446    *response++ = (uint8_t)(baudrate >>  8);
447    *response++ = (uint8_t)(baudrate >> 16);
448    *response   = (uint8_t)(baudrate >> 24);
449  
450    return ((5U << 16) | 5U);
451  }
452  
453  // Process UART Control command and prepare response
454  //   request:  pointer to request data
455  //   response: pointer to response data
456  //   return:   number of bytes in response (lower 16 bits)
457  //             number of bytes in request (upper 16 bits)
458  uint32_t UART_Control (const uint8_t *request, uint8_t *response) {
459    uint8_t control;
460    uint8_t result;
461    uint8_t ret = DAP_OK;
462  
463    if (UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) {
464      ret = DAP_ERROR;
465    } else {
466   
467      control = *request;
468  
469      if ((control & DAP_UART_CONTROL_RX_DISABLE) != 0U) {
470        // Receive disable
471        UART_Receive_Disable();
472      } else if ((control & DAP_UART_CONTROL_RX_ENABLE) != 0U) {
473        // Receive enable
474        if (UartConfigured != 0U) {
475          result = UART_Receive_Enable();
476          if (result != DAP_OK) {
477            ret = DAP_ERROR;
478          }
479        } else {
480          ret = DAP_ERROR;
481        }
482      }
483      if ((control & DAP_UART_CONTROL_RX_BUF_FLUSH) != 0U) {
484        UART_Receive_Flush();
485      }
486  
487      if ((control & DAP_UART_CONTROL_TX_DISABLE) != 0U) {
488        // Transmit disable
489        UART_Transmit_Disable();
490      } else if ((control & DAP_UART_CONTROL_TX_ENABLE) != 0U) {
491        // Transmit enable
492        if (UartConfigured != 0U) {
493          result = UART_Transmit_Enable();
494          if (result != DAP_OK) {
495            ret = DAP_ERROR;
496          }
497        } else {
498          ret = DAP_ERROR;
499        }
500      } 
501      if ((control & DAP_UART_CONTROL_TX_BUF_FLUSH) != 0U) {
502        UART_Transmit_Flush();
503      }
504    }
505  
506    *response = ret;
507  
508    return ((1U << 16) | 1U);
509  }
510  
511  // Process UART Status command and prepare response
512  //   response: pointer to response data
513  //   return:   number of bytes in response (lower 16 bits)
514  //             number of bytes in request (upper 16 bits)
515  uint32_t UART_Status (uint8_t *response) {
516    uint32_t rx_cnt, tx_cnt;
517    uint32_t cnt;
518    uint8_t  status;
519  
520    if ((UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) ||
521        (UartConfigured == 0U)) {
522      rx_cnt = 0U;
523      tx_cnt = 0U;
524      status = 0U;
525    } else {
526  
527      rx_cnt  = UartRxIndexI - UartRxIndexO;
528      rx_cnt += pUSART->GetRxCount();
529      if (rx_cnt > (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2))) {
530        // Overflow
531        UartErrorRxDataLost = 1U;
532        rx_cnt = (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2));
533        UartRxIndexO = UartRxIndexI - rx_cnt;
534      }
535  
536      tx_cnt = UartTxIndexI - UartTxIndexO;
537      cnt = pUSART->GetTxCount();
538      if (UartTransmitActive != 0U) {
539        tx_cnt -= cnt;
540      }
541  
542      status = UART_Get_Status();
543    }
544  
545    *response++ = status;
546    *response++ = (uint8_t)(rx_cnt >>  0);
547    *response++ = (uint8_t)(rx_cnt >>  8);
548    *response++ = (uint8_t)(rx_cnt >> 16);
549    *response++ = (uint8_t)(rx_cnt >> 24);
550    *response++ = (uint8_t)(tx_cnt >>  0);
551    *response++ = (uint8_t)(tx_cnt >>  8);
552    *response++ = (uint8_t)(tx_cnt >> 16);
553    *response   = (uint8_t)(tx_cnt >> 24);
554  
555    return ((0U << 16) | 9U);
556  }
557  
558  // Process UART Transfer command and prepare response
559  //   request:  pointer to request data
560  //   response: pointer to response data
561  //   return:   number of bytes in response (lower 16 bits)
562  //             number of bytes in request (upper 16 bits)
563  uint32_t UART_Transfer (const uint8_t *request, uint8_t *response) {
564    uint32_t rx_cnt, tx_cnt;
565    uint32_t rx_num, tx_num;
566    uint8_t *rx_data;
567    const
568    uint8_t *tx_data;
569    uint32_t num;
570    uint32_t index;
571    uint8_t  status;
572  
573    if (UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) {
574      status = 0U;
575      rx_cnt = 0U;
576      tx_cnt = 0U;
577    } else {
578  
579      // RX Data
580      rx_cnt = ((uint32_t)(*(request+0) << 0)  |
581                (uint32_t)(*(request+1) << 8));
582  
583      if (rx_cnt > (DAP_PACKET_SIZE - 6U)) {
584        rx_cnt = (DAP_PACKET_SIZE - 6U);
585      }
586      rx_num  = UartRxIndexI - UartRxIndexO;
587      rx_num += pUSART->GetRxCount();
588      if (rx_num > (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2))) {
589        // Overflow
590        UartErrorRxDataLost = 1U;
591        rx_num = (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2));
592        UartRxIndexO = UartRxIndexI - rx_num;
593      }
594      if (rx_cnt > rx_num) {
595        rx_cnt = rx_num;
596      }
597  
598      rx_data = (response+5);
599      index = UartRxIndexO & (DAP_UART_RX_BUFFER_SIZE - 1U);
600      if ((index + rx_cnt) <= DAP_UART_RX_BUFFER_SIZE) {
601        memcpy( rx_data,      &UartRxBuf[index], rx_cnt);
602      } else {
603        num = DAP_UART_RX_BUFFER_SIZE - index;
604        memcpy( rx_data,      &UartRxBuf[index], num);
605        memcpy(&rx_data[num], &UartRxBuf[0],     rx_cnt - num);
606      }
607      UartRxIndexO += rx_cnt;
608  
609      // TX Data
610      tx_cnt  = ((uint32_t)(*(request+2) << 0) |
611                 (uint32_t)(*(request+3) << 8));
612      tx_data =              (request+4);
613  
614      if (tx_cnt > (DAP_PACKET_SIZE - 5U)) {
615        tx_cnt = (DAP_PACKET_SIZE - 5U);
616      }
617      tx_num = UartTxIndexI - UartTxIndexO;
618      num = pUSART->GetTxCount();
619      if (UartTransmitActive != 0U) {
620        tx_num -= num;
621      }
622      if (tx_cnt > (DAP_UART_TX_BUFFER_SIZE - tx_num)) {
623        tx_cnt = (DAP_UART_TX_BUFFER_SIZE - tx_num);
624      }
625  
626      index = UartTxIndexI & (DAP_UART_TX_BUFFER_SIZE - 1U);
627      if ((index + tx_cnt) <= DAP_UART_TX_BUFFER_SIZE) {
628        memcpy(&UartTxBuf[index],  tx_data,      tx_cnt);
629      } else {
630        num = DAP_UART_TX_BUFFER_SIZE - index;
631        memcpy(&UartTxBuf[index],  tx_data,      num);
632        memcpy(&UartTxBuf[0],     &tx_data[num], tx_cnt - num);
633      }
634      UartTxIndexI += tx_cnt;
635  
636      if (UartTransmitActive == 0U) {
637        UART_Transmit();
638      }
639  
640      status = UART_Get_Status();
641    }
642  
643    *response++ = status;
644    *response++ = (uint8_t)(tx_cnt >> 0);
645    *response++ = (uint8_t)(tx_cnt >> 8);
646    *response++ = (uint8_t)(rx_cnt >> 0);
647    *response   = (uint8_t)(rx_cnt >> 8);
648  
649    return (((4U + tx_cnt) << 16) | (5U + rx_cnt));
650  }
651  
652  #endif /* DAP_UART */