Embed Toolkit

常用嵌入式数据结构生成器

一键生成环形缓冲区、简单状态机、软件定时器、发布订阅框架的 C 代码,直接复制到工程即可使用

需要一个 RX DMA 的环形缓冲区?选择 uint8_t + 容量 256 + 线程安全,立即得到 .h/.c 源码。

常用嵌入式数据结构生成器
选择数据结构类型,配置参数,右侧实时预览生成的 C 代码
my_buf.h
#ifndef MY_BUF_H
#define MY_BUF_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#define MY_BUF_CAPACITY 32u
#define MY_BUF_MASK     31u

/* Ring buffer storing a power-of-two number of elements. */
typedef struct {
    uint8_t data[MY_BUF_CAPACITY];
    volatile uint32_t head; /* write index */
    volatile uint32_t tail; /* read  index */
} my_buf_t;

void    my_buf_init(my_buf_t *rb);
bool    my_buf_push(my_buf_t *rb, uint8_t item);
bool    my_buf_pop (my_buf_t *rb, uint8_t *out);
bool    my_buf_peek(const my_buf_t *rb, uint8_t *out);
bool    my_buf_is_empty(const my_buf_t *rb);
bool    my_buf_is_full (const my_buf_t *rb);
uint32_t my_buf_size  (const my_buf_t *rb);

#endif /* MY_BUF_H */
my_buf.c
#include "my_buf.h"

/*
 * 本实现仅保证单写单读场景下的 ISR 安全:一个生产者 + 一个消费者
 *(典型如 UART RX ISR 推入、任务循环弹出)。
 *
 * 多写或多读场景必须改用 FreeRTOS StreamBuffer / MessageBuffer,
 * 或在 push/pop 外层加 Mutex 保护。head/tail 的 volatile 与内存序约束
 * 仅对 Cortex-M 的 strong memory model 成立。
 */

void my_buf_init(my_buf_t *rb) {
    rb->head = 0;
    rb->tail = 0;
}

bool my_buf_push(my_buf_t *rb, uint8_t item) {
    uint32_t next = (rb->head + 1u) & MY_BUF_MASK;
    if (next == rb->tail) {
        return false; /* full */
    }
    rb->data[rb->head & MY_BUF_MASK] = item;
    rb->head = next;
    return true;
}

bool my_buf_pop(my_buf_t *rb, uint8_t *out) {
    if (rb->head == rb->tail) {
        return false; /* empty */
    }
    *out = rb->data[rb->tail & MY_BUF_MASK];
    rb->tail = (rb->tail + 1u) & MY_BUF_MASK;
    return true;
}

bool my_buf_peek(const my_buf_t *rb, uint8_t *out) {
    if (rb->head == rb->tail) {
        return false;
    }
    *out = rb->data[rb->tail & MY_BUF_MASK];
    return true;
}

bool my_buf_is_empty(const my_buf_t *rb) {
    return rb->head == rb->tail;
}

bool my_buf_is_full(const my_buf_t *rb) {
    return ((rb->head + 1u) & MY_BUF_MASK) == rb->tail;
}

uint32_t my_buf_size(const my_buf_t *rb) {
    return (rb->head - rb->tail) & MY_BUF_MASK;
}