1
0

imx_uart.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * o Redistributions of source code must retain the above copyright notice, this list
  9. * of conditions and the following disclaimer.
  10. *
  11. * o Redistributions in binary form must reproduce the above copyright notice, this
  12. * list of conditions and the following disclaimer in the documentation and/or
  13. * other materials provided with the distribution.
  14. *
  15. * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
  16. * contributors may be used to endorse or promote products derived from this
  17. * software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  23. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /*!
  31. * @file imx_uart.c
  32. * @brief UART driver.
  33. * @ingroup diag_uart
  34. */
  35. #include "sdk.h"
  36. #include "registers/regsuart.h"
  37. #include "imx_uart.h"
  38. #include "ccm_pll.h"
  39. #include "interrupt.h"
  40. #define UART_UFCR_RFDIV BF_UART_UFCR_RFDIV(4)
  41. //#define UART_UFCR_RFDIV UART_UFCR_RFDIV_4
  42. //#define UART_UFCR_RFDIV UART_UFCR_RFDIV_7
  43. uint32_t uart_get_reffreq(uint32_t instance)
  44. {
  45. uint32_t div = UART_UFCR_RFDIV;
  46. uint32_t ret = 0;
  47. uint32_t freq = get_peri_clock(UART_MODULE_CLK(instance));
  48. if (div == BF_UART_UFCR_RFDIV(4))
  49. ret = freq / 2;
  50. else if (div == BF_UART_UFCR_RFDIV(2))
  51. ret = freq / 4;
  52. else if (div == BF_UART_UFCR_RFDIV(6))
  53. ret = freq / 7;
  54. return ret;
  55. }
  56. uint8_t uart_putchar(uint32_t instance, uint8_t * ch)
  57. {
  58. /* Wait for Tx FIFO not full */
  59. while (HW_UART_UTS(instance).B.TXFULL);
  60. HW_UART_UTXD_WR(instance, *ch);
  61. return *ch;
  62. }
  63. uint8_t uart_getchar(uint32_t instance)
  64. {
  65. uint32_t read_data;
  66. /* If Rx FIFO has no data ready */
  67. if (!(HW_UART_USR2(instance).B.RDR))
  68. return NONE_CHAR;
  69. read_data = HW_UART_URXD_RD(instance);
  70. /* If error are detected */
  71. if (read_data & 0x7C00)
  72. return NONE_CHAR;
  73. return (uint8_t) read_data;
  74. }
  75. void uart_set_FIFO_mode(uint32_t instance, uint8_t fifo, uint8_t trigger_level,
  76. uint8_t service_mode)
  77. {
  78. if (fifo == TX_FIFO) {
  79. /* Configure the TX_FIFO trigger level */
  80. HW_UART_UFCR_CLR(instance,BM_UART_UFCR_TXTL);
  81. HW_UART_UFCR_SET(instance, BF_UART_UFCR_TXTL(trigger_level));
  82. /* Configure the TX_FIFO service mode */
  83. /* Default mode is polling: IRQ and DMA requests are disabled */
  84. HW_UART_UCR1_CLR(instance,(BM_UART_UCR1_TRDYEN | BM_UART_UCR1_TXDMAEN));
  85. if (service_mode == DMA_MODE)
  86. HW_UART_UCR1_SET(instance,BM_UART_UCR1_TXDMAEN);
  87. else if (service_mode == IRQ_MODE)
  88. HW_UART_UCR1_SET(instance,BM_UART_UCR1_TRDYEN);
  89. } else { /* fifo = RX_FIFO */
  90. /* Configure the RX_FIFO trigger level */
  91. HW_UART_UFCR_CLR(instance,BM_UART_UFCR_RXTL);
  92. HW_UART_UFCR_SET(instance,BF_UART_UFCR_RXTL(trigger_level));
  93. /* Configure the RX_FIFO service mode */
  94. /* Default mode is polling: IRQ and DMA requests are disabled */
  95. HW_UART_UCR1_CLR(instance,(BM_UART_UCR1_RRDYEN | BM_UART_UCR1_RXDMAEN));
  96. if (service_mode == DMA_MODE)
  97. HW_UART_UCR1_SET(instance,BM_UART_UCR1_RXDMAEN);
  98. else if (service_mode == IRQ_MODE)
  99. HW_UART_UCR1_SET(instance,BM_UART_UCR1_RRDYEN);
  100. }
  101. }
  102. void uart_set_loopback_mode(uint32_t instance, uint8_t state)
  103. {
  104. if (state == TRUE)
  105. HW_UART_UTS_SET(instance, BM_UART_UTS_LOOP);
  106. else
  107. HW_UART_UTS_CLR(instance, BM_UART_UTS_LOOP);
  108. }
  109. void uart_setup_interrupt(uint32_t instance, void (*irq_subroutine)(void), uint8_t state)
  110. {
  111. uint32_t irq_id = UART_IRQS(instance);
  112. if (state == TRUE) {
  113. /* register the IRQ sub-routine */
  114. register_interrupt_routine(irq_id, irq_subroutine);
  115. /* enable the IRQ */
  116. enable_interrupt(irq_id, CPU_0, 0);
  117. } else
  118. /* disable the IRQ */
  119. disable_interrupt(irq_id, CPU_0);
  120. }
  121. void uart_init(uint32_t instance, uint32_t baudrate, uint8_t parity,
  122. uint8_t stopbits, uint8_t datasize, uint8_t flowcontrol)
  123. {
  124. uint32_t base = REGS_UART_BASE(instance);
  125. /* configure the I/O for the port */
  126. uart_iomux_config(instance);
  127. /* enable the source clocks to the UART port */
  128. clock_gating_config(base, CLOCK_ON);
  129. /* Wait for UART to finish transmitting before changing the configuration */
  130. while (!(HW_UART_UTS(instance).B.TXEMPTY)) ;
  131. /* Disable UART */
  132. HW_UART_UCR1_CLR(instance,BM_UART_UCR1_UARTEN );
  133. /* Configure FIFOs trigger level to half-full and half-empty */
  134. HW_UART_UFCR_WR(instance, BF_UART_UFCR_RXTL(16) | UART_UFCR_RFDIV | BF_UART_UFCR_TXTL(16));
  135. /* Setup One Millisecond timer */
  136. HW_UART_ONEMS_WR(instance, uart_get_reffreq(instance) / 1000);
  137. /* Set parity */
  138. if (parity == PARITY_NONE)
  139. HW_UART_UCR2_CLR(instance,(BM_UART_UCR2_PREN| BM_UART_UCR2_PROE));
  140. else if (parity == PARITY_ODD)
  141. HW_UART_UCR2_SET(instance,(BM_UART_UCR2_PREN| BM_UART_UCR2_PROE));
  142. else { /* parity == PARITY_EVEN */
  143. HW_UART_UCR2_SET(instance, BM_UART_UCR2_PREN);
  144. HW_UART_UCR2_CLR(instance, BM_UART_UCR2_PROE);
  145. }
  146. /* Set stop bit */
  147. if (stopbits == STOPBITS_ONE)
  148. HW_UART_UCR2_CLR(instance, BM_UART_UCR2_STPB);
  149. else /* stopbits == STOPBITS_TWO */
  150. HW_UART_UCR2_SET(instance, BM_UART_UCR2_STPB);
  151. /* Set data size */
  152. if (datasize == EIGHTBITS)
  153. HW_UART_UCR2_SET(instance, BM_UART_UCR2_WS);
  154. else /* stopbits == STOPBITS_TWO */
  155. HW_UART_UCR2_CLR(instance, BM_UART_UCR2_WS);
  156. /* Configure the flow control */
  157. if (flowcontrol == FLOWCTRL_ON) {
  158. /* transmit done when RTS asserted */
  159. HW_UART_UCR2_CLR(instance, BM_UART_UCR2_IRTS );
  160. /* CTS controlled by the receiver */
  161. HW_UART_UCR2_SET(instance, BM_UART_UCR2_CTSC );
  162. } else { /* flowcontrol == FLOWCTRL_OFF */
  163. /* Ignore RTS */
  164. HW_UART_UCR2_SET(instance, BM_UART_UCR2_IRTS);
  165. /* CTS controlled by the CTS bit */
  166. HW_UART_UCR2_CLR(instance, BM_UART_UCR2_CTSC);
  167. }
  168. /* the reference manual says that this bit must always be set */
  169. HW_UART_UCR3_SET(instance, BM_UART_UCR3_RXDMUXSEL);
  170. /* Enable UART */
  171. HW_UART_UCR1_SET(instance, BM_UART_UCR1_UARTEN);
  172. /* Enable FIFOs and does software reset to clear status flags, reset
  173. the transmit and receive state machine, and reset the FIFOs */
  174. HW_UART_UCR2_SET(instance, BM_UART_UCR2_TXEN | BM_UART_UCR2_RXEN | BM_UART_UCR2_SRST);
  175. /* Set the numerator value minus one of the BRM ratio */
  176. HW_UART_UBIR_WR(instance, (baudrate / 100) - 1);
  177. /* Set the denominator value minus one of the BRM ratio */
  178. HW_UART_UBMR_WR(instance, ((uart_get_reffreq(instance) / 1600) - 1));
  179. /* Optional: prevent the UART to enter debug state. Useful when debugging
  180. the code with a JTAG and without active IRQ */
  181. HW_UART_UTS_SET(instance, BM_UART_UTS_DBGEN);
  182. }