Search code examples
cloggingembeddedstatic-librariescircular-buffer

Logger library in C for embedded system using circular(ring) buffer implementation isn't working in the main file


So, I am trying to write my own logger API library for my embedded system. The embedded system is using bare metal programming without any OS. Hence, the logger library is a static library. The project is being built using CMake.

The first goal of the logger is to print the log message to console. It is completed. No issues whatsoever. It is working as expected.

The second goal of the project is saving the log message to the circular(ring) buffer. This is because in case when my embedded device is not connected to the computer, I want to store those log messages in memory using circular(ring) buffer so that they can be printed out a later time when the embedded device connected to my computer. This is where I have trouble with.

It seems that when I tried to test it out in the main.c file nothing is being printed out in the console from the implementation of circular (ring) buffer.

My intention for the logger library is that. User can call the "log_print_buf" API with any string from the main.c and the API will save the string to the ring buffer. Ex: log_print_buf("why did this go wrong"). I'm trying to use the variadic c macros and ring buffer at the same time. But, anyone has a better idea or suggestions?

The circular(ring) buffer library I choose is from Embedded Artistry website. Here is a link to the article and their codes on GitHub: https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/

Circular(ring) buffer GitHub : https://github.com/embeddedartistry/embedded-resources/tree/master/examples/c/circular_buffer

Any suggestions would be greatly welcome and appreciated. Thank you

This is my logger implementation code:

------------- 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;
}

-------------- End ----------------


Solution

  • I'm not familiar with this circular buffer library. But judging from the prototype of circular_buf_put(), I think you are using it incorrectly.

    /// 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);
    

    It appears the circular_buf_put() logs one byte at a time. This line from your code puts only one byte of the log_data into the buffer -- it happens to be the last byte of the log_data.

    circular_buf_put(klog_cbuf, log_data[MAX_LOGDATA_SIZE - 1]);
    

    Maybe you should put every byte of the log_data into the buffer, like this.

    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]);
    }