用于使用循环(环形)缓冲区实现的嵌入式系统的 C 记录器库在主文件中不起作用
Posted
技术标签:
【中文标题】用于使用循环(环形)缓冲区实现的嵌入式系统的 C 记录器库在主文件中不起作用【英文标题】:Logger library in C for embedded system using circular(ring) buffer implementation isn't working in the main file 【发布时间】:2021-07-01 12:31:51 【问题描述】:所以,我正在尝试为我的嵌入式系统编写自己的记录器 API 库。嵌入式系统使用裸机编程,没有任何操作系统。因此,记录器库是一个静态库。该项目正在使用 CMake 构建。
记录器的第一个目标是将日志消息打印到控制台。它完成了。没有任何问题。它按预期工作。
项目的第二个目标是将日志消息保存到循环(环形)缓冲区。这是因为如果我的嵌入式设备未连接到计算机,我想使用循环(环形)缓冲区将这些日志消息存储在内存中,以便稍后在嵌入式设备连接到我的计算机时打印出来。这是我遇到麻烦的地方。
似乎当我尝试在 main.c 文件中对其进行测试时,控制台中没有从循环(环形)缓冲区的实现中打印出任何内容。
我对记录器库的意图是这样的。用户可以使用 main.c 中的任何字符串调用“log_print_buf”API,API 会将字符串保存到环形缓冲区。例如:log_print_buf(“为什么会出错”)。 我正在尝试同时使用可变参数 c 宏和环形缓冲区。但是,有人有更好的想法或建议吗?
我选择的循环(环形)缓冲区库来自 Embedded Artistry 网站。以下是 GitHub 上文章及其代码的链接:https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/
环形(环形)缓冲区 GitHub : https://github.com/embeddedartistry/embedded-resources/tree/master/examples/c/circular_buffer
任何建议都将受到欢迎和赞赏。谢谢
这是我的记录器实现代码:
------------- log.h ------
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <stdarg.h>
#include "cbuf.h"
int log_cbuf_init();
void log_print_cbuf(char *format, ...);
void log_read_cbuf();
#endif // __LOG_H_
-------- log.c -------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "log.h"
#include "cbuf.h"
#define MAX_CBUFFER_SIZE 512
#define MAX_LOGDATA_SIZE 128
cbuf_handle_t klog_cbuf;
int log_cbuf_init()
buffer = malloc(sizeof(uint8_t) *MAX_CBUFFER_SIZE);
klog_cbuf = circular_buf_init(buffer, MAX_CBUFFER_SIZE);
return 0;
void log_print_cbuf(char *format, ...)
char log_data[MAX_LOGDATA_SIZE];
va_list args;
va_start(args, format);
vsnprintf(log_data,MAX_LOGDATA_SIZE - 1, format, args);
va_end(args);
circular_buf_put(klog_cbuf, log_data[MAX_LOGDATA_SIZE - 1]);
return 0;
void log_read_cbuf()
uint8_t data;
while(!circular_buf_empty(klog_cbuf))
circular_buf_get(klog_cbuf, &data);
printf("%c", data);
--------- main.c -----
#include <stdio.h>
#include <stdlib.h>
#include <log.h>
#include "cbuf.h"
int main()
klog_cbuf_init();
log_print_cbuf("Hello World\n");
log_read_cbuf();
return 0;
------------- 结束----
【问题讨论】:
在没有任何操作系统的情况下使用裸机编程 - 但您使用的是malloc
。你有动态内存分配器的特定非操作系统实现吗?
哦,我不知道。那么,你不能在没有任何操作系统的情况下使用 malloc 吗? logger库的目标是STM32。目前,我只是使用 STM32 HAL 对所有外设进行编程。请原谅我的业余水平,因为我三个月前刚开始使用嵌入式编程和 C 语言
malloc
需要一些内存池用作“堆”和管理它的功能。托管程序为此使用操作系统服务。裸机程序没有这种奢侈,必须自己实现或根本不使用动态分配。
我明白了!非常感谢。在这种情况下,如果我根本不使用动态分配,那么您将如何实现环形缓冲区库来将日志消息存储到内存中?我知道我的嵌入式项目有直接内存访问和它自己的 RAM。
只定义一个静态缓冲区(如全局char buffer[MAX_CBUFFER_SIZE]
)
【参考方案1】:
我不熟悉这个循环缓冲区库。但是从circular_buf_put()
的原型来看,我觉得你用错了。
/// Put version 1 continues to add data if the buffer is full
/// Old data is overwritten
/// Requires: cbuf is valid and created by circular_buf_init
void circular_buf_put(cbuf_handle_t cbuf, uint8_t data);
似乎circular_buf_put()
一次记录一个字节。您的代码中的这一行仅将log_data
的一个字节放入缓冲区——它恰好是log_data
的最后一个字节。
circular_buf_put(klog_cbuf, log_data[MAX_LOGDATA_SIZE - 1]);
也许您应该像这样将log_data
的每个字节放入缓冲区。
int log_data_length = vsnprintf(log_data,MAX_LOGDATA_SIZE - 1, format, args);
for (int index = 0, ((index < log_data_length) && (index < MAX_LOGDATA_SIZE )), ++index)
circular_buf_put(klog_cbuf, log_data[index]);
【讨论】:
以上是关于用于使用循环(环形)缓冲区实现的嵌入式系统的 C 记录器库在主文件中不起作用的主要内容,如果未能解决你的问题,请参考以下文章