单片机log日志方案

这里简单记录一个单片机log日志方案:
该日志是记录在外部SPI的flash的,该方案任存在使用的bug,但是做日志的循环记录是足够了。
(1)这里需要了解的SPI flash 使用次数为10W次,该日志目标是错误日志。
(2)日志信息循环擦写的,但是索引不是,这个地方可以自己优化一下。

// 文件索引块结构(24字节)
typedef struct  _file_block {
//用来记录扇区信息,先扇区定位
uint32_t  file_block_base;        // 起始扇区编号 相当于基地址
uint32_t  file_block_start;       // 起始扇区编号 循环记录的头
uint32_t  file_block_end;         // 结束扇区编号 循环记录的尾
uint32_t  file_block_size;        // 扇区数量     可用扇区的数量
uint32_t  file_block_used_size;   // 扇区占用数量 已经使用的扇区数量
//每个扇区进行数据包定位	
uint32_t  file_pack_end;          // 存储的结束
uint32_t  file_pack_size;         // 存储区的字节数字
uint32_t  first_init_flag;        // 做初始化符号
} FileBlock;
#ifndef _FILESYS_H_
#define _FILESYS_H_
#include "main.h"

#define LOG_flash_message_addr    (2 * 1024 * 1024)
#define LOG_flash_addr_end        (5 * 1024 * 1024)
#define LOG_flash_addr_start      (LOG_flash_message_addr+(4*1024))
#define LOG_flash_size            ( (LOG_flash_addr_end - LOG_flash_message_addr ) - (4*1024) )

#define FLASH_MIN_SIZE            4096
#define LOGG_MIN_SIZE             64

// 文件索引块结构(24字节)
typedef struct  _file_block {
uint32_t  file_block_base;        // 起始扇区编号
uint32_t  file_block_start;       // 起始扇区编号
uint32_t  file_block_end;         // 结束扇区编号
uint32_t  file_block_size;        // 扇区数量
uint32_t  file_block_used_size;   // 扇区占用数量
//  4096/64 =64 个空间存放字符串	
uint32_t  file_pack_end;          // 存储的结束
uint32_t  file_pack_size;         // 存储区的字节数字
	
uint32_t  first_init_flag;
} FileBlock;

void init_flash_log(void);
void read_file_log( void );
void clear_file_log( void );
void write_file_log(char* string);
int Flash_LOG_printf( const char *cmd_expr, ...);
#endif
#include "flash_log.h"
#include "log.h"
#include "usr_cfg.h"
uint8_t flash_log_temp[4096]={0};//flash 数据的暂存区
FileBlock  file_block;
uint8_t file_log_is_on=0;


void read_index_message(void)
{
		flash_read_page(LOG_flash_message_addr,flash_log_temp,4096);//读索引地址
	    memcpy((uint8_t *) &file_block,flash_log_temp,sizeof(file_block));
	    if(file_block.first_init_flag !=0x12345678)
		{
		 file_block.file_block_base=LOG_flash_addr_start/4096;  //(起始的偏移编号)	 
		 file_block.file_block_start=0;  //存放消息循环队列的首                       
		 file_block.file_block_end=0;    //存放消息循环队列的尾
		 file_block.file_block_size=(LOG_flash_size)/FLASH_MIN_SIZE; //存放消息循环队列包含的块个数
		 file_block.file_block_used_size=0;//存放消息循环队列使用块的个数
		 	
		 file_block.file_pack_end=0; //每个块尾部可写的位置  //尾部指向下一个可以写的地方
		 file_block.file_pack_size=FLASH_MIN_SIZE /LOGG_MIN_SIZE;//4096/64=64条
		 
		 file_block.first_init_flag=0x12345678;
		 memcpy(flash_log_temp,(uint8_t *) &file_block,sizeof(file_block));	
		 flash_write_page(LOG_flash_message_addr,flash_log_temp,sizeof(file_block));
		 flash_read_page(LOG_flash_message_addr,flash_log_temp,4096);
		 }
}

//获取block 如果满了就删除 delet_num 个扇区
//带回扇区编号
int get_malloc_block(void)
{
	int delet_block=0;
	if(file_block.file_block_used_size >= ( file_block.file_block_size )  )//接近满时候 删除起始的扇区
	{  
	     //删除报文首地址所在的扇区,注意报文的开始一定是扇区的首地址,但是报文的尾随便。
		 delet_block = (  file_block.file_block_base ) +(file_block.file_block_start);
		 flash_EraseSector(delet_block);	
         file_block.file_block_start= (file_block.file_block_start+1)%file_block.file_block_size;
		 file_block.file_block_used_size--;
	}
	return 0;
}


void open_log_function(void)
{
  if(file_log_is_on==0)
  {
	  read_index_message();//加载配置
	}
}

void close_log_function(void)
{
   file_log_is_on=0;
}



