freeRTOS:基于(信号量+线程)的日志系统设计
1.日志的重要性
-
故障排查与调试:嵌入式系统通常运行在资源有限的环境中,故障排查和调试变得尤为复杂。日志系统可以记录系统在运行过程中的各种操作、状态和事件信息,方便开发人员追踪和定位问题所在。通过分析日志,可以快速找到故障源,并进行相应的修复和调试。
-
系统性能优化:嵌入式系统的资源有限,因此性能优化尤为关键。日志系统可以记录系统运行过程中的性能指标,如任务执行时间、资源利用率等。通过分析这些日志,可以发现系统性能瓶颈,进行性能优化和资源管理,提高系统的响应速度和资源利用效率。
-
资源监控与管理:嵌入式系统可能包含多个任务或模块并发运行,而每个任务和模块都可能占用不同的资源。日志系统可以记录各个任务和模块的资源使用情况,如内存分配情况、任务运行状态等。通过分析日志,可以进行资源的动态监控和管理,以确保嵌入式系统的稳定运行。
-
安全审计与故障恢复:嵌入式系统在一些关键领域,如工业控制、医疗设备等,安全性和可靠性要求很高。日志系统可以记录系统的操作行为、故障事件、安全事件等,方便进行安全审计和故障恢复。通过分析日志,可以快速发现安全漏洞和故障点,并采取相应的措施进行修复和恢复。
-
协助产品迭代和升级:通过收集和分析日志数据,可以了解用户的使用习惯、问题反馈和需求变化。这些信息可以用于产品的迭代和升级,提供更好的用户体验和功能优化。
2.代码设计
#ifndef _CJ_LOG_H_
#define _CJ_LOG_H_#include <stdbool.h>#define MAX_LOG_QUEUE_CNT 10typedef 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; //参数1unsigned char para2; //参数2unsigned char para3; //参数3unsigned char para4; //参数4int 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;}}elsebreak;}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;}elsereturn 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; //参数1unsigned char para2; //参数2unsigned char para3; //参数3unsigned char para4; //参数4int checkSum; //校验和
}CjLog;
相关文章:
freeRTOS:基于(信号量+线程)的日志系统设计
1.日志的重要性 故障排查与调试:嵌入式系统通常运行在资源有限的环境中,故障排查和调试变得尤为复杂。日志系统可以记录系统在运行过程中的各种操作、状态和事件信息,方便开发人员追踪和定位问题所在。通过分析日志,可以快速找到故…...

数据可视化(1)
使用python带的matplotlib库进行简单的绘图。使用之前先进行安装,pip install matplotlib。如果安装了Anaconda,则无需安装matplotlib。 1.简单折线图 #绘制简单图表 import matplotlib.pyplot as plt plt.plot([1,2,3,4,5]) plt.show() import matplotlib.pyp…...

Llama 2: Open Foundation and Fine-Tuned Chat Models
文章目录 TL;DRIntroduction背景本文方案 实现方式预训练预训练数据训练细节训练硬件支持预训练碳足迹 微调SFTSFT 训练细节 RLHF人类偏好数据收集奖励模型迭代式微调(RLHF)拒绝采样(Rejection Sampling)PPO多轮一致性的系统消息&…...
BTY-DNS AMA回顾:致力于创建Web3领域中的去中心化身份(DID)
传统域名系统 (DNS) 是一个分层的分散信息存储,用于将用户在网络浏览器中输入可读名称(例如www.baidu.com)解析为IP地址,来访问互联网上的计算机。传统域名系统存在一些例如过于集中化管理、效率并不高等局限性问题。而去中心化域…...

【设计模式——学习笔记】23种设计模式——装饰器模式Decorator(原理讲解+应用场景介绍+案例介绍+Java代码实现)
生活案例 咖啡厅 咖啡定制案例 在咖啡厅中,有多种不同类型的咖啡,客户在预定了咖啡之后,还可以选择添加不同的调料来调整咖啡的口味,当客户点了咖啡添加了不同的调料,咖啡的价格需要做出相应的改变。 要求ÿ…...

《golang设计模式》第一部分·创建型模式-01-单例模式(Singleton)
文章目录 1. 概述1.1 目的1.2 实现方式 2. 代码示例2.1 设计2.2 代码 1. 概述 1.1 目的 保证类只有一个实例有方法能让外部访问到该实例 1.2 实现方式 懒汉式 在第一次调用单例对象时创建该对象,这样可以避免不必要的资源浪费 饿汉式 在程序启动时就创建单例对象…...

