freeRTOS:基于(队列+线程)的日志系统设计

1.日志的重要性

  1. 故障排查与调试:嵌入式系统通常运行在资源有限的环境中,故障排查和调试变得尤为复杂。日志系统可以记录系统在运行过程中的各种操作、状态和事件信息,方便开发人员追踪和定位问题所在。通过分析日志,可以快速找到故障源,并进行相应的修复和调试。

  2. 系统性能优化:嵌入式系统的资源有限,因此性能优化尤为关键。日志系统可以记录系统运行过程中的性能指标,如任务执行时间、资源利用率等。通过分析这些日志,可以发现系统性能瓶颈,进行性能优化和资源管理,提高系统的响应速度和资源利用效率。

  3. 资源监控与管理:嵌入式系统可能包含多个任务或模块并发运行,而每个任务和模块都可能占用不同的资源。日志系统可以记录各个任务和模块的资源使用情况,如内存分配情况、任务运行状态等。通过分析日志,可以进行资源的动态监控和管理,以确保嵌入式系统的稳定运行。

  4. 安全审计与故障恢复:嵌入式系统在一些关键领域,如工业控制、医疗设备等,安全性和可靠性要求很高。日志系统可以记录系统的操作行为、故障事件、安全事件等,方便进行安全审计和故障恢复。通过分析日志,可以快速发现安全漏洞和故障点,并采取相应的措施进行修复和恢复。

  5. 协助产品迭代和升级:通过收集和分析日志数据,可以了解用户的使用习惯、问题反馈和需求变化。这些信息可以用于产品的迭代和升级,提供更好的用户体验和功能优化。

2.代码设计 

#ifndef _CJ_LOG_H_
#define _CJ_LOG_H_

#include <stdbool.h>

#define MAX_LOG_QUEUE_CNT 10

typedef enum _LogType
{
   LT_DEBUG   = 0,
   LT_INFO    = 1,
   LT_WARNING = 2,
   LT_ERROR   = 3,
}LogType;

typedef struct _CjLog
{
    unsigned int timestamp;      //时间戳
    LogType type;                //类别
    unsigned char para1;         //参数1
    unsigned char para2;         //参数2
    unsigned char para3;         //参数3
    unsigned char para4;         //参数4
    int checkSum;                //校验和
}CjLog;

void clog_Init();
int clog_addlog(CjLog *log);
int clog_getLog(unsigned int startTime, unsigned int endTime, unsigned char *buf);
bool clog_getLog(unsigned int index, unsigned char *buf);
int clog_getCnt();
void clog_clear();

#endif
#include "cjlog.h"
#include "freertos/queue.h"

/* 创建一个日志队列 */
static QueueHandle_t log_queue;

static void clog_write_thread(void)
{
	uart_event_t event;
    CjLog receivedLog;
	int len = 0;
	printf("clog_write_thread start !\n");
	while (1)
	{
        BaseType_t xStatus = xQueueReceive(log_queue, &receivedLog, portMAX_DELAY);
        if (xStatus == pdPASS) 
        {
            printf("Get a new log!\n");
            /* 写日志函数(需校验checkSum) 具体根据实际平台去实现 */
            if(flash_writeLog(receivedLog) == false)
                printf("Write log failed!\n");
        } 
        else 
        {
        
        }
	}
	return;
}

void clog_Init()
{
    log_queue = xQueueCreate(MAX_LOG_QUEUE_CNT, sizeof(CjLog));

    /* 创建一个接收线程 */
	xTaskCreate(clog_write_thread, "log_thread", 2048, NULL, configMAX_PRIORITIES, NULL);
}


void clog_addlog(CjLog *log)
{
   xQueueSend(log_queue, &log, portMAX_DELAY);
}