//读取所有log
void read_file_log( void )
{
	#define __is_print(ch)       ((unsigned int)((ch) - ' ') < 127u - ' ')
	int i,j=0;
	int read_block=0;
	COLOR_RED_INFO(">>>>   read log  <<<<\r\n");
	for(i=0;i<=file_block.file_block_used_size;i++)
  {
		 read_block = (  file_block.file_block_base) + ( (file_block.file_block_start+i)%file_block.file_block_size );
			              
	   flash_read_page(read_block*4096,flash_log_temp,4096);
		 for(j=0;j<FLASH_MIN_SIZE;j++)
		 {
			 if( __is_print(flash_log_temp[j]) )
			 {
			  printf("%c",    flash_log_temp[j] );
			 }
			 if(flash_log_temp[j] ==0x0D ) printf("\r");
		   if(flash_log_temp[j] ==0x0A ) printf("\n");
		 }	 
	}
  COLOR_RED_INFO(">>>>*************<<<<\r\n"); 	
}
//擦除所有log
void clear_file_log( void )
{
		 int i=0;
	   COLOR_RED_INFO(">>>>  earse log  <<<<\r\n");
		 for(i=0;i<= (LOG_flash_size/4096);i++)		
		 {
			 flash_EraseSector((LOG_flash_addr_start/4096)+i); 
			 progress_printf_bar( (i*100)/(LOG_flash_size/4096) );
		 }
		 printf("\r\n");
		 flash_EraseSector(LOG_flash_message_addr/4096);
		 
		 file_block.file_block_base=LOG_flash_addr_start/4096;  //(起始的偏移编号)
		 //block 编码 0-1790 	 
		 file_block.file_block_start=0;                         
		 file_block.file_block_end=0;
		 file_block.file_block_size=(LOG_flash_size)/FLASH_MIN_SIZE; 
		 file_block.file_block_used_size=0;
			
		 file_block.file_pack_end=0;
		 file_block.file_pack_size=FLASH_MIN_SIZE /LOGG_MIN_SIZE;
			 
		 file_block.first_init_flag=0x12345678;
		 memset( flash_log_temp,0,sizeof(flash_log_temp));
		 memcpy(flash_log_temp,(uint8_t *) &file_block,sizeof(file_block));	
		 flash_write_page(LOG_flash_message_addr,flash_log_temp,sizeof(file_block));
     IWDT_Clr();
		 COLOR_RED_INFO(">>>>*************<<<<\r\n"); 	
}


//写字符串到log空间  最大64个字符
void write_file_log(char* string)
{
	uint32_t addr   = get_malloc_block();//获取
//	uint32_t offset = file_block.file_pack_end;
	uint32_t read_block=0;
	//读flash
	COLOR_RED_INFO(">>>>  write log  <<<<\r\n");
	read_block =( file_block.file_block_base + file_block.file_block_end  );
	//printf("new_addr: 0x%x\r\n",read_block);
	flash_read_page(read_block*4096,flash_log_temp,4096);
	memcpy(&flash_log_temp[file_block.file_pack_end*LOGG_MIN_SIZE],string,strlen(string));
	//回写flash
	flash_write_page(read_block*4096,flash_log_temp,4096);
	
	file_block.file_pack_end+=1;
	if(file_block.file_pack_end>=file_block.file_pack_size)
	{
		 file_block.file_pack_end=0;
		 file_block.file_block_end=(file_block.file_block_end+1)%file_block.file_block_size;//寻找下一个扇区
		 file_block.file_block_used_size++; 
	}
	//写回控制块
	memset( flash_log_temp,0,sizeof(flash_log_temp));
	memcpy( flash_log_temp,(uint8_t *) &file_block,sizeof(file_block)/sizeof(uint8_t));
	flash_write_page(LOG_flash_message_addr,flash_log_temp,sizeof(file_block)/sizeof(uint8_t));
	printf("%s",string);
	COLOR_RED_INFO(">>>>*************<<<<\r\n"); 
}



//写字符串到log空间  最大64个字符
void printf_flash_log(char* string)
{
	uint32_t addr   = get_malloc_block();//获取
//	uint32_t offset = file_block.file_pack_end;
	uint32_t read_block=0;
	//读flash
	read_block =( file_block.file_block_base + file_block.file_block_end  );
	//printf("new_addr: 0x%x\r\n",read_block);
	flash_read_page(read_block*4096,flash_log_temp,4096);
	memcpy(&flash_log_temp[file_block.file_pack_end*LOGG_MIN_SIZE],string,strlen(string));
	//回写flash
	flash_write_page(read_block*4096,flash_log_temp,4096);
	
	file_block.file_pack_end+=1;
	if(file_block.file_pack_end>=file_block.file_pack_size)
	{
		 file_block.file_pack_end=0;
		 file_block.file_block_end=(file_block.file_block_end+1)%file_block.file_block_size;//寻找下一个扇区
		 file_block.file_block_used_size++; 
	}
	//写回控制块
	memset( flash_log_temp,0,sizeof(flash_log_temp));
	memcpy( flash_log_temp,(uint8_t *) &file_block,sizeof(file_block)/sizeof(uint8_t));
	flash_write_page(LOG_flash_message_addr,flash_log_temp,sizeof(file_block)/sizeof(uint8_t));
	printf("%s",string);
}

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IOT-Power

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值