用于使用循环(环形)缓冲区实现的嵌入式系统的 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 记录器库在主文件中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何优雅地实现环形缓冲区?

优雅地用宏实现环形缓冲区

优雅地用宏实现环形缓冲区

优雅地用宏实现环形缓冲区

C语言实现环形队列的原理和方法

C语言实现环形队列的原理和方法