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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值