driver_uart.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * @File name : driver_uart.c
  3. * @Author : Bluetrum IOT Team
  4. * @Date : 2023-02-14
  5. * @Description : This file provides functions to manage the most functionalities
  6. * of the UART peripheral.
  7. *
  8. * Copyright (c) by Bluetrum, All Rights Reserved.
  9. */
  10. #include "driver_uart.h"
  11. /**
  12. * @brief Initializes the uart peripheral according to the specified
  13. * parameters in the uart_init_struct.
  14. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  15. * @param uart_init_struct: pointer to a uart_init_typedef structure that
  16. * contains the configuration information for the specified UART peripheral.
  17. * @retval None
  18. */
  19. void uart_init(uart_typedef *uartx, uart_init_typedef* uart_init_struct)
  20. {
  21. uint32_t tmp_reg, sys_clk_val, baud_reg;
  22. //---------- UART Controller Register ----------//
  23. tmp_reg = uartx->con;
  24. tmp_reg &= (uint32_t)(~UARTxCON_RXEN);
  25. tmp_reg &= (uint32_t)(~UARTxCON_ONELINE);
  26. tmp_reg &= (uint32_t)(~UARTxCON_BIT9EN);
  27. tmp_reg &= (uint32_t)(~UARTxCON_SB2EN);
  28. tmp_reg |= (uint32_t)(uart_init_struct->mode |
  29. uart_init_struct->one_line_enable |
  30. uart_init_struct->stop_bits |
  31. uart_init_struct->word_len);
  32. if (uartx == UART) {
  33. tmp_reg &= (uint32_t)(~UARTxCON_CLKSRC);
  34. tmp_reg |= (uint32_t)(uart_init_struct->clock_source);
  35. } else if (uartx == UDET) {
  36. tmp_reg &= (uint32_t)(~UARTxCON_FIXBAUD);
  37. tmp_reg |= (uint32_t)(uart_init_struct->baud_fix);
  38. }
  39. uartx->con = tmp_reg;
  40. if (uartx == UART) {
  41. //---------- UART Baud Configuration ----------//
  42. sys_clk_val = sys_clk_nhz_get();
  43. if (uart_init_struct->clock_source == UART_SYSTEM_CLOCK) {
  44. baud_reg = (uint16_t)((sys_clk_val / uart_init_struct->baud) - 1);
  45. } else {
  46. // uart clk is double frequency of the clock source when select uart_inc
  47. sys_clk_val = 2 * clk_uart_inc_get(CLK_VALUE_MODE_FREQ);
  48. baud_reg = (uint16_t)((sys_clk_val / uart_init_struct->baud) - 1);
  49. }
  50. tmp_reg = (uint32_t)((baud_reg << 16) | baud_reg);
  51. uartx->baud = tmp_reg;
  52. } else if (uartx == UDET && uart_init_struct->baud_fix == UART_BAUD_FIX) {
  53. sys_clk_val = clk_udet_clk_get(CLK_VALUE_MODE_FREQ);
  54. baud_reg = (uint16_t)((sys_clk_val / uart_init_struct->baud) - 1);
  55. uartx->baud = baud_reg;
  56. }
  57. }
  58. /**
  59. * @brief De-initialize the specified uart peripheral.
  60. * @param uartx: which uart need to config. it should the one of [UART or UDET].
  61. * @retval None
  62. */
  63. void uart_deinit(uart_typedef *uartx)
  64. {
  65. uartx->con = 0;
  66. if (uartx == UART) {
  67. clk_gate0_cmd(CLK_GATE0_UART, CLK_DIS);
  68. } else if (uartx == UDET) {
  69. clk_gate0_cmd(CLK_GATE0_UDET, CLK_DIS);
  70. }
  71. }
  72. /**
  73. * @brief Enable or disable the specified UART peripheral.
  74. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  75. * @param state: the state of the UARTx peripheral.
  76. * this parameter can be: ENABLE or DISABLE.
  77. * @retval None
  78. */
  79. void uart_cmd(uart_typedef *uartx, FUNCTIONAL_STATE state)
  80. {
  81. if (state != DISABLE) {
  82. uartx->con |= UARTxCON_UTEN;
  83. } else {
  84. uartx->con &= (uint32_t)(~UARTxCON_UTEN);
  85. }
  86. }
  87. /**
  88. * @brief Transmits data through the UARTx peripheral.
  89. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  90. * @param data: the data to transmit.
  91. * @retval None
  92. */
  93. AT(.com_periph.uart.send)
  94. void uart_send_data(uart_typedef *uartx, uint16_t data)
  95. {
  96. uartx->data = (data & (uint16_t)0xff);
  97. }
  98. /**
  99. * @brief Return the received data lastly by the UARTx peripheral.
  100. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  101. * @retval The received data.
  102. */
  103. AT(.com_periph.uart.recv)
  104. uint16_t uart_receive_data(uart_typedef *uartx)
  105. {
  106. if (uartx->con & UARTxCON_BIT9EN) {
  107. return (uartx->data & (uint16_t)0x1ff);
  108. } else {
  109. return (uartx->data & (uint16_t)0xff);
  110. }
  111. }
  112. /**
  113. * @brief Enable or disable the specified UARTx interrupt.
  114. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  115. * @param isr: Function to be executed for service interruption.
  116. * @param pr: Priority of service interruption.
  117. * @param interrupt_type: specifies the UART interrupt sources to be enable or disable.
  118. * this parameter can be one of the following values:
  119. * @arg UART_IT_TX: Transmit single data finish interrupt enable bit.
  120. * @arg UART_IT_RX: Receive single data finish interrupt enable bit.
  121. * @arg UART_IT_ERR: Raise error interrupt enable bit.
  122. * @arg UART_IT_KEY: Match key interrupt enable bit.
  123. * @arg UART_IT_RSTKEY: Reset match key interrupt enable bit.
  124. * @param state: the state of the UARTx peripheral.
  125. * this parameter can be: ENABLE or DISABLE.
  126. * @retval None
  127. */
  128. void uart_pic_config(uart_typedef *uartx, isr_t isr, int pr, UART_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
  129. {
  130. uint32_t interrupt_con_bit = 0;
  131. uint32_t all_interrupt_type_mask = UART_IT_TX | UART_IT_RX | UART_IT_ERR | UART_IT_KEY | UART_IT_RSTKEY;
  132. if (interrupt_type == 0) {
  133. return;
  134. }
  135. if (interrupt_type & UART_IT_TX) {
  136. interrupt_con_bit |= UARTxCON_TXIE;
  137. }
  138. if (interrupt_type & UART_IT_RX) {
  139. interrupt_con_bit |= UARTxCON_RXIE;
  140. }
  141. if (interrupt_type & UART_IT_ERR) {
  142. }
  143. if (interrupt_type & UART_IT_KEY) {
  144. }
  145. if (interrupt_type & UART_IT_RSTKEY) {
  146. }
  147. if (state != DISABLE) {
  148. sys_irq_init(IRQn_UART0_UDET, pr, isr);
  149. uartx->con |= interrupt_con_bit;
  150. } else {
  151. uartx->con &= ~interrupt_con_bit;
  152. if (interrupt_type == all_interrupt_type_mask) {
  153. PICEN &= ~BIT(IRQn_UART0_UDET);
  154. }
  155. }
  156. }
  157. /**
  158. * @brief Check the specified UART flag is set or not.
  159. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  160. * @param interrupt_type: specifies the flag to check.
  161. * this parameter can be one of the following values:
  162. * @arg UART_IT_TX: Transmit single data finish interrupt enable bit.
  163. * @arg UART_IT_RX: Receive single data finish interrupt enable bit.
  164. * @arg UART_IT_ERR: Raise error interrupt enable bit.
  165. * @arg UART_IT_KEY: Match key interrupt enable bit.
  166. * @arg UART_IT_RSTKEY: Reset match key interrupt enable bit.
  167. * @retval The state of uart_flag (SET or RESET).
  168. */
  169. AT(.com_periph.uart.get_flag)
  170. FLAG_STATE uart_get_flag(uart_typedef *uartx, UART_IT_TYPEDEF interrupt_type)
  171. {
  172. uint32_t interrupt_con_bit = 0;
  173. if (interrupt_type & UART_IT_TX) {
  174. interrupt_con_bit |= UARTxCON_TXPND;
  175. }
  176. if (interrupt_type & UART_IT_RX) {
  177. interrupt_con_bit |= UARTxCON_RXPND;
  178. }
  179. if (interrupt_type & UART_IT_ERR) {
  180. }
  181. if (interrupt_type & UART_IT_KEY) {
  182. }
  183. if (interrupt_type & UART_IT_RSTKEY) {
  184. }
  185. if ((uartx->con & interrupt_con_bit) != RESET) {
  186. return SET;
  187. } else {
  188. return RESET;
  189. }
  190. }
  191. /**
  192. * @brief Clear the UART's pending flag.
  193. * @param uartx: where x can be (0..2) to select the uartx peripheral.
  194. * @param interrupt_type: specifies the flag to check.
  195. * this parameter can be one of the following values:
  196. * @arg UART_IT_TX: Transmit single data finish interrupt enable bit.
  197. * @arg UART_IT_RX: Receive single data finish interrupt enable bit.
  198. * @arg UART_IT_ERR: Raise error interrupt enable bit.
  199. * @arg UART_IT_KEY: Match key interrupt enable bit.
  200. * @arg UART_IT_RSTKEY: Reset match key interrupt enable bit.
  201. * @retval None
  202. */
  203. AT(.com_periph.uart.clear_flag)
  204. void uart_clear_flag(uart_typedef *uartx, UART_IT_TYPEDEF interrupt_type)
  205. {
  206. uint32_t interrupt_con_bit = 0;
  207. if (interrupt_type & UART_IT_TX) {
  208. interrupt_con_bit |= UARTxCPND_CTXPND;
  209. }
  210. if (interrupt_type & UART_IT_RX) {
  211. interrupt_con_bit |= UARTxCPND_CRXPND;
  212. }
  213. if (interrupt_type & UART_IT_ERR) {
  214. interrupt_con_bit |= UARTxCPND_RX4BUF_ERR_CLR;
  215. }
  216. if (interrupt_type & UART_IT_KEY) {
  217. interrupt_con_bit |= UARTxCPND_CKEYPND;
  218. }
  219. if (interrupt_type & UART_IT_RSTKEY) {
  220. interrupt_con_bit |= UARTxCPND_CRSTKEYPND;
  221. }
  222. uartx->cpnd |= interrupt_con_bit;
  223. }
  224. /**
  225. * @brief Config the baud rate of the serial port.
  226. * @param uartx: The uart that need to config.
  227. * @param baud: The baudrate value need to set.
  228. * @retval None
  229. */
  230. void uart_baud_config(uart_typedef *uartx, uint32_t baud)
  231. {
  232. uint32_t clk_val, baud_reg;
  233. if (uartx->con & UARTxCON_UTEN)
  234. while ((uartx->con & UARTxCON_TXPND) == 0);
  235. if (uartx == UART) {
  236. if ((uartx->con & UARTxCON_CLKSRC) == 0) { // if select is sys clk
  237. clk_val = sys_clk_nhz_get();
  238. } else { // if select is inc clk
  239. clk_val = 2 * clk_uart_inc_get(CLK_VALUE_MODE_FREQ); // uart clk is double frequency of the clock source when select uart_inc
  240. }
  241. baud_reg = (uint16_t)((clk_val / baud) - 1);
  242. uartx->baud = (uint32_t)((baud_reg << 16) | baud_reg);
  243. } else if (uartx == UDET && (uartx->con & UARTxCON_FIXBAUD)) {
  244. clk_val = clk_udet_clk_get(CLK_VALUE_MODE_FREQ);
  245. baud_reg = (uint16_t)((clk_val / baud) - 1);
  246. uartx->baud = baud_reg;
  247. }
  248. }