PageRenderTime 28ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/bertos/cpu/cortex-m3/drv/ser_stm32.c

https://github.com/mtarek/BeRTOS
C | 386 lines | 278 code | 46 blank | 62 comment | 11 complexity | 2cc5e63f49914d9e534cb5009d34a2ea MD5 | raw file
  1. /**
  2. * \file
  3. * <!--
  4. * This file is part of BeRTOS.
  5. *
  6. * Bertos is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. * As a special exception, you may use this file as part of a free software
  21. * library without restriction. Specifically, if other files instantiate
  22. * templates or use macros or inline functions from this file, or you compile
  23. * this file and link it with other files to produce an executable, this
  24. * file does not by itself cause the resulting executable to be covered by
  25. * the GNU General Public License. This exception does not however
  26. * invalidate any other reasons why the executable file might be covered by
  27. * the GNU General Public License.
  28. *
  29. * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
  30. *
  31. * -->
  32. *
  33. * \brief STM32 UART interface driver.
  34. *
  35. * \author Daniele Basile <asterix@develer.com>
  36. */
  37. #include "ser_stm32.h"
  38. #include "cfg/cfg_ser.h"
  39. #include <cfg/macros.h> /* for BV() */
  40. #include <cfg/debug.h>
  41. #include <drv/gpio_stm32.h>
  42. #include <drv/irq_cm3.h>
  43. #include <drv/clock_stm32.h>
  44. #include <drv/ser_p.h>
  45. #include <drv/ser.h>
  46. /* From the high-level serial driver */
  47. extern struct Serial *ser_handles[SER_CNT];
  48. struct CM3Serial
  49. {
  50. struct SerialHardware hw;
  51. volatile bool sending;
  52. uint32_t base;
  53. sysirq_t irq;
  54. };
  55. /* Forward declaration */
  56. static struct CM3Serial UARTDesc[SER_CNT];
  57. /* GPIO descriptor for UART pins */
  58. struct gpio_uart_info
  59. {
  60. /* GPIO base address register */
  61. uint32_t base;
  62. /* Pin(s) bitmask */
  63. uint32_t rx_pin;
  64. uint32_t tx_pin;
  65. /* Sysctl */
  66. uint32_t sysctl_gpio;
  67. uint32_t sysctl_usart;
  68. };
  69. /* Table to retrieve GPIO pins configuration to work as UART pins */
  70. static const struct gpio_uart_info gpio_uart[SER_CNT] =
  71. {
  72. /* UART1 */
  73. {
  74. .base = GPIOA_BASE,
  75. .rx_pin = GPIO_USART1_RX_PIN,
  76. .tx_pin = GPIO_USART1_TX_PIN,
  77. .sysctl_gpio = RCC_APB2_GPIOA,
  78. .sysctl_usart = RCC_APB2_USART1,
  79. },
  80. /* UART2 */
  81. {
  82. .base = GPIOA_BASE,
  83. .rx_pin = GPIO_USART2_RX_PIN,
  84. .tx_pin = GPIO_USART2_TX_PIN,
  85. .sysctl_gpio = RCC_APB2_GPIOA,
  86. .sysctl_usart = RCC_APB1_USART2,
  87. },
  88. /* UART3 */
  89. {
  90. .base = GPIOB_BASE,
  91. .rx_pin = GPIO_USART3_RX_PIN,
  92. .tx_pin = GPIO_USART3_TX_PIN,
  93. .sysctl_gpio = RCC_APB2_GPIOB,
  94. .sysctl_usart = RCC_APB1_USART3,
  95. },
  96. };
  97. #define USART1_PORT 0
  98. #define USART2_PORT 1
  99. #define USART3_PORT 2
  100. void stm32_uartSetBaudRate(uint32_t base, unsigned long baud)
  101. {
  102. struct stm32_usart *_base = (struct stm32_usart *)base;
  103. _base->BRR = evaluate_brr(_base, CPU_FREQ, baud);
  104. }
  105. void stm32_uartSetParity(uint32_t base, int parity)
  106. {
  107. struct stm32_usart *_base = (struct stm32_usart *)base;
  108. /* USART_WORD_LEN_8B */
  109. _base->CR1 &= ~BV(CR1_M);
  110. switch(parity)
  111. {
  112. case SER_PARITY_NONE:
  113. _base->CR1 &= ~BV(CR1_PCE);
  114. break;
  115. case SER_PARITY_ODD:
  116. _base->CR1 |= (BV(CR1_PCE) | BV(CR1_PS));
  117. break;
  118. case SER_PARITY_EVEN:
  119. _base->CR1 |= BV(CR1_PCE);
  120. _base->CR1 &= ~BV(CR1_PS);
  121. break;
  122. default:
  123. ASSERT(0);
  124. return;
  125. }
  126. }
  127. void stm32_uartInit(int port)
  128. {
  129. struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
  130. ASSERT(port >= 0 && port < SER_CNT);
  131. /* Enable clocking on AFIO */
  132. RCC->APB2ENR |= RCC_APB2_AFIO;
  133. RCC->APB2ENR |= gpio_uart[port].sysctl_gpio;
  134. /* Configure USART pins */
  135. if (port == USART1_PORT)
  136. {
  137. RCC->APB2ENR |= gpio_uart[port].sysctl_usart;
  138. }
  139. else
  140. {
  141. RCC->APB1ENR |= gpio_uart[port].sysctl_usart;
  142. }
  143. stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base, gpio_uart[port].tx_pin,
  144. GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
  145. stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base, gpio_uart[port].rx_pin,
  146. GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
  147. /* Clear control registry */
  148. base->CR2 = 0;
  149. base->CR1 = 0;
  150. base->CR3 = 0;
  151. base->SR = 0;
  152. /* Set serial param: 115.200 bps, no parity */
  153. stm32_uartSetBaudRate(UARTDesc[port].base, 115200);
  154. stm32_uartSetParity(UARTDesc[port].base, SER_PARITY_NONE);
  155. /* Enable trasmision and receiver */
  156. base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
  157. }
  158. static bool tx_sending(struct SerialHardware *_hw)
  159. {
  160. struct CM3Serial *hw = (struct CM3Serial *)_hw;
  161. return hw->sending;
  162. }
  163. static void uart_irq_rx(int port)
  164. {
  165. struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
  166. struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
  167. char c;
  168. while (stm32_uartRxReady(UARTDesc[port].base))
  169. {
  170. c = base->DR;
  171. if (fifo_isfull(rxfifo))
  172. ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
  173. else
  174. fifo_push(rxfifo, c);
  175. }
  176. }
  177. static void uart_irq_tx(int port)
  178. {
  179. struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
  180. struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
  181. if (fifo_isempty(txfifo))
  182. {
  183. /*
  184. * Disable TX empty interrupts if there're no more
  185. * characters to transmit.
  186. */
  187. base->CR1 &= ~BV(CR1_TXEIE);
  188. UARTDesc[port].sending = false;
  189. }
  190. else
  191. {
  192. base->DR = fifo_pop(txfifo);
  193. }
  194. }
  195. static void uart_common_irq_handler(int port)
  196. {
  197. struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
  198. uint32_t status;
  199. /* Read and clear the IRQ status */
  200. status = base->SR;
  201. /* Check hw errors */
  202. ser_handles[port]->status = status &
  203. (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
  204. /* Process the IRQ */
  205. if (status & BV(CR1_RXNEIE))
  206. {
  207. uart_irq_rx(port);
  208. }
  209. if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
  210. {
  211. uart_irq_tx(port);
  212. }
  213. }
  214. static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
  215. {
  216. struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
  217. /* Register the IRQ handler */
  218. sysirq_setHandler(UARTDesc[port].irq, handler);
  219. base->CR1 |= BV(CR1_RXNEIE);
  220. }
  221. static void stm32_uartIRQDisable(int port)
  222. {
  223. struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
  224. base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
  225. }
  226. /* UART class definition */
  227. #define UART_PORT(port) \
  228. /* UART TX and RX buffers */ \
  229. static unsigned char uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
  230. static unsigned char uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE]; \
  231. \
  232. /* UART interrupt handler */ \
  233. static DECLARE_ISR(uart ## port ## _irq_handler) \
  234. { \
  235. uart_common_irq_handler(USART ## port ## _PORT); \
  236. } \
  237. \
  238. /* UART public methods */ \
  239. static void uart ## port ## _txStart(struct SerialHardware *_hw) \
  240. { \
  241. struct FIFOBuffer *txfifo = &ser_handles[USART ## port ## _PORT]->txfifo; \
  242. struct CM3Serial *hw = (struct CM3Serial *)_hw; \
  243. struct stm32_usart *base = (struct stm32_usart *)USART## port ## _BASE; \
  244. if (hw->sending) \
  245. return; \
  246. stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo)); \
  247. if (!fifo_isempty(txfifo)) \
  248. { \
  249. hw->sending = true; \
  250. base->CR1 |= BV(CR1_TXEIE); \
  251. } \
  252. } \
  253. \
  254. static void uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
  255. unsigned long baud) \
  256. { \
  257. stm32_uartSetBaudRate(USART## port ## _BASE, baud); \
  258. } \
  259. \
  260. static void uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
  261. int parity) \
  262. { \
  263. stm32_uartSetParity(USART## port ## _BASE, parity); \
  264. } \
  265. \
  266. static void uart ## port ## _cleanup(struct SerialHardware *_hw) \
  267. { \
  268. struct CM3Serial *hw = (struct CM3Serial *)_hw; \
  269. hw->sending = false; \
  270. stm32_uartIRQDisable(USART ## port ## _PORT); \
  271. stm32_uartClear(USART## port ## _BASE); \
  272. stm32_uartDisable(USART## port ## _BASE); \
  273. } \
  274. \
  275. static void uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw), \
  276. UNUSED_ARG(struct Serial *, ser)) \
  277. { \
  278. stm32_uartInit(USART ## port ## _PORT); \
  279. stm32_uartEnable(USART## port ## _BASE); \
  280. stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler); \
  281. } \
  282. \
  283. /* UART operations */ \
  284. static const struct SerialHardwareVT USART ## port ## _VT = \
  285. { \
  286. .init = uart ## port ## _init, \
  287. .cleanup = uart ## port ## _cleanup, \
  288. .setBaudrate = uart ## port ## _setbaudrate, \
  289. .setParity = uart ## port ## _setparity, \
  290. .txStart = uart ## port ## _txStart, \
  291. .txSending = tx_sending, \
  292. };
  293. /* UART port instances */
  294. UART_PORT(1)
  295. UART_PORT(2)
  296. UART_PORT(3)
  297. static struct CM3Serial UARTDesc[SER_CNT] =
  298. {
  299. {
  300. .hw = {
  301. .table = &USART1_VT,
  302. .txbuffer = uart1_txbuffer,
  303. .rxbuffer = uart1_rxbuffer,
  304. .txbuffer_size = sizeof(uart1_txbuffer),
  305. .rxbuffer_size = sizeof(uart1_rxbuffer),
  306. },
  307. .sending = false,
  308. .base = USART1_BASE,
  309. .irq = USART1_IRQHANDLER,
  310. },
  311. {
  312. .hw = {
  313. .table = &USART2_VT,
  314. .txbuffer = uart2_txbuffer,
  315. .rxbuffer = uart2_rxbuffer,
  316. .txbuffer_size = sizeof(uart2_txbuffer),
  317. .rxbuffer_size = sizeof(uart2_rxbuffer),
  318. },
  319. .sending = false,
  320. .base = USART2_BASE,
  321. .irq = USART2_IRQHANDLER,
  322. },
  323. {
  324. .hw = {
  325. .table = &USART3_VT,
  326. .txbuffer = uart3_txbuffer,
  327. .rxbuffer = uart3_rxbuffer,
  328. .txbuffer_size = sizeof(uart3_txbuffer),
  329. .rxbuffer_size = sizeof(uart3_rxbuffer),
  330. },
  331. .sending = false,
  332. .base = USART3_BASE,
  333. .irq = USART3_IRQHANDLER,
  334. },
  335. };
  336. struct SerialHardware *ser_hw_getdesc(int port)
  337. {
  338. ASSERT(port >= 0 && port < SER_CNT);
  339. return &UARTDesc[port].hw;
  340. }