nu_scuart.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**************************************************************************//**
  2. * @file scuart.c
  3. * @brief N9H30 series Smartcard UART mode (SCUART) driver source file
  4. *
  5. * @note
  6. * SPDX-License-Identifier: Apache-2.0
  7. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include "N9H30.h"
  10. #include "nu_scuart.h"
  11. /** @addtogroup N9H30_Device_Driver N9H30 Device Driver
  12. @{
  13. */
  14. /** @addtogroup N9H30_SCUART_Driver SCUART Driver
  15. @{
  16. */
  17. /** @addtogroup N9H30_SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions
  18. @{
  19. */
  20. /**
  21. * @brief Disable smartcard uart interface.
  22. * @param sc Smartcard module number
  23. * @return None
  24. * @details The function is used to disable smartcard interface UART mode.
  25. */
  26. void SCUART_Close(UINT sc)
  27. {
  28. if (sc == 0)
  29. {
  30. outpw(REG_SC0_INTEN, 0);
  31. outpw(REG_SC0_UARTCTL, 0);
  32. outpw(REG_SC0_CTL, 0);
  33. }
  34. else
  35. {
  36. outpw(REG_SC1_INTEN, 0);
  37. outpw(REG_SC1_UARTCTL, 0);
  38. outpw(REG_SC1_CTL, 0);
  39. }
  40. }
  41. /// @cond HIDDEN_SYMBOLS
  42. /**
  43. * @brief This function returns module clock of specified SC interface
  44. * @param[in] sc Smartcard module number
  45. * @return Module clock of specified SC interface
  46. */
  47. static uint32_t SCUART_GetClock(UINT sc)
  48. {
  49. uint32_t u32Div;
  50. if (sc == 0)
  51. u32Div = ((inpw(REG_CLK_DIVCTL6) >> 24) & 0xF) + 1;
  52. else
  53. u32Div = ((inpw(REG_CLK_DIVCTL6) >> 28) & 0xF) + 1;
  54. return 12000000 / u32Div;
  55. }
  56. /// @endcond HIDDEN_SYMBOLS
  57. /**
  58. * @brief Enable smartcard uart interface.
  59. * @param[in] sc Smartcard module number
  60. * @param[in] u32baudrate Target baudrate of smartcard module.
  61. * @return Actual baudrate of smartcard mode.
  62. * @details This function use to enable smartcard module UART mode and set baudrate.
  63. * @note This function configures character width to 8 bits, 1 stop bit, and no parity.
  64. * And can use \ref SCUART_SetLineConfig function to update these settings.
  65. */
  66. UINT SCUART_Open(UINT sc, UINT u32baudrate)
  67. {
  68. uint32_t u32Clk = SCUART_GetClock(sc), u32Div;
  69. // Calculate divider for target baudrate
  70. u32Div = (u32Clk + (u32baudrate >> 1) - 1) / u32baudrate - 1;
  71. if (sc == 0)
  72. {
  73. outpw(REG_SC0_CTL, SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk); // Enable smartcard interface and stop bit = 1
  74. outpw(REG_SC0_UARTCTL, SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk); // Enable UART mode, disable parity and 8 bit per character
  75. outpw(REG_SC0_ETUCTL, u32Div);
  76. }
  77. else
  78. {
  79. outpw(REG_SC1_CTL, SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk); // Enable smartcard interface and stop bit = 1
  80. outpw(REG_SC1_UARTCTL, SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk); // Enable UART mode, disable parity and 8 bit per character
  81. outpw(REG_SC1_ETUCTL, u32Div);
  82. }
  83. return (u32Clk / (u32Div + 1));
  84. }
  85. /**
  86. * @brief Read data from smartcard UART interface.
  87. * @param[in] sc Smartcard module number
  88. * @param[in] pu8RxBuf The buffer to store receive the data.
  89. * @param[in] u32ReadBytes Target number of characters to receive.
  90. * @return Actual character number reads to buffer.
  91. * @details The function is used to read Rx data from RX FIFO.
  92. * @note This function does not block and return immediately if there's no data available.
  93. */
  94. UINT SCUART_Read(UINT sc, char *pu8RxBuf, UINT u32ReadBytes)
  95. {
  96. uint32_t u32Count;
  97. if (sc == 0)
  98. {
  99. for (u32Count = 0; u32Count < u32ReadBytes; u32Count++)
  100. {
  101. if (inpw(REG_SC0_STATUS) & SC_STATUS_RXEMPTY_Msk) // no data available
  102. {
  103. break;
  104. }
  105. pu8RxBuf[u32Count] = inpw(REG_SC0_DAT); // get data from FIFO
  106. }
  107. }
  108. else
  109. {
  110. for (u32Count = 0; u32Count < u32ReadBytes; u32Count++)
  111. {
  112. if (inpw(REG_SC1_STATUS) & SC_STATUS_RXEMPTY_Msk) // no data available
  113. {
  114. break;
  115. }
  116. pu8RxBuf[u32Count] = inpw(REG_SC1_DAT); // get data from FIFO
  117. }
  118. }
  119. return u32Count;
  120. }
  121. /**
  122. * @brief This function use to config smartcard UART mode line setting.
  123. * @param[in] sc Smartcard module number
  124. * @param[in] u32Baudrate Target baudrate of smartcard module. If this value is 0, UART baudrate will not change.
  125. * @param[in] u32DataWidth The data length, could be:
  126. * - \ref SCUART_CHAR_LEN_5
  127. * - \ref SCUART_CHAR_LEN_6
  128. * - \ref SCUART_CHAR_LEN_7
  129. * - \ref SCUART_CHAR_LEN_8
  130. * @param[in] u32Parity The parity setting, could be:
  131. * - \ref SCUART_PARITY_NONE
  132. * - \ref SCUART_PARITY_ODD
  133. * - \ref SCUART_PARITY_EVEN
  134. * @param[in] u32StopBits The stop bit length, could be:
  135. * - \ref SCUART_STOP_BIT_1
  136. * - \ref SCUART_STOP_BIT_2
  137. * @return Actual baudrate of smartcard.
  138. * @details Smartcard UART mode is operated in LIN data frame.
  139. */
  140. UINT SCUART_SetLineConfig(UINT sc, UINT u32Baudrate, UINT u32DataWidth, UINT u32Parity, UINT u32StopBits)
  141. {
  142. uint32_t u32Clk = SCUART_GetClock(sc), u32Div;
  143. if (u32Baudrate == 0) // keep original baudrate setting
  144. {
  145. u32Div = (sc == 0) ? inpw(REG_SC0_ETUCTL) & 0xFFF : inpw(REG_SC1_ETUCTL) & 0xFFF;
  146. }
  147. else
  148. {
  149. // Calculate divider for target baudrate
  150. u32Div = (u32Clk + (u32Baudrate >> 1) - 1) / u32Baudrate - 1;
  151. if (sc == 0)
  152. outpw(REG_SC0_ETUCTL, u32Div);
  153. else
  154. outpw(REG_SC1_ETUCTL, u32Div);
  155. }
  156. if (sc == 0)
  157. {
  158. outpw(REG_SC0_CTL, u32StopBits | SC_CTL_SCEN_Msk); // Set stop bit
  159. outpw(REG_SC0_UARTCTL, u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk); // Set character width and parity
  160. }
  161. else
  162. {
  163. outpw(REG_SC1_CTL, u32StopBits | SC_CTL_SCEN_Msk); // Set stop bit
  164. outpw(REG_SC1_UARTCTL, u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk); // Set character width and parity
  165. }
  166. return (u32Clk / (u32Div + 1));
  167. }
  168. /**
  169. * @brief This function use to set receive timeout count.
  170. * @param[in] sc Smartcard module number
  171. * @param[in] u32TOC Rx timeout counter, using baudrate as counter unit. Valid range are 0~0x1FF,
  172. * set this value to 0 will disable timeout counter.
  173. * @return None
  174. * @details The time-out counter resets and starts counting whenever the RX buffer received a
  175. * new data word. Once the counter decrease to 1 and no new data is received or CPU
  176. * does not read any data from FIFO, a receiver time-out interrupt will be generated.
  177. */
  178. void SCUART_SetTimeoutCnt(UINT sc, UINT u32TOC)
  179. {
  180. if (sc == 0)
  181. outpw(REG_SC0_RXTOUT, u32TOC);
  182. else
  183. outpw(REG_SC1_RXTOUT, u32TOC);
  184. }
  185. /**
  186. * @brief Write data to smartcard UART interface.
  187. * @param[in] sc Smartcard module number
  188. * @param[in] pu8TxBuf The buffer containing data to send to transmit FIFO.
  189. * @param[in] u32WriteBytes Number of data to send.
  190. * @return None
  191. * @details This function is to write data into transmit FIFO to send data out.
  192. * @note This function blocks until all data write into FIFO.
  193. */
  194. void SCUART_Write(UINT sc, char *pu8TxBuf, UINT u32WriteBytes)
  195. {
  196. uint32_t u32Count;
  197. if (sc == 0)
  198. {
  199. for (u32Count = 0; u32Count != u32WriteBytes; u32Count++)
  200. {
  201. while (inpw(REG_SC0_STATUS) & SC_STATUS_TXFULL_Msk); // Wait 'til FIFO not full
  202. outpw(REG_SC0_DAT, pu8TxBuf[u32Count]); // Write 1 byte to FIFO
  203. }
  204. }
  205. else
  206. {
  207. for (u32Count = 0; u32Count != u32WriteBytes; u32Count++)
  208. {
  209. while (inpw(REG_SC0_STATUS) & SC_STATUS_TXFULL_Msk); // Wait 'til FIFO not full
  210. outpw(REG_SC1_DAT, pu8TxBuf[u32Count]); // Write 1 byte to FIFO
  211. }
  212. }
  213. }
  214. /*@}*/ /* end of group N9H30_SCUART_EXPORTED_FUNCTIONS */
  215. /*@}*/ /* end of group N9H30_SCUART_Driver */
  216. /*@}*/ /* end of group N9H30_Device_Driver */
  217. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/