- //PC10 TX4 DMA1.4.4
- //PC11 RX4 DMA1.2.4
- DMA_TX_IRQH_INIT_FUNC(UART4, 1,4,4);
- DMA_RX_INIT_FUNC(UART4, 1,2,4);
- UART_INIT(uart_xxx, UART4, GPIOC, 11, 1024, GPIOC, 10, 1024, 1);
调用样例
- uart_xxx->init(57600);
- uart_xxx->read(............
头文件
- #ifndef _UART_DMA_H_
- #define _UART_DMA_H_
- typedef const struct
- {
- u32 (*write_space)();
- u32 (*read_valid_len)();
- bool (*read)(u8 *ptr);
- u32 (*reads)(u8 *ptr, u32 len);
- bool (*write)(u8 data);
- u32 (*writes)(const u8 *ptr, u32 len);
- void (*init)(u32 bps);
- }UART_OPS;
- extern const UART_OPS *uart_xxx;
- extern const UART_OPS *uart_yyy;
- extern const UART_OPS *uart_zzz;
- #endif
C文件- typedef struct _fifo
- {
- u32 size; /* the size of the allocated buffer */
- u32 in; /* data is added at offset (in % size) */
- u32 out; /* data is extracted from off. (out % size) */
- u8 *buffer; /* the buffer holding the data */
- }FIFO;
- uint32_t is2n(uint32_t un)
- {
- return un&(un-1);
- }
- uint32_t max2n(uint32_t un)
- {
- //下面的函数返回不大于un的2的最大幂
- uint32_t mi = is2n(un);
- return mi?max2n(mi):un;
- }
- static void fifo_init(FIFO *fifo, u8 *buff, u32 size)
- {
- if (!is2n(size))
- {
- size = max2n(size);
- }
- fifo->size = size;
- fifo->in = fifo->out = 0;
- fifo->buffer = buff;
- }
- static u32 kfifo_put(FIFO *fifo, const u8 *buffer, u32 len)
- {
- u32 l;
- len = min(len, fifo->size - fifo->in + fifo->out); //剩余空间
- l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); //从in到fifo尾剩余空间
- memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
- memcpy(fifo->buffer, buffer + l, len - l);
- fifo->in += len;
- return len;
- }
- static u32 kfifo_get(FIFO *fifo, u8 *buffer, u32 len)
- {
- u32 l;
- len = min(len, fifo->in - fifo->out); //数据长度
- l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); //out到fifo尾数据长度
- memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); //先拷队尾
- memcpy(buffer + l, fifo->buffer, len - l); //再拷前面
- fifo->out += len;
- return len;
- }
- //tx fifo
- static u32 txfifo_put(FIFO *fifo, const u8 *buffer, u32 len)
- {
- u32 l;
- len = min(len, fifo->size - fifo->in + fifo->out);
- l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
- memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
- memcpy(fifo->buffer, buffer + l, len - l);
- fifo->in += len;
- return len;
- }
- static u32 txfifo_dma_get_valid(FIFO *fifo, u8 **pptr, u32 *plen)
- {
- u32 len;
- len = min((fifo->in - fifo->out),
- fifo->size - (fifo->out & (fifo->size - 1)));
- *pptr = fifo->buffer + (fifo->out & (fifo->size - 1));
- *plen = len;
- fifo->out += len;
- return len;
- }
- static u32 txfifo_write_space(FIFO *fifo)
- {
- s32 valid_len;
- valid_len = (fifo->in - fifo->out);
- if (valid_len >= 0)
- return fifo->size - valid_len;
- else
- return fifo->size;
- }
- //rx fifo
- static u32 rxfifo_get_valid_len(FIFO *fifo, u32 dma_ndtr)
- {
- s32 valid_len;
- valid_len = (fifo->size - dma_ndtr) - (fifo->out & (fifo->size - 1));
- if (valid_len < 0)
- valid_len += fifo->size;
- return valid_len;
- }
- static u32 rxfifo_get(FIFO *fifo, u32 dma_ndtr, u8 *buffer, u32 len)
- {
- u32 l;
- len = min(len, rxfifo_get_valid_len(fifo, dma_ndtr));
- l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
- memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
- memcpy(buffer + l, fifo->buffer, len - l);
- fifo->out += len;
- return len;
- }
- typedef struct _UART_CONTEXT{
- USART_TypeDef *uart_type;
- FIFO *fifo_rx;
- FIFO *fifo_tx;
- DMA_Stream_TypeDef *dma_tx;
- DMA_Stream_TypeDef *dma_rx;
- }UART_CONTEXT;
- static u32 uart_write_space(UART_CONTEXT *context)
- {
- return txfifo_write_space(context->fifo_tx);
- }
- static u32 uart_read_valid_len(UART_CONTEXT *context)
- {
- return rxfifo_get_valid_len(context->fifo_rx, context->dma_rx->NDTR);
- }
- static bool uart_read(UART_CONTEXT *context, u8 *ptr)
- {
- return (1 == rxfifo_get(context->fifo_rx, context->dma_rx->NDTR, ptr, 1));
- }
- static u32 uart_reads(UART_CONTEXT *context, u8 *ptr, u32 len)
- {
- return rxfifo_get(context->fifo_rx, context->dma_rx->NDTR, ptr, len);
- }
- static void uart_tx_try_start_dma(UART_CONTEXT *context, DMA_Stream_TypeDef *dma_stream_tx)
- {
- u8 *memptr;
- u32 len;
- txfifo_dma_get_valid(context->fifo_tx, &memptr, &len);
- if ((len > 0) && ((dma_stream_tx->CR & (uint32_t)DMA_SxCR_EN) == 0))
- {
- dma_stream_tx->M0AR = (u32)memptr;
- dma_stream_tx->NDTR = len;
- dma_stream_tx->CR |= (uint32_t)DMA_SxCR_EN;
- }
- }
- static bool uart_write(UART_CONTEXT *context, u8 data)
- {
- bool result;
- result = (1 == txfifo_put(context->fifo_tx, &data, 1));
- uart_tx_try_start_dma(context, context->dma_tx);
- return result;
- }
- static u32 uart_writes(UART_CONTEXT *context, const u8 *ptr, u32 len)
- {
- u32 txed_len;
- txed_len = txfifo_put(context->fifo_tx, ptr, len);
- uart_tx_try_start_dma(context, context->dma_tx);
- return txed_len;
- }
- static void uart_txdma_tc_callback(UART_CONTEXT *context, USART_TypeDef *uart_type, DMA_Stream_TypeDef *dma_stream_tx)
- {
- u8 *memptr;
- u32 len;
- txfifo_dma_get_valid(context->fifo_tx, &memptr, &len);
- if (len > 0)
- {
- dma_stream_tx->M0AR = (u32)memptr;
- dma_stream_tx->NDTR = len;
- dma_stream_tx->CR |= (uint32_t)DMA_SxCR_EN;
- }
- }
- #define DMA_TX_IRQH_INIT_FUNC(uart, dma, stream, channel) \
- void DMA##dma##_Stream##stream##_IRQHandler(void) \
- { \
- extern UART_CONTEXT struct_##uart; \
- if (DMA_GetFlagStatus(DMA##dma##_Stream##stream, DMA_FLAG_TCIF##stream) != RESET) \
- { \
- DMA_ClearFlag(DMA##dma##_Stream##stream, DMA_FLAG_TCIF##stream); \
- uart_txdma_tc_callback(&struct_##uart, uart, DMA##dma##_Stream##stream); \
- } \
- } \
- \
- static void uart##_TXDMA_init(u32 memory_addr, u32 memory_size, u8 priority) \
- { \
- extern UART_CONTEXT struct_##uart; \
- NVIC_InitTypeDef NVIC_InitStructure; \
- DMA_InitTypeDef DMA_InitStructure; \
- \
- struct_##uart.dma_tx = DMA##dma##_Stream##stream; \
- \
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA##dma, ENABLE); \
- \
- DMA_Cmd(DMA##dma##_Stream##stream, DISABLE); \
- \
- DMA_DeInit(DMA##dma##_Stream##stream); \
- \
- DMA_InitStructure.DMA_Channel = DMA_Channel_##channel; \
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(uart##->DR)); \
- DMA_InitStructure.DMA_Memory0BaseAddr = memory_addr; \
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; \
- DMA_InitStructure.DMA_BufferSize = (uint32_t)memory_size; \
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; \
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; \
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; \
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; \
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; \
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; \
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; \
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; \
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; \
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; \
- DMA_Init(DMA##dma##_Stream##stream, &DMA_InitStructure); \
- \
- DMA_ClearFlag(DMA##dma##_Stream##stream, DMA_FLAG_TCIF##stream); \
- DMA_ITConfig(DMA##dma##_Stream##stream, DMA_IT_TC, ENABLE); \
- \
- NVIC_InitStructure.NVIC_IRQChannel = DMA##dma##_Stream##stream##_IRQn; \
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = priority >> 4; \
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = priority & 0x0F; \
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; \
- NVIC_Init(&NVIC_InitStructure); \
- \
- DMA_Cmd(DMA##dma##_Stream##stream, DISABLE); \
- }
- #define DMA_RX_INIT_FUNC(uart, dma, stream, channel) \
- static void uart##_RXDMA_init(u32 memory_addr, u32 memory_size) \
- { \
- extern UART_CONTEXT struct_##uart; \
- DMA_InitTypeDef DMA_InitStructure; \
- \
- struct_##uart.dma_rx = DMA##dma##_Stream##stream; \
- \
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA##dma, ENABLE); \
- \
- DMA_Cmd(DMA##dma##_Stream##stream, DISABLE); \
- \
- DMA_DeInit(DMA##dma##_Stream##stream); \
- \
- DMA_InitStructure.DMA_Channel = DMA_Channel_##channel; \
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(uart##->DR)); \
- DMA_InitStructure.DMA_Memory0BaseAddr = memory_addr; \
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; \
- DMA_InitStructure.DMA_BufferSize = memory_size; \
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; \
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; \
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; \
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; \
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; \
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; \
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; \
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; \
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; \
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; \
- DMA_Init(DMA##dma##_Stream##stream, &DMA_InitStructure); \
- DMA_Cmd(DMA##dma##_Stream##stream, ENABLE); \
- }
- #define UART_INIT(ops_ptr, uart, gpio_rx, pin_rx, fifosize_rx, gpio_tx, pin_tx, fifosize_tx, tx_dma_irq_priority) \
- static UART_CONTEXT struct_##uart = {.uart_type = uart, }; \
- static void _##uart##_init(u32 bps) \
- { \
- USART_InitTypeDef USART_InitStructure; \
- GPIO_InitTypeDef GPIO_InitStructure; \
- \
- static FIFO rxfifo, txfifo; \
- static u8 rxbuff[fifosize_rx], txbuff[fifosize_tx]; \
- \
- fifo_init(&rxfifo, rxbuff, fifosize_rx); \
- struct_##uart.fifo_rx = &rxfifo; \
- fifo_init(&txfifo, txbuff, fifosize_tx); \
- struct_##uart.fifo_tx = &txfifo; \
- \
- GPIO_PinAFConfig(gpio_tx, GPIO_PinSource##pin_tx, GPIO_AF_##uart); \
- \
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; \
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; \
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; \
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##pin_tx; \
- GPIO_Init(gpio_tx, &GPIO_InitStructure); \
- \
- GPIO_PinAFConfig(gpio_rx, GPIO_PinSource##pin_rx, GPIO_AF_##uart); \
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##pin_rx; \
- GPIO_Init(gpio_rx, &GPIO_InitStructure); \
- \
- USART_InitStructure.USART_BaudRate = bps; \
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; \
- USART_InitStructure.USART_StopBits = USART_StopBits_1; \
- USART_InitStructure.USART_Parity = USART_Parity_No; \
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; \
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; \
- USART_Init(uart, &USART_InitStructure); \
- \
- USART_DMACmd(uart, USART_DMAReq_Tx, ENABLE); \
- USART_DMACmd(uart, USART_DMAReq_Rx, ENABLE); \
- USART_Cmd(uart, ENABLE); \
- uart##_RXDMA_init((u32)(rxfifo.buffer), fifosize_rx); \
- uart##_TXDMA_init((u32)(txfifo.buffer), fifosize_tx, tx_dma_irq_priority); \
- } \
- \
- static u32 _##uart##_write_space(){return uart_write_space(&struct_##uart);} \
- static u32 _##uart##_read_valid_len(){return uart_read_valid_len(&struct_##uart);} \
- static bool _##uart##_read(u8 *ptr){return uart_read(&struct_##uart, ptr);} \
- static u32 _##uart##_reads(u8 *ptr, u32 len){return uart_reads(&struct_##uart, ptr, len);} \
- static bool _##uart##_write(u8 data){return uart_write(&struct_##uart, data);} \
- static u32 _##uart##_writes(const u8 *ptr, u32 len){return uart_writes(&struct_##uart, ptr, len);} \
- static UART_OPS _##uart##ops={ \
- .write_space = _##uart##_write_space, \
- .read_valid_len = _##uart##_read_valid_len, \
- .read = _##uart##_read, \
- .reads = _##uart##_reads, \
- .write = _##uart##_write, \
- .writes = _##uart##_writes, \
- .init = _##uart##_init}; \
- const UART_OPS *ops_ptr = &_##uart##ops;