123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- #include "board.h"
- #include "hw_dma_uart.h"
- #include "Action.h"
- #include "MachineConfig.h"
- typedef struct
- {
- GPIO_TypeDef *tx_port;
- uint8_t tx_pin;
- GPIO_TypeDef *rx_port;
- uint8_t rx_pin;
- uint32_t remap; //remap描述,不为0时说明需要remap
- GPIO_TypeDef *rs485_port;
- unsigned short rs485_pin;
- } hw_uart_pin_t;
- typedef struct
- {
- USART_TypeDef *base; //串口对像
- uint32_t speed; //通讯速度
- uint8_t rx_dma_stream; //接收所在的DMA
- //uint8_t rx_dma_ch; //接收所在DMA通道
- uint8_t tx_dma_stream; //接收所在的DMA
- //uint8_t tx_dma_ch; //发送所在DMA通道
- int rx_timeout; //接收空闲时间
- int tx_endtime; //发送完毕后多少时候算完成
- unsigned short rx_length; //接收长度
- unsigned short dma_value; //上次DMA接收的长度值
- sw_timer_t recv_timer;
- sw_timer_t send_timer;
- } hw_dma_uart_t;
- //管脚配置
- //管脚功能复用,需要自己去查找数据手册
- static hw_uart_pin_t hw_uart_pins_map[HW_DMA_UART_NUMBER] = {
- { GPIOA, 9,GPIOA, 10, 0, 0 },
- { GPIOD, 5, GPIOD, 6, GPIO_Remap_USART2, GPIOC, 0 },
- { GPIOB, 10, GPIOB, 11, 0, 0, 0 }
- };
- //串口配置
- //DMA对应的数据流通道,可以查找手册查到
- static hw_dma_uart_t hw_uarts_map[HW_DMA_UART_NUMBER] = {
- { USART1, 115200, ST_DMA1_STREAM5,ST_DMA1_STREAM4,2000, 0 },
- { USART2, 19200, ST_DMA1_STREAM6,ST_DMA1_STREAM7,2000, 0 },
- { USART3, 115200, ST_DMA1_STREAM3,ST_DMA1_STREAM2,2000, 0 }
- };
- #define RS485_RX_ENABLE(port,pin) port->BRR = 1 << pin
- #define RS485_TX_ENABLE(port,pin) port->BSRR = 1 << pin
- static int current_core_freq = 1;
- void hw_dma_uart_init(int clk)
- {
- uint32_t brr_value = 0;
- int index = 0;
- int src_clk = 0;
- //使能DMA2的时钟
- current_core_freq = clk;
-
- if(USE_EXTEND_INOUTPUT)
- {
- hw_uarts_map[0].speed = 256000;
- }
-
- for (index = 0; index < HW_DMA_UART_NUMBER; index++)
- {
- uint32_t port = (uint32_t)hw_uart_pins_map[index].rx_port;
- uint16_t pin = hw_uart_pins_map[index].rx_pin;
- if (port >= GPIOA_BASE &&
- port <= GPIOG_BASE)
- {
- RCC->APB2ENR |= 0x04 << ((port - GPIOA_BASE) / 0x400);
- GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
- GPIO_MODE_IPD,
- GPIO_SPEED_50M,
- GPIO_PUPD_PD);
-
- }
- port = (uint32_t)hw_uart_pins_map[index].tx_port;
- pin = hw_uart_pins_map[index].tx_pin;
- if (port >= GPIOA_BASE &&
- port <= GPIOG_BASE)
- {
- RCC->APB2ENR |= 0x04 << ((port - GPIOA_BASE) / 0x400);
- GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
- GPIO_MODE_AF_PP,
- GPIO_SPEED_50M,
- GPIO_PUPD_PD);
- }
- //不为0时说明管脚需要开启重新赋值
- if (hw_uart_pins_map[index].remap != 0) {
- GPIO_Remap_Set(hw_uart_pins_map[index].remap, 1);
- }
-
- port = (uint32_t)hw_uart_pins_map[index].rs485_port;
- pin = hw_uart_pins_map[index].rs485_pin;
- if (port >= GPIOA_BASE &&
- port <= GPIOG_BASE)
- {
- RCC->APB2ENR |= 0x04 << ((port - GPIOA_BASE) / 0x400);
- GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
- GPIO_MODE_OUT_PP,
- GPIO_SPEED_50M,
- GPIO_PUPD_PU);
- RS485_RX_ENABLE(((GPIO_TypeDef *)port), pin);
- }
- }
- for (index = 0; index < HW_DMA_UART_NUMBER; index++)
- {
- uint32_t base = (uint32_t)hw_uarts_map[index].base;
- //设置跟随波特率
- hw_noinit_write(2 * index + 2, hw_uarts_map[index].speed);
- if (base >= USART2_BASE && base <= UART5_BASE)
- {
- uint32_t rcc_src = 1 << ((base - USART2_BASE) / 0x400 + 17);
- do
- {
- RCC->APB1ENR |= rcc_src;
- }while ((RCC->APB1ENR & rcc_src) == 0);
- src_clk = 1000000 * clk / 2;
- } else if (base == USART1_BASE)
- {
- uint32_t rcc_src = 1 << 14;
- do
- {
- RCC->APB2ENR |= rcc_src;
- }while ((RCC->APB2ENR & rcc_src) == 0);
- src_clk = 1000000 * clk;
- }
- {
- hw_dma_uart_t *uart = &hw_uarts_map[index];
- int streamx = 0;
- float temp = 0;
- uint16_t baud_value = 0;
- uint16_t fraction = 0;
- DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->rx_dma_stream);
- DMA_TypeDef *st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->rx_dma_stream);
- streamx = uart->rx_dma_stream % 7;
- st_dma_stream->CCR &= ~0x00000001;
- SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
- st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
-
- st_dma_stream->CPAR = (uint32_t)(uart->base->DR); //DMA外设地址
- st_dma_stream->CCR = 0; //先全部复位CR寄存器值
- st_dma_stream->CCR |= 0 << 4; //存储器到外设模式
- st_dma_stream->CCR |= 0 << 5; //非循环模式(即使用普通模式)
- st_dma_stream->CCR |= 0 << 6; //外设非增量模式
- st_dma_stream->CCR |= 1 << 7; //存储器增量模式
- st_dma_stream->CCR |= 0 << 8; //外设数据长度:8位
- st_dma_stream->CCR |= 0 << 10; //存储器数据长度:8位
- st_dma_stream->CCR |= 1 << 12; //中等优先级
- st_dma_stream->CCR |= 0 << 14; //非存储器到存储器模式
- st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->tx_dma_stream);
- st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->tx_dma_stream);
- streamx = uart->tx_dma_stream % 7;
- st_dma_stream->CCR &= ~0x00000001;
- SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
- st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
-
- st_dma_stream->CPAR = (uint32_t)(uart->base->DR); //DMA外设地址
- st_dma_stream->CCR = 0; //先全部复位CR寄存器值
- st_dma_stream->CCR |= 1 << 4; //存储器到外设模式
- st_dma_stream->CCR |= 0 << 5; //非循环模式(即使用普通模式)
- st_dma_stream->CCR |= 0 << 6; //外设非增量模式
- st_dma_stream->CCR |= 1 << 7; //存储器增量模式
- st_dma_stream->CCR |= 0 << 8; //外设数据长度:8位
- st_dma_stream->CCR |= 0 << 10; //存储器数据长度:8位
- st_dma_stream->CCR |= 1 << 12; //中等优先级
- st_dma_stream->CCR |= 0 << 14; //非存储器到存储器模式
- uart->base->CR1 = 0; //清零CR1寄存器
- temp = (float)(src_clk) / (uart->speed * 16);
- baud_value = (u16)temp;
- fraction = (u16)((temp - baud_value) * 16 + 0.5);
- brr_value = (baud_value << 4) + fraction;
- uart->base->BRR = brr_value;
- uart->base->CR1 |= 0 << 12; //设置M0=0&M1=0,选择8位字长
- uart->base->CR1 |= 1 << 3; //串口发送使能
- uart->base->CR1 |= 1 << 2; //串口接收使能
- //不带任何校验
- uart->base->CR2 &= ~(0x03 << 12); //1位停止位
- uart->base->CR3 |= 1 << 7; //DMA发送使能
- uart->base->CR1 |= 1 << 13; //串口使能
- //使能脚默认接收模式
- if (hw_uart_pins_map[index].rs485_port != (void *)0)
- {
- RS485_RX_ENABLE(hw_uart_pins_map[index].rs485_port,hw_uart_pins_map[index].rs485_pin);
- }
- }
- }
- }
- /**
- * 读取串口缓冲,
- *
- * @author lxz
- *
- * @param uart_index 串口编号
- * @param buffer 读取数据的缓冲
- * @param size 读取的最大长度
- *
- * @return int 实际读取数量
- */
- int hw_dma_uart_begin_read(unsigned char uart_index, unsigned char *buffer, int size)
- {
- if (uart_index < HW_DMA_UART_NUMBER && size > 0)
- {
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- uint32_t sr;
- int streamx = 0;
- DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->rx_dma_stream);
- DMA_TypeDef *st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->rx_dma_stream);
- streamx = uart->rx_dma_stream % 7;
- st_dma_stream->CCR &= ~0x00000001;
- SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
-
- st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
-
- sr = uart->base->SR;
- uart->base->SR &= ~(1 << 3);
- sr = uart->base->DR;
- sr = sr;
- (void)sr;
- uart->dma_value = size;
- uart->rx_length = size;
- //开始接收
- st_dma_stream->CCR = 0; //先全部复位CR寄存器值
- st_dma_stream->CCR |= (1 << 7) | (1 << 12); //存储器增量模式
- st_dma_stream->CPAR = (uint32_t)(&uart->base->DR);
- st_dma_stream->CMAR = (uint32_t)buffer;
- st_dma_stream->CNDTR = size;
- st_dma_stream->CCR |= 1 << 0;
- uart->base->CR3 |= 1 << 6; //DMA接收使能
- if (hw_uart_pins_map[uart_index].rs485_port != (void *)0)
- {
- RS485_RX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
- }
- }
- return 0;
- }
- /**
- * 输出到串口缓冲
- *
- * @author lxz
- *
- * @param uart_index 串口编号
- * @param buffer 发送数据的缓冲
- * @param size 发送的数据长度
- *
- * @return int 实际发送的数据长度
- *
- */
- int hw_dma_uart_begin_write(unsigned char uart_index, const char *buffer, int size)
- {
- if (uart_index < HW_DMA_UART_NUMBER && size > 0)
- {
- //使能脚发判断模式
- if (hw_uart_pins_map[uart_index].rs485_port != (void *)0)
- {
- RS485_TX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
- }
- #ifdef USART_WRITE_DEBUG
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- while (size > 0)
- {
- if ((uart->base->ISR & 0x80))
- {
- size--;
- uart->base->TDR = *buffer;
- buffer++;
- }
- }
- #else
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- int streamx = 0;
- DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(uart->tx_dma_stream);
- DMA_TypeDef *st_dma = (DMA_TypeDef *)st_dma_get_dmax(uart->tx_dma_stream);
- streamx = uart->tx_dma_stream % 7;
- st_dma_stream->CCR &= ~0x00000001;
- SW_WAIT_FINISH(st_dma_stream->CCR & 0X01);
- st_dma->IFCR |= 0X0F << (4 * streamx); //清空之前该stream上的所有中断标志
-
- st_dma_stream->CPAR = (uint32_t)(&uart->base->DR);
- st_dma_stream->CMAR = (uint32_t)buffer;
- st_dma_stream->CNDTR = size;
- st_dma_stream->CCR |= 1 << 0;
- #endif
- }
- return 0;
- }
- /**
- * 检查是否读取成功,成功会返回对应长度
- *
- * @author lxz
- *
- * @param void
- *
- * @return int
- */
- int hw_dma_uart_read_finish(unsigned char uart_index)
- {
- if (uart_index < HW_DMA_UART_NUMBER && hw_uarts_map[uart_index].rx_length > 0)
- {
- DMA_Stream_TypeDef *st_dma_stream = (DMA_Stream_TypeDef *)st_dma_get_stream(hw_uarts_map[uart_index].rx_dma_stream);
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- int res = st_dma_stream->CNDTR;
- int sr = uart->base->SR;
- //如果硬件产生了错误,需要手动清除
- if (sr & (1 << 3))
- {
- uart->base->SR &= ~(1 << 3);
- }
- if (res == 0)
- {
- res = uart->rx_length - res;
- uart->rx_length = 0;
- uart->base->CR3 &= ~(1 << 6); //取消DMA接收使能
- return res;
- } else if (res != uart->dma_value)
- {
- uart->dma_value = res;
- sw_timer_start(&uart->recv_timer, 0, uart->rx_timeout);
- } else if (uart->rx_length != res &&
- sw_timer_expire(&uart->recv_timer))
- {
- //停止接收
- st_dma_stream->CCR &= ~0x00000001;
- res = uart->rx_length - res;
- uart->rx_length = 0;
- uart->base->CR3 &= ~(1 << 6); //取消DMA接收使能
- return res;
- }
- }
- return 0;
- }
- /**
- * 检测是否写入成功,写入成功会返回1
- *
- * @author lxz
- *
- * @param void
- *
- * @return int
- */
- int hw_dma_uart_write_finish(unsigned char uart_index)
- {
- if (uart_index < HW_DMA_UART_NUMBER)
- {
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- if (uart->base->SR & 1 << 6)
- {
- if (sw_timer_expire(&uart->send_timer))
- {
- //使能脚转接收模式
- if (hw_uart_pins_map[uart_index].rs485_port != (void *)0)
- {
- RS485_RX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
- }
- return 1;
- }
- } else
- {
- sw_timer_start(&uart->send_timer, 0, uart->tx_endtime);
- }
- }
- return 0;
- }
- /**
- * 串口一些参数动态设置接口
- *
- * @author lxz
- *
- * @param uart_index
- * @param cmd
- * @param value
- */
- int hw_dma_uart_control(unsigned char uart_index, char cmd, void *value)
- {
- if (uart_index >= HW_DMA_UART_NUMBER)
- {
- return -1;
- }
- switch (cmd)
- {
- case UART_CTRL_SET_SPEED : //设置串口速度
- {
- uint32_t base = (uint32_t)hw_uarts_map[uart_index].base;
- uint32_t brr_value = 0;
- float temp = 0;
- uint16_t baud_value = 0;
- uint16_t fraction = 0;
- int src_clk = 0;
- int speed = *((int *)value);
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- if (base >= USART2_BASE && base <= UART5_BASE)
- {
- src_clk = 1000000 * current_core_freq / 2;
- } else if (base == USART1_BASE)
- {
- src_clk = 1000000 * current_core_freq;
- }
- uart->speed = speed;
- hw_noinit_write(2 * uart_index + 2, speed);
- temp = (float)(src_clk) / (uart->speed * 16);
- baud_value = (u16)temp;
- fraction = (u16)((temp - baud_value) * 16);
- brr_value = (baud_value << 4) + fraction;
-
- uart->base->CR1 &= ~(1 << 13); //清零CR1寄存器
- uart->base->BRR = brr_value;
- uart->base->CR1 |= 1 << 13; //串口使能
-
- }
- break;
- case UART_CTRL_SET_RDFIN_TIME : //设置串口接收完成判断时间
- {
- hw_uarts_map[uart_index].rx_timeout = *((int *)value);
- }
- break;
- case UART_CTRL_SET_WRFIN_TIME : //设置串口发送完成判断时间
- {
- hw_uarts_map[uart_index].tx_endtime = *((int *)value);
- }
- break;
- case UART_CTRL_GET_SPEED : //获取当前速度
- {
- return hw_uarts_map[uart_index].speed;
- }
- break;
- case UART_CTRL_GET_RDFIN_TIME : //获取当前串口接收完成时间
- {
- return hw_uarts_map[uart_index].rx_timeout;
- }
- break;
- case UART_CTRL_GET_WRFIN_TIME : //获取当前串口写入完成时间
- {
- return hw_uarts_map[uart_index].tx_endtime;
- }
- break;
- case UART_CTRL_GET_RDFIN : //串口接收是否完成,如果完成会返回接收长度
- {
- return hw_dma_uart_read_finish(uart_index);
- }
- break;
- case UART_CTRL_GET_WRFIN : //串口发送是否完成
- {
- return hw_dma_uart_write_finish(uart_index);
- }
- default:
- break;
- }
- return 0;
- }
|