hw_dma_uart.c 16 KB

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