stm32 HAL库 DMA + IDLE
摘要
为啥还写stm32 HAL库 DMA + IDLE呢?主要是网上已经充斥大量的DMA + IDLE的内容了,但是都会停止DMA进行操作的。
以下使用kfifo的改版,在空闲中断,把DMA当前的位置传进环形队列中。
stm32CubeMx 设置
使能串口2DMA,并且开空闲中断
使能注册回调函数功能
源码
初始化
#define RX_BUF_LEN 1024
#define RING_BUF_LEN 128
volatile uint8_t rx_buf[RX_BUF_LEN+1]={0};
volatile struct hgfifo_item hgfifobuf[RING_BUF_LEN+1]={0};
volatile struct hgfifo hgfifop;
// 回调
void uart_callback(UART_HandleTypeDef *huart, uint16_t Size)
{
static int16_t val = 0;
struct hgfifo_item rxval = {0};
rxval.tail = RX_BUF_LEN - huart->hdmarx->Instance->CNDTR;//剩下长度
rxval.head = val;//剩下长度
val = rxval.tail;
hgfifo_in((struct hgfifo*)&hgfifop,&rxval);
}
// 初始化
void My_UART_Init(void)
{
// 其 大小必须为 2 的 N 次方
hgfifo_init((struct hgfifo*)&hgfifop,(struct hgfifo_item *)hgfifobuf,RING_BUF_LEN);
HAL_UART_RegisterRxEventCallback(&huart2,uart_callback);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,(uint8_t *)rx_buf,RX_BUF_LEN);
}
int maint ()
{
if(!hgfifo_is_empty((struct hgfifo*)&hgfifop))
{
struct hgfifo_item rxval = {0};
hgfifo_out((struct hgfifo*)&hgfifop,&rxval);
// 不能操作 hgfifop 中的 in out, 会变
char arr[100] ={0};
if(rxval.tail >= rxval.head)
{
memcpy(arr,(uint8_t*)rx_buf + rxval.head,rxval.tail - rxval.head);
}
else
{
int16_t len = RX_BUF_LEN - rxval.head;
memcpy(arr,(uint8_t*)rx_buf + rxval.head,len);
memcpy(arr+len,(uint8_t*)rx_buf,rxval.tail);
}
}
}
改造的kfifo
//
// Created by HG10 on 2023/3/10.
//
#include "hgfifo.h"
#include <string.h>
#define min(a,b) ((a)<(b)?(a):(b))
/* is x a power of 2? */
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
/**
* kfifo_init - initialize a FIFO using a preallocated buffer
* @fifo: the fifo to assign the buffer
* @buffer: the preallocated buffer to be used.
* @size: the size of the internal buffer, this has to be a power of 2.
*
*/
void hgfifo_init(struct hgfifo *fifo, struct hgfifo_item *buffer, unsigned int size)
{
/* TODO: size must be a power of 2? */
fifo->buffer = buffer;
fifo->size = size;
hgfifo_reset(fifo);
}
/**
* kfifo_in - puts some data into the FIFO
* @fifo: the fifo to be used.
* @from: the data to be added.
* @len: the length of the data to be added.
*
* This function copies at most @len bytes from the @from buffer into
* the FIFO depending on the free space, and returns the number of
* bytes copied.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these functions.
*/
unsigned int hgfifo_in(struct hgfifo *fifo, const struct hgfifo_item *from)
{
/*
* 前面讲到fifo->size已经2的次幂圆整,主要是方便这里计算,提升效率
* 在对10进行求余的时候,我们发现,余数总是整数中的个位上的数字,而不用管其他位是什么;
* 所以,kfifo->in % kfifo->size 可以转化为 kfifo->in & (kfifo->size – 1),效率会提升
* 所以fifo->size - (fifo->in & (fifo->size - L)) 即位 fifo->in 到 buffer末尾所剩余的长度,
* L取len和剩余长度的最小值,即为需要拷贝L 字节到fifo->buffer + fifo->in的位置上。
*/
// L = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
unsigned int len = min(hgfifo_avail(fifo), 1);
fifo->buffer[fifo->in & (fifo->size - 1)] = *from;
fifo->in ++;
return len;
}
/**
* kfifo_out - gets some data from the FIFO
* @fifo: the fifo to be used.
* @to: where the data must be copied.
* @len: the size of the destination buffer.
*
* This function copies at most @len bytes from the FIFO into the
* @to buffer and returns the number of copied bytes.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these functions.
*/
unsigned int hgfifo_out(struct hgfifo *fifo, struct hgfifo_item *to)
{
//len = min(len, fifo->in - fifo->out);
unsigned int len = min(hgfifo_len(fifo), 1);
*to = fifo->buffer[fifo->out & (fifo->size - 1)];
fifo->out ++;
return len;
}
//
// Created by HG10 on 2023/3/10.
//
#ifndef PROJECT_HGFIFO_H
#define PROJECT_HGFIFO_H
#include <stddef.h>
struct hgfifo_item{
unsigned int head;
unsigned int tail;
// void * data;
};
struct hgfifo {
struct hgfifo_item *buffer; /* the buffer holding the data */
unsigned int size; /* the size of the allocated buffer */
unsigned int in; /* data is added at offset (in % size) */
unsigned int out; /* data is extracted from off. (out % size) */
};
/*
* Macros for declaration and initialization of the hgfifo datatype
*/
extern void hgfifo_init(struct hgfifo *fifo, struct hgfifo_item *buffer,
unsigned int size);
extern unsigned int hgfifo_in(struct hgfifo *fifo,
const struct hgfifo_item *from);
extern unsigned int hgfifo_out(struct hgfifo *fifo,
struct hgfifo_item *to);
/**
* hgfifo_initialized - Check if hgfifo is initialized.
* @fifo: fifo to check
* Return %true if FIFO is initialized, otherwise %false.
* Assumes the fifo was 0 before.
*/
static inline int hgfifo_initialized(struct hgfifo *fifo)
{
return fifo->buffer != NULL;
}
/**
* hgfifo_reset - removes the entire FIFO contents
* @fifo: the fifo to be emptied.
*/
static inline void hgfifo_reset(struct hgfifo *fifo)
{
fifo->in = fifo->out = 0;
}
/**
* hgfifo_reset_out - skip FIFO contents
* @fifo: the fifo to be emptied.
*/
static inline void hgfifo_reset_out(struct hgfifo *fifo)
{
fifo->out = fifo->in;
}
/**
* hgfifo_size - returns the size of the fifo in bytes
* @fifo: the fifo to be used.
*/
static inline unsigned int hgfifo_size(struct hgfifo *fifo)
{
return fifo->size;
}
/**
* hgfifo_len - returns the number of used bytes in the FIFO
* @fifo: the fifo to be used.
*/
static inline unsigned int hgfifo_len(struct hgfifo *fifo)
{
register unsigned int out;
out = fifo->out;
return fifo->in - out;
}
/**
* hgfifo_is_empty - returns true if the fifo is empty
* @fifo: the fifo to be used.
*/
static inline int hgfifo_is_empty(struct hgfifo *fifo)
{
return fifo->in == fifo->out;
}
/**
* hgfifo_is_full - returns true if the fifo is full
* @fifo: the fifo to be used.
*/
static inline int hgfifo_is_full(struct hgfifo *fifo)
{
return hgfifo_len(fifo) == hgfifo_size(fifo);
}
/**
* hgfifo_avail - returns the number of bytes available in the FIFO
* @fifo: the fifo to be used.
*/
static inline unsigned int hgfifo_avail(struct hgfifo *fifo)
{
return hgfifo_size(fifo) - hgfifo_len(fifo);
}
extern void hgfifo_skip(struct hgfifo *fifo, unsigned int len);
/*
* __hgfifo_add_out internal helper function for updating the out offset
*/
static inline void __hgfifo_add_out(struct hgfifo *fifo,
unsigned int off)
{
fifo->out += off;
}
/*
* __hgfifo_add_in internal helper function for updating the in offset
*/
static inline void __hgfifo_add_in(struct hgfifo *fifo,
unsigned int off)
{
fifo->in += off;
}
/*
* __hgfifo_off internal helper function for calculating the index of a
* given offeset
*/
static inline unsigned int __hgfifo_off(struct hgfifo *fifo, unsigned int off)
{
return off & (fifo->size - 1);
}
#endif //PROJECT_KFIFO_H