hw_dma_uart.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include "board.h"
  2. #include "hw_dma_uart.h"
  3. #include "Action.h"
  4. #include "MachineConfig.h"
  5. typedef struct
  6. {
  7. GPIO_TypeDef *tx_port;
  8. uint8_t tx_pin;
  9. GPIO_TypeDef *rx_port;
  10. uint8_t rx_pin;
  11. uint32_t remap; //remap描述,不为0时说明需要remap
  12. GPIO_TypeDef *rs485_port;
  13. unsigned short rs485_pin;
  14. } hw_uart_pin_t;
  15. typedef struct
  16. {
  17. USART_TypeDef *base; //串口对像
  18. uint32_t speed; //通讯速度
  19. uint8_t rx_dma_stream; //接收所在的DMA
  20. //uint8_t rx_dma_ch; //接收所在DMA通道
  21. uint8_t tx_dma_stream; //接收所在的DMA
  22. //uint8_t tx_dma_ch; //发送所在DMA通道
  23. int rx_timeout; //接收空闲时间
  24. int tx_endtime; //发送完毕后多少时候算完成
  25. unsigned short rx_length; //接收长度
  26. unsigned short dma_value; //上次DMA接收的长度值
  27. sw_timer_t recv_timer;
  28. sw_timer_t send_timer;
  29. } hw_dma_uart_t;
  30. //管脚配置
  31. //管脚功能复用,需要自己去查找数据手册
  32. static hw_uart_pin_t hw_uart_pins_map[HW_DMA_UART_NUMBER] = {
  33. { GPIOA, 9,GPIOA, 10, 0, 0 },
  34. { GPIOD, 5, GPIOD, 6, GPIO_Remap_USART2, GPIOC, 0 },
  35. { GPIOB, 10, GPIOB, 11, 0, 0, 0 }
  36. };
  37. //串口配置
  38. //DMA对应的数据流通道,可以查找手册查到
  39. static hw_dma_uart_t hw_uarts_map[HW_DMA_UART_NUMBER] = {
  40. { USART1, 115200, ST_DMA1_STREAM5,ST_DMA1_STREAM4,2000, 0 },
  41. { USART2, 19200, ST_DMA1_STREAM6,ST_DMA1_STREAM7,2000, 0 },
  42. { USART3, 115200, ST_DMA1_STREAM3,ST_DMA1_STREAM2,2000, 0 }
  43. };
  44. #define RS485_RX_ENABLE(port,pin) port->BRR = 1 << pin
  45. #define RS485_TX_ENABLE(port,pin) port->BSRR = 1 << pin
  46. static int current_core_freq = 1;
  47. void hw_dma_uart_init(int clk)
  48. {
  49. uint32_t brr_value = 0;
  50. int index = 0;
  51. int src_clk = 0;
  52. //使能DMA2的时钟
  53. current_core_freq = clk;
  54. if(USE_EXTEND_INOUTPUT)
  55. {
  56. hw_uarts_map[0].speed = 256000;
  57. }
  58. for (index = 0; index < HW_DMA_UART_NUMBER; index++)
  59. {
  60. uint32_t port = (uint32_t)hw_uart_pins_map[index].rx_port;
  61. uint16_t pin = hw_uart_pins_map[index].rx_pin;
  62. if (port >= GPIOA_BASE &&
  63. port <= GPIOG_BASE)
  64. {
  65. RCC->APB2ENR |= 0x04 << ((port - GPIOA_BASE) / 0x400);
  66. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  67. GPIO_MODE_IPD,
  68. GPIO_SPEED_50M,
  69. GPIO_PUPD_PD);
  70. }
  71. port = (uint32_t)hw_uart_pins_map[index].tx_port;
  72. pin = hw_uart_pins_map[index].tx_pin;
  73. if (port >= GPIOA_BASE &&
  74. port <= GPIOG_BASE)
  75. {
  76. RCC->APB2ENR |= 0x04 << ((port - GPIOA_BASE) / 0x400);
  77. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  78. GPIO_MODE_AF_PP,
  79. GPIO_SPEED_50M,
  80. GPIO_PUPD_PD);
  81. }
  82. //不为0时说明管脚需要开启重新赋值
  83. if (hw_uart_pins_map[index].remap != 0) {
  84. GPIO_Remap_Set(hw_uart_pins_map[index].remap, 1);
  85. }
  86. port = (uint32_t)hw_uart_pins_map[index].rs485_port;
  87. pin = hw_uart_pins_map[index].rs485_pin;
  88. if (port >= GPIOA_BASE &&
  89. port <= GPIOG_BASE)
  90. {
  91. RCC->APB2ENR |= 0x04 << ((port - GPIOA_BASE) / 0x400);
  92. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  93. GPIO_MODE_OUT_PP,
  94. GPIO_SPEED_50M,
  95. GPIO_PUPD_PU);
  96. RS485_RX_ENABLE(((GPIO_TypeDef *)port), pin);
  97. }
  98. }
  99. for (index = 0; index < HW_DMA_UART_NUMBER; index++)
  100. {
  101. uint32_t base = (uint32_t)hw_uarts_map[index].base;
  102. //设置跟随波特率
  103. hw_noinit_write(2 * index + 2, hw_uarts_map[index].speed);
  104. if (base >= USART2_BASE && base <= UART5_BASE)
  105. {
  106. uint32_t rcc_src = 1 << ((base - USART2_BASE) / 0x400 + 17);
  107. do
  108. {
  109. RCC->APB1ENR |= rcc_src;
  110. }while ((RCC->APB1ENR & rcc_src) == 0);
  111. src_clk = 1000000 * clk / 2;
  112. } else if (base == USART1_BASE)
  113. {
  114. uint32_t rcc_src = 1 << 14;
  115. do
  116. {
  117. RCC->APB2ENR |= rcc_src;
  118. }while ((RCC->APB2ENR & rcc_src) == 0);
  119. src_clk = 1000000 * clk;
  120. }
  121. {
  122. hw_dma_uart_t *uart = &hw_uarts_map[index];
  123. int streamx = 0;
  124. float temp = 0;
  125. uint16_t baud_value = 0;
  126. uint16_t fraction = 0;
  127. DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->rx_dma_stream);
  128. DMA_TypeDef *st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->rx_dma_stream);
  129. streamx = uart->rx_dma_stream % 7;
  130. st_dma_stream->CCR &= ~0x00000001;
  131. SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
  132. st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
  133. st_dma_stream->CPAR = (uint32_t)(uart->base->DR); //DMA外设地址
  134. st_dma_stream->CCR = 0; //先全部复位CR寄存器值
  135. st_dma_stream->CCR |= 0 << 4; //存储器到外设模式
  136. st_dma_stream->CCR |= 0 << 5; //非循环模式(即使用普通模式)
  137. st_dma_stream->CCR |= 0 << 6; //外设非增量模式
  138. st_dma_stream->CCR |= 1 << 7; //存储器增量模式
  139. st_dma_stream->CCR |= 0 << 8; //外设数据长度:8位
  140. st_dma_stream->CCR |= 0 << 10; //存储器数据长度:8位
  141. st_dma_stream->CCR |= 1 << 12; //中等优先级
  142. st_dma_stream->CCR |= 0 << 14; //非存储器到存储器模式
  143. st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->tx_dma_stream);
  144. st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->tx_dma_stream);
  145. streamx = uart->tx_dma_stream % 7;
  146. st_dma_stream->CCR &= ~0x00000001;
  147. SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
  148. st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
  149. st_dma_stream->CPAR = (uint32_t)(uart->base->DR); //DMA外设地址
  150. st_dma_stream->CCR = 0; //先全部复位CR寄存器值
  151. st_dma_stream->CCR |= 1 << 4; //存储器到外设模式
  152. st_dma_stream->CCR |= 0 << 5; //非循环模式(即使用普通模式)
  153. st_dma_stream->CCR |= 0 << 6; //外设非增量模式
  154. st_dma_stream->CCR |= 1 << 7; //存储器增量模式
  155. st_dma_stream->CCR |= 0 << 8; //外设数据长度:8位
  156. st_dma_stream->CCR |= 0 << 10; //存储器数据长度:8位
  157. st_dma_stream->CCR |= 1 << 12; //中等优先级
  158. st_dma_stream->CCR |= 0 << 14; //非存储器到存储器模式
  159. uart->base->CR1 = 0; //清零CR1寄存器
  160. temp = (float)(src_clk) / (uart->speed * 16);
  161. baud_value = (u16)temp;
  162. fraction = (u16)((temp - baud_value) * 16 + 0.5);
  163. brr_value = (baud_value << 4) + fraction;
  164. uart->base->BRR = brr_value;
  165. uart->base->CR1 |= 0 << 12; //设置M0=0&M1=0,选择8位字长
  166. uart->base->CR1 |= 1 << 3; //串口发送使能
  167. uart->base->CR1 |= 1 << 2; //串口接收使能
  168. //不带任何校验
  169. uart->base->CR2 &= ~(0x03 << 12); //1位停止位
  170. uart->base->CR3 |= 1 << 7; //DMA发送使能
  171. uart->base->CR1 |= 1 << 13; //串口使能
  172. //使能脚默认接收模式
  173. if (hw_uart_pins_map[index].rs485_port != (void *)0)
  174. {
  175. RS485_RX_ENABLE(hw_uart_pins_map[index].rs485_port,hw_uart_pins_map[index].rs485_pin);
  176. }
  177. }
  178. }
  179. }
  180. /**
  181. * 读取串口缓冲,
  182. *
  183. * @author lxz
  184. *
  185. * @param uart_index 串口编号
  186. * @param buffer 读取数据的缓冲
  187. * @param size 读取的最大长度
  188. *
  189. * @return int 实际读取数量
  190. */
  191. int hw_dma_uart_begin_read(unsigned char uart_index, unsigned char *buffer, int size)
  192. {
  193. if (uart_index < HW_DMA_UART_NUMBER && size > 0)
  194. {
  195. hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
  196. uint32_t sr;
  197. int streamx = 0;
  198. DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->rx_dma_stream);
  199. DMA_TypeDef *st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->rx_dma_stream);
  200. streamx = uart->rx_dma_stream % 7;
  201. st_dma_stream->CCR &= ~0x00000001;
  202. SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
  203. st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
  204. sr = uart->base->SR;
  205. uart->base->SR &= ~(1 << 3);
  206. sr = uart->base->DR;
  207. sr = sr;
  208. (void)sr;
  209. uart->dma_value = size;
  210. uart->rx_length = size;
  211. //开始接收
  212. st_dma_stream->CCR = 0; //先全部复位CR寄存器值
  213. st_dma_stream->CCR |= (1 << 7) | (1 << 12); //存储器增量模式
  214. st_dma_stream->CPAR = (uint32_t)(&uart->base->DR);
  215. st_dma_stream->CMAR = (uint32_t)buffer;
  216. st_dma_stream->CNDTR = size;
  217. st_dma_stream->CCR |= 1 << 0;
  218. uart->base->CR3 |= 1 << 6; //DMA接收使能
  219. if (hw_uart_pins_map[uart_index].rs485_port != (void *)0)
  220. {
  221. RS485_RX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
  222. }
  223. }
  224. return 0;
  225. }
  226. /**
  227. * 输出到串口缓冲
  228. *
  229. * @author lxz
  230. *
  231. * @param uart_index 串口编号
  232. * @param buffer 发送数据的缓冲
  233. * @param size 发送的数据长度
  234. *
  235. * @return int 实际发送的数据长度
  236. *
  237. */
  238. int hw_dma_uart_begin_write(unsigned char uart_index, const char *buffer, int size)
  239. {
  240. if (uart_index < HW_DMA_UART_NUMBER && size > 0)
  241. {
  242. //使能脚发判断模式
  243. if (hw_uart_pins_map[uart_index].rs485_port != (void *)0)
  244. {
  245. RS485_TX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
  246. }
  247. #ifdef USART_WRITE_DEBUG
  248. hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
  249. while (size > 0)
  250. {
  251. if ((uart->base->ISR & 0x80))
  252. {
  253. size--;
  254. uart->base->TDR = *buffer;
  255. buffer++;
  256. }
  257. }
  258. #else
  259. hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
  260. int streamx = 0;
  261. DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->tx_dma_stream);
  262. DMA_TypeDef *st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->tx_dma_stream);
  263. streamx = uart->tx_dma_stream % 7;
  264. st_dma_stream->CCR &= ~0x00000001;
  265. SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
  266. st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
  267. st_dma_stream->CPAR = (uint32_t)(&uart->base->DR);
  268. st_dma_stream->CMAR = (uint32_t)buffer;
  269. st_dma_stream->CNDTR = size;
  270. st_dma_stream->CCR |= 1 << 0;
  271. #endif
  272. }
  273. return 0;
  274. }
  275. /**
  276. * 检查是否读取成功,成功会返回对应长度
  277. *
  278. * @author lxz
  279. *
  280. * @param void
  281. *
  282. * @return int
  283. */
  284. int hw_dma_uart_read_finish(unsigned char uart_index)
  285. {
  286. if (uart_index < HW_DMA_UART_NUMBER && hw_uarts_map[uart_index].rx_length > 0)
  287. {
  288. DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(hw_uarts_map[uart_index].rx_dma_stream);
  289. hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
  290. int res = st_dma_stream->CNDTR;
  291. int sr = uart->base->SR;
  292. //如果硬件产生了错误,需要手动清除
  293. if (sr & (1 << 3))
  294. {
  295. uart->base->SR &= ~(1 << 3);
  296. }
  297. if (res == 0)
  298. {
  299. res = uart->rx_length - res;
  300. uart->rx_length = 0;
  301. uart->base->CR3 &= ~(1 << 6); //取消DMA接收使能
  302. return res;
  303. } else if (res != uart->dma_value)
  304. {
  305. uart->dma_value = res;
  306. sw_timer_start(&uart->recv_timer, 0, uart->rx_timeout);
  307. } else if (uart->rx_length != res &&
  308. sw_timer_expire(&uart->recv_timer))
  309. {
  310. //停止接收
  311. st_dma_stream->CCR &= ~0x00000001;
  312. res = uart->rx_length - res;
  313. uart->rx_length = 0;
  314. uart->base->CR3 &= ~(1 << 6); //取消DMA接收使能
  315. return res;
  316. }
  317. }
  318. return 0;
  319. }
  320. /**
  321. * 检测是否写入成功,写入成功会返回1
  322. *
  323. * @author lxz
  324. *
  325. * @param void
  326. *
  327. * @return int
  328. */
  329. int hw_dma_uart_write_finish(unsigned char uart_index)
  330. {
  331. if (uart_index < HW_DMA_UART_NUMBER)
  332. {
  333. hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
  334. if (uart->base->SR & 1 << 6)
  335. {
  336. if (sw_timer_expire(&uart->send_timer))
  337. {
  338. //使能脚转接收模式
  339. if (hw_uart_pins_map[uart_index].rs485_port != (void *)0)
  340. {
  341. RS485_RX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
  342. }
  343. return 1;
  344. }
  345. } else
  346. {
  347. sw_timer_start(&uart->send_timer, 0, uart->tx_endtime);
  348. }
  349. }
  350. return 0;
  351. }
  352. /**
  353. * 串口一些参数动态设置接口
  354. *
  355. * @author lxz
  356. *
  357. * @param uart_index
  358. * @param cmd
  359. * @param value
  360. */
  361. int hw_dma_uart_control(unsigned char uart_index, char cmd, void *value)
  362. {
  363. if (uart_index >= HW_DMA_UART_NUMBER)
  364. {
  365. return -1;
  366. }
  367. switch (cmd)
  368. {
  369. case UART_CTRL_SET_SPEED : //设置串口速度
  370. {
  371. uint32_t base = (uint32_t)hw_uarts_map[uart_index].base;
  372. uint32_t brr_value = 0;
  373. float temp = 0;
  374. uint16_t baud_value = 0;
  375. uint16_t fraction = 0;
  376. int src_clk = 0;
  377. int speed = *((int *)value);
  378. hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
  379. if (base >= USART2_BASE && base <= UART5_BASE)
  380. {
  381. src_clk = 1000000 * current_core_freq / 2;
  382. } else if (base == USART1_BASE)
  383. {
  384. src_clk = 1000000 * current_core_freq;
  385. }
  386. uart->speed = speed;
  387. hw_noinit_write(2 * uart_index + 2, speed);
  388. temp = (float)(src_clk) / (uart->speed * 16);
  389. baud_value = (u16)temp;
  390. fraction = (u16)((temp - baud_value) * 16);
  391. brr_value = (baud_value << 4) + fraction;
  392. uart->base->CR1 &= ~(1 << 13); //清零CR1寄存器
  393. uart->base->BRR = brr_value;
  394. uart->base->CR1 |= 1 << 13; //串口使能
  395. }
  396. break;
  397. case UART_CTRL_SET_RDFIN_TIME : //设置串口接收完成判断时间
  398. {
  399. hw_uarts_map[uart_index].rx_timeout = *((int *)value);
  400. }
  401. break;
  402. case UART_CTRL_SET_WRFIN_TIME : //设置串口发送完成判断时间
  403. {
  404. hw_uarts_map[uart_index].tx_endtime = *((int *)value);
  405. }
  406. break;
  407. case UART_CTRL_GET_SPEED : //获取当前速度
  408. {
  409. return hw_uarts_map[uart_index].speed;
  410. }
  411. break;
  412. case UART_CTRL_GET_RDFIN_TIME : //获取当前串口接收完成时间
  413. {
  414. return hw_uarts_map[uart_index].rx_timeout;
  415. }
  416. break;
  417. case UART_CTRL_GET_WRFIN_TIME : //获取当前串口写入完成时间
  418. {
  419. return hw_uarts_map[uart_index].tx_endtime;
  420. }
  421. break;
  422. case UART_CTRL_GET_RDFIN : //串口接收是否完成,如果完成会返回接收长度
  423. {
  424. return hw_dma_uart_read_finish(uart_index);
  425. }
  426. break;
  427. case UART_CTRL_GET_WRFIN : //串口发送是否完成
  428. {
  429. return hw_dma_uart_write_finish(uart_index);
  430. }
  431. default:
  432. break;
  433. }
  434. return 0;
  435. }