nu_scuart.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**************************************************************************//**
  2. * @file scuart.c
  3. * @brief Smartcard UART mode (SCUART) driver source file
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  7. *****************************************************************************/
  8. #include "NuMicro.h"
  9. static uint32_t SCUART_GetClock(SC_T *sc);
  10. /** @addtogroup Standard_Driver Standard Driver
  11. @{
  12. */
  13. /** @addtogroup SCUART_Driver SCUART Driver
  14. @{
  15. */
  16. /** @addtogroup SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions
  17. @{
  18. */
  19. /**
  20. * @brief The function is used to disable smartcard interface UART mode.
  21. * @param sc The base address of smartcard module.
  22. * @return None
  23. */
  24. void SCUART_Close(SC_T *sc)
  25. {
  26. sc->INTEN = 0UL;
  27. sc->UARTCTL = 0UL;
  28. sc->CTL = 0UL;
  29. }
  30. /** @cond HIDDEN_SYMBOLS */
  31. /**
  32. * @brief This function returns module clock of specified SC interface
  33. * @param[in] sc The base address of smartcard module.
  34. * @return Module clock of specified SC interface
  35. */
  36. static uint32_t SCUART_GetClock(SC_T *sc)
  37. {
  38. uint32_t u32ClkSrc, u32Num, u32Clk;
  39. if (sc == SC0)
  40. {
  41. u32Num = 0UL;
  42. }
  43. else
  44. {
  45. u32Num = 1UL;
  46. }
  47. u32ClkSrc = CLK->CLKSEL4 >> (u32Num + CLK_CLKSEL4_SC0SEL_Msk);
  48. /* Get smartcard module clock */
  49. if (u32ClkSrc == 0UL)
  50. {
  51. u32Clk = __HXT;
  52. }
  53. else
  54. {
  55. u32Clk = CLK_GetPCLK3Freq();
  56. }
  57. u32Clk /= (((CLK->CLKDIV1 >> (4UL * u32Num)) & CLK_CLKDIV1_SC0DIV_Msk) + 1UL);
  58. return u32Clk;
  59. }
  60. /** @endcond HIDDEN_SYMBOLS */
  61. /**
  62. * @brief This function use to enable smartcard module UART mode and set baudrate.
  63. * @param[in] sc The base address of smartcard module.
  64. * @param[in] u32baudrate Target baudrate of smartcard module.
  65. * @return Actual baudrate of smartcard mode
  66. * @details This function configures character width to 8 bits, 1 stop bit, and no parity.
  67. * And can use \ref SCUART_SetLineConfig function to update these settings
  68. * The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled
  69. * by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1
  70. * register. Since the baudrate divider is 12-bit wide and must be larger than 4,
  71. * (clock source / baudrate) must be larger or equal to 5 and smaller or equal to
  72. * 4096. Otherwise this function cannot configure SCUART to work with target baudrate.
  73. */
  74. uint32_t SCUART_Open(SC_T *sc, uint32_t u32baudrate)
  75. {
  76. uint32_t u32Clk = SCUART_GetClock(sc), u32Div;
  77. /* Calculate divider for target baudrate */
  78. u32Div = (u32Clk + (u32baudrate >> 1) - 1UL) / u32baudrate - 1UL;
  79. /* Enable smartcard interface and stop bit = 1 */
  80. sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk;
  81. /* Enable UART mode, disable parity and 8 bit per character */
  82. sc->UARTCTL = SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk;
  83. sc->ETUCTL = u32Div;
  84. return (u32Clk / (u32Div + 1UL));
  85. }
  86. /**
  87. * @brief The function is used to read Rx data from RX FIFO.
  88. * @param[in] sc The base address of smartcard module.
  89. * @param[in] pu8RxBuf The buffer to store receive the data
  90. * @param[in] u32ReadBytes Target number of characters to receive
  91. * @return Actual character number reads to buffer
  92. * @note This function does not block and return immediately if there's no data available
  93. */
  94. uint32_t SCUART_Read(SC_T *sc, uint8_t pu8RxBuf[], uint32_t u32ReadBytes)
  95. {
  96. uint32_t u32Count;
  97. for (u32Count = 0UL; u32Count < u32ReadBytes; u32Count++)
  98. {
  99. if (SCUART_GET_RX_EMPTY(sc)) /* no data available */
  100. {
  101. break;
  102. }
  103. pu8RxBuf[u32Count] = (uint8_t)SCUART_READ(sc); /* get data from FIFO */
  104. }
  105. return u32Count;
  106. }
  107. /**
  108. * @brief This function use to configure smartcard UART mode line setting.
  109. * @param[in] sc The base address of smartcard module.
  110. * @param[in] u32Baudrate Target baudrate of smartcard module. If this value is 0, UART baudrate will not change.
  111. * @param[in] u32DataWidth The data length, could be
  112. * - \ref SCUART_CHAR_LEN_5
  113. * - \ref SCUART_CHAR_LEN_6
  114. * - \ref SCUART_CHAR_LEN_7
  115. * - \ref SCUART_CHAR_LEN_8
  116. * @param[in] u32Parity The parity setting, could be
  117. * - \ref SCUART_PARITY_NONE
  118. * - \ref SCUART_PARITY_ODD
  119. * - \ref SCUART_PARITY_EVEN
  120. * @param[in] u32StopBits The stop bit length, could be
  121. * - \ref SCUART_STOP_BIT_1
  122. * - \ref SCUART_STOP_BIT_2
  123. * @return Actual baudrate of smartcard
  124. * @details The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled
  125. * by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1
  126. * register. Since the baudrate divider is 12-bit wide and must be larger than 4,
  127. * (clock source / baudrate) must be larger or equal to 5 and smaller or equal to
  128. * 4096. Otherwise this function cannot configure SCUART to work with target baudrate.
  129. */
  130. uint32_t SCUART_SetLineConfig(SC_T *sc, uint32_t u32Baudrate, uint32_t u32DataWidth, uint32_t u32Parity, uint32_t u32StopBits)
  131. {
  132. uint32_t u32Clk = SCUART_GetClock(sc), u32Div;
  133. if (u32Baudrate == 0UL) /* keep original baudrate setting */
  134. {
  135. u32Div = sc->ETUCTL & SC_ETUCTL_ETURDIV_Msk;
  136. }
  137. else
  138. {
  139. /* Calculate divider for target baudrate */
  140. u32Div = (u32Clk + (u32Baudrate >> 1) - 1UL) / u32Baudrate - 1UL;
  141. sc->ETUCTL = u32Div;
  142. }
  143. /* Set stop bit */
  144. sc->CTL = u32StopBits | SC_CTL_SCEN_Msk;
  145. /* Set character width and parity */
  146. sc->UARTCTL = u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk;
  147. return (u32Clk / (u32Div + 1UL));
  148. }
  149. /**
  150. * @brief This function use to set receive timeout count.
  151. * @param[in] sc The base address of smartcard module.
  152. * @param[in] u32TOC Rx timeout counter, using baudrate as counter unit. Valid range are 0~0x1FF,
  153. * set this value to 0 will disable timeout counter
  154. * @return None
  155. * @details The time-out counter resets and starts counting whenever the RX buffer received a
  156. * new data word. Once the counter decrease to 1 and no new data is received or CPU
  157. * does not read any data from FIFO, a receiver time-out interrupt will be generated.
  158. */
  159. void SCUART_SetTimeoutCnt(SC_T *sc, uint32_t u32TOC)
  160. {
  161. sc->RXTOUT = u32TOC;
  162. }
  163. /**
  164. * @brief This function is to write data into transmit FIFO to send data out.
  165. * @param[in] sc The base address of smartcard module.
  166. * @param[in] pu8TxBuf The buffer containing data to send to transmit FIFO.
  167. * @param[in] u32WriteBytes Number of data to send.
  168. * @return None
  169. * @note This function blocks until all data write into FIFO
  170. */
  171. void SCUART_Write(SC_T *sc, uint8_t pu8TxBuf[], uint32_t u32WriteBytes)
  172. {
  173. uint32_t u32Count;
  174. for (u32Count = 0UL; u32Count != u32WriteBytes; u32Count++)
  175. {
  176. /* Wait 'til FIFO not full */
  177. while (SCUART_GET_TX_FULL(sc))
  178. {
  179. ;
  180. }
  181. /* Write 1 byte to FIFO */
  182. sc->DAT = pu8TxBuf[u32Count];
  183. }
  184. }
  185. /*@}*/ /* end of group SCUART_EXPORTED_FUNCTIONS */
  186. /*@}*/ /* end of group SCUART_Driver */
  187. /*@}*/ /* end of group Standard_Driver */