int clog_getLog(unsigned int startTime, unsigned int endTime, unsigned char *buf)
{
    if(endTime == 0)
        endTime = 0xffffffff;

    /* 读取当前日志数量 具体根据实际平台去实现 */
    const int logCount = readLogCnt();
    int cnt = 0;
    
    //从最新的日志扫描至最旧的
    for(int i = 0; i < logCount; i++)
    {
        /* 读取当前日志 也需要根据平台去实现 */
        CjLog *log = flash_readLog(i);
        if(log)
        {
            if(log->timestamp <= endTime && log->timestamp >= startTime)
            {
                *buf++ = (unsigned char)(log->timestamp >> 24);
                *buf++ = (unsigned char)(log->timestamp >> 16);
                *buf++ = (unsigned char)(log->timestamp >> 8);
                *buf++ = (unsigned char)(log->timestamp);
                *buf++ = (unsigned char)log->type;
                *buf++ = log->para1;
                *buf++ = log->para2;
                *buf++ = log->para3;
                *buf++ = log->para4;
                cnt ++;
            }
            else
            {
                if(log->timestamp < startTime)   
                    break;
            }
        }
        else
            break;
    }

    return cnt;
}

bool clog_getLog(unsigned int index, unsigned char *buf)
{
    /* 读取当前日志数量 具体根据实际平台去实现 */
    const int logCount = flash_readLogCnt();
    if(index > logCount)
    {
        return false;
    }

    /* 读取当前日志 也需要根据平台去实现 */
    CjLog *log = flash_readLog(index);
    if(log)
    {
        *buf++ = (unsigned char)(log->timestamp >> 24);
        *buf++ = (unsigned char)(log->timestamp >> 16);
        *buf++ = (unsigned char)(log->timestamp >> 8);
        *buf++ = (unsigned char)(log->timestamp);
        *buf++ = (unsigned char)log->type;
        *buf++ = log->para1;
        *buf++ = log->para2;
        *buf++ = log->para3;
        *buf++ = log->para4;
        return true;
    }
    else
        return false;

}

int clog_getCnt()
{
    /* 读取当前日志数量 具体根据实际平台去实现 */
    return flash_readLogCnt();
}

void clog_clear()
{
     /* 清空也需要根据平台去实现 */
     flash_clearAllLog();
}

3.注意事项

1.与flash有关的函数的实现需要与实际情况结合。

2.flash读的时候要进行校验。

3.日志结构体可以根据实际的flash芯片设计大小,字节对齐等。

/* 4字节对齐 这里刚好是 4个 4字节 */
typedef struct _CjLog
{
    unsigned int timestamp;      //时间戳
    LogType type;                //类别
    unsigned char para1;         //参数1
    unsigned char para2;         //参数2
    unsigned char para3;         //参数3
    unsigned char para4;         //参数4
    int checkSum;                //校验和
}CjLog;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于FreeRTOS操作系统的stm32F103C8T6项目可以实现多任务并发运行。FreeRTOS是一个小巧、可裁剪的RTOS系统,具有以下特点: 1. 内核支持抢占式、合作式和时间片调度,可以根据任务的优先级来决定下一刻应该运行哪个任务。 2. 提供了一个用于低功耗的Tickless模式,可以有效节省能源。 3. 支持动态或静态RAM,可以根据需要选择创建任务、消息队列、信号量、软件定时器等组件时使用的内存类型。 4. 已经在超过30种架构的芯片上进行了移植,包括stm32F103系列。 5. FreeRTOS系统简单、小巧、易用,通常情况下内核占用4k-9k字节的空间。 6. 支持实时任务和协程,任务与任务、任务与中断之间可以使用任务通知、消息队列、信号量等进行通信和同步。 7. 具有优先级继承特性的互斥信号量,高效的软件定时器,强大的跟踪执行功能和堆栈溢出检测功能。 8. 任务数量和优先级没有限制,可以根据项目需求创建任意数量和优先级的任务。 因此,基于FreeRTOS操作系统的stm32F103C8T6项目可以充分利用该RTOS系统的特点,实现多任务并发运行,提高系统的实时性和可靠性。 #### 引用[.reference_title] - *1* [stm32F103C8T6基于FreeRTOS操作系统的多任务(STM32CUBEMX)](https://blog.csdn.net/Mouer__/article/details/121616118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [stm32F103C8T6基于FreeRTOS操作系统的多任务](https://blog.csdn.net/weixin_46129506/article/details/121659483)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值