若依微服务整合activiti7.1.0.M6
若依微服务3.6.3版本整合activiti7(7.1.0.M6) 目前有两种办法集成activiti7 放弃activiti7新版本封装的API,使用老版本的API,这种方式只需要直接集成即可,在7.1.0.M6版本中甚至不需要去除security的依赖。不多介绍&a…...
Ubuntu 下安装软件,卸载,查看已经安装的软件
参考网址:http://wiki.ubuntu.org.cn/UbuntuSkills 一般的安装程序用三种: .deb 和.rpm 这两种安装文件 .bundle 这是二进制的安装文件 而 tar.gz 这类的只是压缩包(相当于 .rar,.zip 压缩包一样),如果此类文件是程序的话&a…...

微信小程序导入微信地址
获取用户收货地址。调起用户编辑收货地址原生界面,并在编辑完成后返回用户选择的地址。 1:原生微信小程序接口使用API:wx.chooseAddress(OBJECT) wx.chooseAddress({success (res) {console.log(res.userName)console.log(res.postalCode)c…...
如何在Debian中配置代理服务器?
开始搭建代理服务器 首先我参考如下文章进行搭建代理服务器,步骤每一个命令都执行过报了各种错,找了博客 目前尚未开始,我已经知道我的路很长,很难走呀,加油,go!go!go! …...

在外远程NAS群晖Drive - 群晖Drive挂载电脑磁盘同步备份【无需公网IP】
文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…...
[SQL挖掘机] - 标量子查询
介绍: 标量子查询(Scalar Subquery)是一种特殊类型的子查询,它返回单个值作为结果,而不是结果集。标量子查询通常嵌套在另一个查询的选择列表、条件或表达式中,并提供单个值来完成计算、比较或作为查询结果的一部分。…...

MTK 进META的两种方式
1. Preloader进meta: 开机情况下:先发adb reboot meta进入Preloader,然后再进META 2. 开机后直接进meta...
AutoSAR系列讲解(实践篇)9.2-信息发送的Filter机制
再强调一遍哈,这几节的内容大家看不懂没关系。都属于不常用的知识,仅作了解,假如用到了可以再挖出来看看。还有一点,很多的英文不太好翻译,比如这里的Filter,翻译成滤波,筛选我感觉都不太贴切,干脆就直接叫Filter了,之后应该会出现类似的英文,博主尽量想办法让大家理…...

JVM详解(超详细)
目录 JVM 的简介 JVM 执行流程 JVM 运行时数据区 由五部分组成 JVM 的类加载机制 类加载的过程(五个) 双亲委派模型 类加载器 双亲委派模型的优点 JVM 中的垃圾回收策略 GC GC 中主要分成两个阶段 死亡对象的判断算法 引用计数算法 可达性分析算法 垃圾回收算…...

Vue学习Day3——生命周期\组件化
一、Vue生命周期 Vue生命周期:就是一个Vue实例从创建 到 销毁 的整个过程。 生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁 1.创建阶段:创建响应式数据 2.挂载阶段:渲染模板 3.更新阶段:修改数据,更…...

Rust vs Go:常用语法对比(八)
题目来自 Golang vs. Rust: Which Programming Language To Choose in 2023?[1] 141. Iterate in sequence over two lists Iterate in sequence over the elements of the list items1 then items2. For each iteration print the element. 依次迭代两个列表 依次迭代列表项1…...

pytorch学习-线性神经网络——softmax回归+损失函数+图片分类数据集
1.softmax回归 Softmax回归(Softmax Regression)是一种常见的多分类模型,可以用于将输入变量映射到多个类别的概率分布中。softmax回归是机器学习中非常重要并且经典的模型,虽然叫回归,实际上是一个分类问题 1.1分类与…...

Docker compose(容器编排)
Docker compose(容器编排) 一、安装Docker compose 1.安装Docker compose Docker Compose 环境安装 Docker Compose 是 Docker 的独立产品,因此需要安装 Docker 之后在单独安装 Docker Compose#下载 curl -L https://github.com/docker/co…...

xmind latex【记录备忘】
xmind latex 换行 换行必须要有\begin{align}和\end{align},此时再在里面用\才能换行,如果只写112\224是不能换行的...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...