#include "rtthread.h" #include "stm32f4xx.h" #include "board.h" #include "if_uart_dma.h" #ifndef RT_THREAD #define rt_interrupt_enter() #define rt_interrupt_leave() #define rt_sem_create(...) 0 #define rt_sem_delete(...) #define rt_sem_take(...) #define rt_sem_release(...) #endif #define GPIO_Initer() {.GPIO_Mode=GPIO_Mode_AF,\ .GPIO_Speed=GPIO_Speed_50MHz,\ .GPIO_OType=GPIO_OType_PP,\ .GPIO_PuPd=GPIO_PuPd_UP \ } #define UART_Initer() {.USART_WordLength=USART_WordLength_8b,\ .USART_StopBits=USART_StopBits_1,\ .USART_Parity=USART_Parity_No,\ .USART_HardwareFlowControl=USART_HardwareFlowControl_None,\ .USART_Mode=USART_Mode_Rx | USART_Mode_Tx,\ } #define NVIC_Initer() {0} #define DMA_RX_Initer() {\ .DMA_DIR = DMA_DIR_PeripheralToMemory,\ .DMA_PeripheralInc = DMA_PeripheralInc_Disable,\ .DMA_MemoryInc = DMA_MemoryInc_Enable,\ .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,\ .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,\ .DMA_Mode = DMA_Mode_Circular,\ .DMA_Priority = DMA_Priority_High,\ .DMA_FIFOMode = DMA_FIFOMode_Disable,\ .DMA_FIFOThreshold = DMA_FIFOThreshold_Full,\ .DMA_MemoryBurst = DMA_MemoryBurst_Single,\ .DMA_PeripheralBurst = DMA_PeripheralBurst_Single,\ } #define DMA_TX_Initer() {\ .DMA_DIR = DMA_DIR_MemoryToPeripheral,\ .DMA_PeripheralInc = DMA_PeripheralInc_Disable,\ .DMA_MemoryInc = DMA_MemoryInc_Enable,\ .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,\ .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,\ .DMA_Mode = DMA_Mode_Normal,\ .DMA_Priority = DMA_Priority_Medium,\ .DMA_FIFOMode = DMA_FIFOMode_Disable,\ .DMA_FIFOThreshold = DMA_FIFOThreshold_Full,\ .DMA_MemoryBurst = DMA_MemoryBurst_Single,\ .DMA_PeripheralBurst = DMA_PeripheralBurst_Single,\ } typedef struct{ char *name; USART_TypeDef *uart; void (*uart_clock_fun)(uint32_t,FunctionalState); uint32_t uart_rcc; int baudrate; int irq_channel; void (*gpio_tx_clock_fun)(uint32_t,FunctionalState); uint32_t gpio_tx_rcc; GPIO_TypeDef *gpio_tx_base; uint16_t gpio_tx_pin; uint8_t gpio_tx_af; void (*gpio_rx_clock_fun)(uint32_t,FunctionalState); uint32_t gpio_rx_rcc; GPIO_TypeDef *gpio_rx_base; uint16_t gpio_rx_pin; uint8_t gpio_rx_af; DMA_Stream_TypeDef *dma_rx_stream; void (*dma_rx_clock_fun)(uint32_t,FunctionalState); uint32_t dma_rx_rcc; uint32_t dma_rx_channel; DMA_Stream_TypeDef *dma_tx_stream; void (*dma_tx_clock_fun)(uint32_t,FunctionalState); uint32_t dma_tx_rcc; uint32_t dma_tx_channel; int dma_tx_irq_channel; uint32_t dma_tx_tc_flag; }uart_dtb; static const uart_dtb g_uartdtb[]={ { .name="uart1", .uart=USART1, .uart_clock_fun=RCC_APB2PeriphClockCmd, .uart_rcc=RCC_APB2Periph_USART1, .baudrate=57600, .irq_channel=USART1_IRQn, .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_tx_rcc=RCC_AHB1Periph_GPIOA, .gpio_tx_base=GPIOA, .gpio_tx_pin=9, .gpio_tx_af=GPIO_AF_USART1, .gpio_rx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_rx_rcc=RCC_AHB1Periph_GPIOA, .gpio_rx_base=GPIOA, .gpio_rx_pin=10, .gpio_rx_af=GPIO_AF_USART1, .dma_rx_stream=DMA2_Stream5, .dma_rx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_rx_rcc=RCC_AHB1Periph_DMA2, .dma_rx_channel=DMA_Channel_4, .dma_tx_stream=DMA2_Stream7, .dma_tx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_tx_rcc=RCC_AHB1Periph_DMA2, .dma_tx_channel=DMA_Channel_4, .dma_tx_irq_channel=DMA2_Stream7_IRQn, .dma_tx_tc_flag=DMA_FLAG_TCIF7, }, { .name="uart2", .uart=USART2, .uart_clock_fun=RCC_APB1PeriphClockCmd, .uart_rcc=RCC_APB1Periph_USART2, .baudrate=57600, .irq_channel=USART2_IRQn, .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_tx_rcc=RCC_AHB1Periph_GPIOD, .gpio_tx_base=GPIOD, .gpio_tx_pin=5, .gpio_tx_af=GPIO_AF_USART2, .gpio_rx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_rx_rcc=RCC_AHB1Periph_GPIOD, .gpio_rx_base=GPIOD, .gpio_rx_pin=6, .gpio_rx_af=GPIO_AF_USART2, .dma_rx_stream=DMA1_Stream5, .dma_rx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_rx_rcc=RCC_AHB1Periph_DMA1, .dma_rx_channel=DMA_Channel_4, .dma_tx_stream=DMA1_Stream6, .dma_tx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_tx_rcc=RCC_AHB1Periph_DMA1, .dma_tx_channel=DMA_Channel_4, .dma_tx_irq_channel=DMA1_Stream6_IRQn, .dma_tx_tc_flag=DMA_FLAG_TCIF6, }, { .name="uart3", .uart=USART3, .uart_clock_fun=RCC_APB1PeriphClockCmd, .uart_rcc=RCC_APB1Periph_USART3, .baudrate=57600, .irq_channel=USART3_IRQn, .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_tx_rcc=RCC_AHB1Periph_GPIOD, .gpio_tx_base=GPIOD, .gpio_tx_pin=8, .gpio_tx_af=GPIO_AF_USART3, .gpio_rx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_rx_rcc=RCC_AHB1Periph_GPIOD, .gpio_rx_base=GPIOD, .gpio_rx_pin=9, .gpio_rx_af=GPIO_AF_USART3, .dma_rx_stream=DMA1_Stream1, .dma_rx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_rx_rcc=RCC_AHB1Periph_DMA1, .dma_rx_channel=DMA_Channel_4, .dma_tx_stream=DMA1_Stream3, .dma_tx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_tx_rcc=RCC_AHB1Periph_DMA1, .dma_tx_channel=DMA_Channel_4, .dma_tx_irq_channel=DMA1_Stream3_IRQn, .dma_tx_tc_flag=DMA_FLAG_TCIF3, }, { .name="uart4", .uart=UART4, .uart_clock_fun=RCC_APB1PeriphClockCmd, .uart_rcc=RCC_APB1Periph_UART4, .baudrate=115200, .irq_channel=UART4_IRQn, .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_tx_rcc=RCC_AHB1Periph_GPIOC, .gpio_tx_base=GPIOC, .gpio_tx_pin=10, .gpio_tx_af=GPIO_AF_UART4, .gpio_rx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_rx_rcc=RCC_AHB1Periph_GPIOC, .gpio_rx_base=GPIOC, .gpio_rx_pin=11, .gpio_rx_af=GPIO_AF_UART4, .dma_rx_stream=DMA1_Stream2, .dma_rx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_rx_rcc=RCC_AHB1Periph_DMA1, .dma_rx_channel=DMA_Channel_4, .dma_tx_stream=DMA1_Stream4, .dma_tx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_tx_rcc=RCC_AHB1Periph_DMA1, .dma_tx_channel=DMA_Channel_4, .dma_tx_irq_channel=DMA1_Stream4_IRQn, .dma_tx_tc_flag=DMA_FLAG_TCIF4, }, { .name="uart5", .uart=UART5, .uart_clock_fun=RCC_APB1PeriphClockCmd, .uart_rcc=RCC_APB1Periph_UART5, .baudrate=57600, .irq_channel=UART5_IRQn, .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_tx_rcc=RCC_AHB1Periph_GPIOC, .gpio_tx_base=GPIOC, .gpio_tx_pin=12, .gpio_tx_af=GPIO_AF_UART5, .gpio_rx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_rx_rcc=RCC_AHB1Periph_GPIOD, .gpio_rx_base=GPIOD, .gpio_rx_pin=2, .gpio_rx_af=GPIO_AF_UART5, .dma_rx_stream=DMA1_Stream0, .dma_rx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_rx_rcc=RCC_AHB1Periph_DMA1, .dma_rx_channel=DMA_Channel_4, .dma_tx_stream=DMA1_Stream7, .dma_tx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_tx_rcc=RCC_AHB1Periph_DMA1, .dma_tx_channel=DMA_Channel_4, .dma_tx_irq_channel=DMA1_Stream7_IRQn, .dma_tx_tc_flag=DMA_FLAG_TCIF7, }, { .name="uart6", .uart=USART6, .uart_clock_fun=RCC_APB2PeriphClockCmd, .uart_rcc=RCC_APB2Periph_USART6, .baudrate=57600, .irq_channel=USART6_IRQn, .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_tx_rcc=RCC_AHB1Periph_GPIOC, .gpio_tx_base=GPIOC, .gpio_tx_pin=6, .gpio_tx_af=GPIO_AF_USART6, .gpio_rx_clock_fun=RCC_AHB1PeriphClockCmd, .gpio_rx_rcc=RCC_AHB1Periph_GPIOC, .gpio_rx_base=GPIOC, .gpio_rx_pin=7, .gpio_rx_af=GPIO_AF_USART6, .dma_rx_stream=DMA2_Stream2, .dma_rx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_rx_rcc=RCC_AHB1Periph_DMA2, .dma_rx_channel=DMA_Channel_5, .dma_tx_stream=DMA2_Stream6, .dma_tx_clock_fun=RCC_AHB1PeriphClockCmd, .dma_tx_rcc=RCC_AHB1Periph_DMA2, .dma_tx_channel=DMA_Channel_5, .dma_tx_irq_channel=DMA2_Stream6_IRQn, .dma_tx_tc_flag=DMA_FLAG_TCIF6, }, }; typedef struct{ const uart_dtb *dtb; void (*irq_fun)(void *t,uint8_t d); void (*irq_fun_end)(void *t,uint32_t len); void *t; uint8_t *rx_buff; uint32_t rx_buff_size; void *sem; int in_send; }self_data; static self_data g_self[LENGTH(g_uartdtb)]; def_find_fun(uart_dtb,g_uartdtb) static int init(uart_def *u,int bsp) { param_check(u); if(u->private_data) return 0; GPIO_InitTypeDef init=GPIO_Initer(); USART_InitTypeDef init2=UART_Initer(); NVIC_InitTypeDef init3=NVIC_Initer(); int index; const uart_dtb *dtb=find(u->name,&index); self_data *self=&g_self[index]; self->dtb=dtb; self->irq_fun=0; self->t=0; self->sem=rt_sem_create(u->name,1,RT_IPC_FLAG_FIFO); self->in_send=0; { u->private_data=self; dtb->uart_clock_fun(dtb->uart_rcc,ENABLE); if(bsp==0) bsp=dtb->baudrate; init2.USART_BaudRate = bsp; USART_Init(dtb->uart, &init2); USART_Cmd(dtb->uart, ENABLE); dtb->gpio_tx_clock_fun(dtb->gpio_tx_rcc,ENABLE); GPIO_PinAFConfig(dtb->gpio_tx_base,dtb->gpio_tx_pin,dtb->gpio_tx_af); init.GPIO_Pin=1<gpio_tx_pin; GPIO_Init(dtb->gpio_tx_base,&init); dtb->gpio_rx_clock_fun(dtb->gpio_rx_rcc,ENABLE); GPIO_PinAFConfig(dtb->gpio_rx_base,dtb->gpio_rx_pin,dtb->gpio_rx_af); init.GPIO_Pin=1<gpio_rx_pin; GPIO_Init(dtb->gpio_rx_base,&init); init3.NVIC_IRQChannel = dtb->irq_channel; init3.NVIC_IRQChannelPreemptionPriority=3; init3.NVIC_IRQChannelSubPriority =3; init3.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&init3); USART_ITConfig(dtb->uart, USART_IT_IDLE, ENABLE); init3.NVIC_IRQChannel = dtb->dma_tx_irq_channel; init3.NVIC_IRQChannelPreemptionPriority=3; init3.NVIC_IRQChannelSubPriority =3; init3.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&init3); } return 0; } static int dma_rx_init(self_data *self,uint8_t *rx_buff,uint32_t rx_buff_size) { const uart_dtb *dtb=self->dtb; DMA_InitTypeDef init=DMA_RX_Initer(); USART_DMACmd(dtb->uart,USART_DMAReq_Rx,ENABLE); DMA_DeInit(dtb->dma_rx_stream); while (DMA_GetCmdStatus(dtb->dma_rx_stream) != DISABLE); RCC_AHB1PeriphClockCmd(dtb->dma_rx_rcc,ENABLE); init.DMA_Channel = dtb->dma_rx_channel; init.DMA_PeripheralBaseAddr = (u32)(&(dtb->uart->DR)); init.DMA_Memory0BaseAddr = (u32)rx_buff; DMA_Init(dtb->dma_rx_stream, &init); DMA_Cmd(dtb->dma_rx_stream, DISABLE); return 0; } static int dma_rx_reset(self_data *self) { const uart_dtb *dtb=self->dtb; DMA_Cmd(dtb->dma_rx_stream, DISABLE); while(DMA_GetCmdStatus(dtb->dma_rx_stream)!=DISABLE); DMA_SetCurrDataCounter(dtb->dma_rx_stream, self->rx_buff_size); DMA_Cmd(dtb->dma_rx_stream, ENABLE); return 0; } static int dma_tx_init(self_data *self,const uint8_t *tx_buff,uint32_t tx_buff_size) { const uart_dtb *dtb=self->dtb; DMA_InitTypeDef init=DMA_TX_Initer(); USART_DMACmd(dtb->uart,USART_DMAReq_Tx,ENABLE); DMA_DeInit(dtb->dma_tx_stream); while (DMA_GetCmdStatus(dtb->dma_tx_stream) != DISABLE); RCC_AHB1PeriphClockCmd(dtb->dma_tx_rcc,ENABLE); init.DMA_Channel = dtb->dma_tx_channel; init.DMA_PeripheralBaseAddr = (u32)(&(dtb->uart->DR)); init.DMA_Memory0BaseAddr = (u32)tx_buff; init.DMA_BufferSize=tx_buff_size; DMA_Init(dtb->dma_tx_stream, &init); DMA_Cmd(dtb->dma_tx_stream, ENABLE); DMA_ITConfig(dtb->dma_tx_stream,DMA_IT_TC,ENABLE); return 0; } static int dma_tx_reset(self_data *self,uint8_t *tx_buff,uint32_t tx_buff_size) { const uart_dtb *dtb=self->dtb; USART_DMACmd(dtb->uart,USART_DMAReq_Tx,ENABLE); DMA_Cmd(dtb->dma_tx_stream, DISABLE); while(DMA_GetCmdStatus(dtb->dma_tx_stream)!=DISABLE); DMA_ClearFlag(dtb->dma_tx_stream,dtb->dma_tx_tc_flag); DMA_SetCurrDataCounter(dtb->dma_tx_stream, tx_buff_size); dtb->dma_rx_stream->M0AR=(uint32_t)tx_buff; DMA_Cmd(dtb->dma_tx_stream, ENABLE); return 0; } static int deinit(uart_def *u) { param_check(u); if(u->private_data==0) return 0; NVIC_InitTypeDef init3=NVIC_Initer(); const uart_dtb *dtb=find(u->name,0); { USART_Cmd(dtb->uart, DISABLE); dtb->uart_clock_fun(dtb->uart_rcc,DISABLE); dtb->gpio_tx_clock_fun(dtb->gpio_tx_rcc,DISABLE); dtb->gpio_rx_clock_fun(dtb->gpio_rx_rcc,DISABLE); init3.NVIC_IRQChannelCmd = DISABLE; NVIC_Init(&init3); USART_ITConfig(dtb->uart, USART_IT_RXNE, DISABLE); rt_sem_delete(((self_data *)u->private_data)->sem); u->private_data=0; } return 0; } static int set_irq(uart_def *u,void (*irq)(void *t,uint8_t d),void *t) { param_check(u); param_check(u->private_data); self_data *self=u->private_data; irq_disable(); self->irq_fun=irq; self->t=t; irq_enable(); return 0; } static int set_end_irq(uart_def *u,uint8_t *rx_buff,int rx_buff_size, void (*irq)(void *t,uint32_t len),void *t) { param_check(u); param_check(u->private_data); self_data *self=u->private_data; dma_rx_init(self,rx_buff,rx_buff_size); self->rx_buff=rx_buff; self->rx_buff_size=rx_buff_size; dma_rx_reset(self); irq_disable(); self->irq_fun_end=irq; self->t=t; irq_enable(); return 0; } static int read(uart_def *u,uint8_t *b,int len) { param_check(u); param_check(u->private_data); return 0; } // dma后台发送需要保证数据在发送期间有效 static int write(uart_def *u,const uint8_t *b,int len) { param_check(u); param_check(u->private_data); self_data *self=u->private_data; USART_TypeDef *uart=self->dtb->uart; if(1){ dma_tx_init(self,b,len); }else{ for(int i=0;iDR=b[i]; } } return len; } // 阻塞发送,此函数结束即可释放内存 static int write_block(uart_def *u,const uint8_t *b,int len) { param_check(u); param_check(u->private_data); self_data *self=u->private_data; USART_TypeDef *uart=self->dtb->uart; self->in_send=1; if(1){ dma_tx_init(self,b,len); }else{ for(int i=0;iDR=b[i]; } self->in_send=0; } while(self->in_send){} return len; } static inline void self_irq(self_data *self) { rt_interrupt_enter(); const uart_dtb *dtb=self->dtb; if(USART_GetFlagStatus(dtb->uart,USART_FLAG_RXNE)) { if(self->irq_fun){ self->irq_fun(self->t,dtb->uart->DR); } } else if(USART_GetFlagStatus(dtb->uart,USART_FLAG_TC)) { USART_ClearFlag(dtb->uart,USART_FLAG_TC); } else if(USART_GetFlagStatus(dtb->uart,USART_FLAG_IDLE)) { USART_ReceiveData(dtb->uart); if(self->irq_fun_end){ self->irq_fun_end(self->t,self->rx_buff_size-DMA_GetCurrDataCounter(dtb->dma_rx_stream)); } dma_rx_reset(self); } rt_interrupt_leave(); } static inline void self_dma_irq(self_data *self) { rt_interrupt_enter(); const uart_dtb *dtb=self->dtb; if(DMA_GetFlagStatus(dtb->dma_tx_stream,dtb->dma_tx_tc_flag)) { DMA_ClearFlag(dtb->dma_tx_stream,dtb->dma_tx_tc_flag); DMA_Cmd(dtb->dma_tx_stream, DISABLE); self->in_send=0; } rt_interrupt_leave(); } void USART1_IRQHandler(void) { self_data *self=&g_self[0]; self_irq(self); } void USART2_IRQHandler(void) { self_data *self=&g_self[1]; self_irq(self); } void USART3_IRQHandler(void) { self_data *self=&g_self[2]; self_irq(self); } void UART4_IRQHandler(void) { self_data *self=&g_self[3]; self_irq(self); } void UART5_IRQHandler(void) { self_data *self=&g_self[4]; self_irq(self); } void USART6_IRQHandler(void) { self_data *self=&g_self[5]; self_irq(self); } void DMA2_Stream7_IRQHandler(void) { self_data *self=&g_self[0]; self_dma_irq(self); } void DMA1_Stream6_IRQHandler(void) { self_data *self=&g_self[1]; self_dma_irq(self); } void DMA1_Stream3_IRQHandler(void) { self_data *self=&g_self[2]; self_dma_irq(self); } void DMA1_Stream4_IRQHandler(void) { self_data *self=&g_self[3]; self_dma_irq(self); } void DMA1_Stream7_IRQHandler(void) { self_data *self=&g_self[4]; self_dma_irq(self); } void DMA2_Stream6_IRQHandler(void) { self_data *self=&g_self[5]; self_dma_irq(self); } uart_init_export(uart1,init,deinit,set_irq,set_end_irq,read,write,0) uart_init_export(uart2,init,deinit,set_irq,set_end_irq,read,write,0) uart_init_export(uart3,init,deinit,set_irq,set_end_irq,read,write,0) uart_init_export(uart5,init,deinit,set_irq,set_end_irq,read,write,0) uart_init_export(uart6,init,deinit,set_irq,set_end_irq,read,write,0) uart_init_export(uart4,init,deinit,set_irq,set_end_irq,read,write_block,0)