
1. System Log
2. Thought Analysis
-
Directory area: classified by date, records the storage address, log index, and log size of the logs for the day. The directory can provide an overview of the entire log file; -
Parameter area: stores parameters such as the log write position, number of directory items, write status, etc.; -
Log area: this is our main storage area, recording the system logs, supporting circular writing. These three areas need to occupy some memory, and their sizes can be allocated by oneself.


3. Flash Memory Partitioning
#define FLASH_SECTOR_SIZE ((uint32_t)0x001000)#define FLASH_BLOCK_32K_SIZE ((uint32_t)0x008000)#define FLASH_BLOCK_64K_SIZE ((uint32_t)0x010000)#define SECTOR_MASK (FLASH_SECTOR_SIZE - 1) /* Sector mask ------*/#define SECTOR_BASE(addr) (addr & (~SECTOR_MASK)) /* Base address of the sector --*/#define SECTOR_OFFSET(addr) (addr & SECTOR_MASK) /* Offset within the sector --*/
#define BLOCK_32K_BASE(addr) (addr & (~(FLASH_BLOCK_32K_SIZE)))#define BLOCK_64K_BASE(addr) (addr & (~(FLASH_BLOCK_64K_SIZE)))
typedef enum { FLASH_BLOCK_4K = 0, /**< flash erase block size 4k */ FLASH_BLOCK_32K = 1, /**< flash erase block size 32k */ FLASH_BLOCK_64K = 2 /**< flash erase block size 64k */}flash_block_t;
/* Flash space index */typedef enum{ FLASH_CATALOG_ZONE = 0, FLASH_SYSLOG_PARA_ZONE, FLASH_SYSLOG_ZONE, FLASH_ZONEX,}flash_zone_e;
typedef struct{ flash_zone_e zone; uint32_t start_address; uint32_t end_address;}flash_table_t;
/* Address partitioning */static const flash_table_t flash_table[] = { { .zone = FLASH_CATALOG_ZONE, .start_address = 0x03200000, .end_address = 0x032FFFFF}, { .zone = FLASH_SYSLOG_PARA_ZONE, .start_address = 0x03300000, .end_address = 0x033FFFFF}, { .zone = FLASH_SYSLOG_ZONE, .start_address = 0x03400000, .end_address = 0x03FFFFFF}, };
flash_table_t *get_flash_table(flash_zone_e zone){ int i = 0; for (i = 0; i < flash_zone_count; i++) { if (zone == flash_table[i].zone) return (flash_table_t *)&flash_table[i]; }
return NULL; }
int flash_erase(flash_zone_e zone, uint32_t address, flash_block_t block_type){ flash_table_t *flash_table_tmp = get_flash_table(zone);
if (flash_table_tmp == NULL) return -1;
if (address < flash_table_tmp->start_address ||address > flash_table_tmp->end_address) return -1;
return bsp_spi_flash_erase(address, block_type);}
int flash_write(flash_zone_e zone, uint32_t address, const uint8_t*data, uint32_t length){ flash_table_t *flash_table_tmp = get_flash_table(zone);
if (flash_table_tmp == NULL) return -1;
if ((address < flash_table_tmp->start_address) ||((address + length) > flash_table_tmp->end_address)) return -1;
return bsp_spi_flash_buffer_write(address, (uint8_t *)data, length);}
int flash_read(flash_zone_e zone, uint32_t address, uint8_t*buffer, uint32_t length){ flash_table_t *flash_table_tmp = get_flash_table(zone);
if (flash_table_tmp == NULL) return -1;
if ((address < flash_table_tmp->start_address) ||((address + length) > flash_table_tmp->end_address)) return -1;
bsp_spi_flash_buffer_read(buffer, address, length); return 0;}
typedef struct { uint16_t Year; /* Year:YYYY */ uint8_t Month; /* Month:MM */ uint8_t Day; /* Day:DD */ uint8_t Hour; /* Hour:HH */ uint8_t Minute; /* Minute:MM */ uint8_t Second; /* Second:SS */}time_t;
int bsp_rtc_get_time(time_t *date);
#define SYSTEM_LOG_MAGIC_PARAM 0x87654321 /* Log parameter identifier */typedef struct { uint32_t magic; /* Parameter identifier */ uint16_t crc; /* Checksum */ uint16_t len; /* Parameter length */} single_sav_t;
/* Log area parameters */typedef struct { uint32_t write_pos; /* Write position */ uint32_t catalog_num; /* Number of directory items */ uint8_t log_cyclic_status; /* System log circular write status */ uint8_t catalog_cyclic_status; /* Log directory circular write status */ time_t log_latest_time; /* Store latest time */}system_log_t;
/* Directory area parameters */typedef struct { uint32_t log_id; /* Log index */ uint32_t log_addr; /* Log address */ uint32_t log_offset; /* Log offset size, in bytes */ time_t log_time; /* Log storage time */}system_catalog_t;
/* System log parameters */typedef struct { single_sav_t crc_val; system_log_t system_log; system_catalog_t system_catalog;}sys_log_param_t;
typedef struct { uint8_t system_log_print_enable; /* System log print enable */ uint16_t system_log_print_id; /* Print specified id system log */ uint32_t system_log_param_addr; /* Current log write address */} sys_ram_t;
sys_ram_t SysRam;sys_log_param_t SysLogParam;
sys_ram_t *gp_sys_ram = &SysRam;sys_log_param_t *gp_sys_log = &SysLogParam;
4. Implementation Interface Description
/* 16-bit CRC verification high table */static const uint8_t auchCRCHi[]={0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40};
/* 16-bit CRC verification low table */static const uint8_t auchCRCLo[]={0x00,0xc0,0xc1,0x01,0xc3,0x03,0x02,0xc2,0xc6,0x06,0x07,0xc7,0x05,0xc5,0xc4,0x04,0xcc,0x0c,0x0d,0xcd,0x0f,0xcf,0xce,0x0e,0x0a,0xca,0xcb,0x0b,0xc9,0x09,0x08,0xc8,0xd8,0x18,0x19,0xd9,0x1b,0xdb,0xda,0x1a,0x1e,0xde,0xdf,0x1f,0xdd,0x1d,0x1c,0xdc,0x14,0xd4,0xd5,0x15,0xd7,0x17,0x16,0xd6,0xd2,0x12,0x13,0xd3,0x11,0xd1,0xd0,0x10,0xf0,0x30,0x31,0xf1,0x33,0xf3,0xf2,0x32,0x36,0xf6,0xf7,0x37,0xf5,0x35,0x34,0xf4,0x3c,0xfc,0xfd,0x3d,0xff,0x3f,0x3e,0xfe,0xfa,0x3a,0x3b,0xfb,0x39,0xf9,0xf8,0x38,0x28,0xe8,0xe9,0x29,0xeb,0x2b,0x2a,0xea,0xee,0x2e,0x2f,0xef,0x2d,0xed,0xec,0x2c,0xe4,0x24,0x25,0xe5,0x27,0xe7,0xe6,0x26,0x22,0xe2,0xe3,0x23,0xe1,0x21,0x20,0xe0,
0xa0,0x60,0x61,0xa1,0x63,0xa3,0xa2,0x62,0x66,0xa6,0xa7,0x67,0xa5,0x65,0x64,0xa4,0x6c,0xac,0xad,0x6d,0xaf,0x6f,0x6e,0xae,0xaa,0x6a,0x6b,0xab,0x69,0xa9,0xa8,0x68,0x78,0xb8,0xb9,0x79,0xbb,0x7b,0x7a,0xba,0xbe,0x7e,0x7f,0xbf,0x7d,0xbd,0xbc,0x7c,0xb4,0x74,0x75,0xb5,0x77,0xb7,0xb6,0x76,0x72,0xb2,0xb3,0x73,0xb1,0x71,0x70,0xb0,0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9c,0x5c,0x5d,0x9d,0x5f,0x9f,0x9e,0x5e,0x5a,0x9a,0x9b,0x5b,0x99,0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4b,0x8b,0x8a,0x4a,0x4e,0x8e,0x8f,0x4f,0x8d,0x4d,0x4c,0x8c,0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40};
/* Implement CRC function */static uint16_t CRC16(uint8_t* puchMsg, uint16_t usDataLen){ uint8_t uchCRCHi=0xff; uint8_t uchCRCLo=0xff; uint16_t uIndex;
while(usDataLen--) { uIndex=uchCRCHi^*(puchMsg++); uchCRCHi=uchCRCLo^auchCRCHi[uIndex]; uchCRCLo=auchCRCLo[uIndex]; }
return uchCRCHi<<8|uchCRCLo;}
void save_system_log_param(void){ uint32_t i = 0; uint32_t addr = 0; uint32_t remainbyte = 0; uint32_t start_addr; int len = sizeof(sys_log_param_t); uint8_t *pdata = (uint8_t *)&SysLogParam; flash_table_t *flash_tmp = get_flash_table(FLASH_SYSLOG_PARA_ZONE);
/* Verify parameters */ gp_sys_log->crc_val.magic = SYSTEM_LOG_MAGIC_PARAM; gp_sys_log->crc_val.len = sizeof(sys_log_param_t) - sizeof(single_sav_t); gp_sys_log->crc_val.crc = CRC16(&pdata[sizeof(single_sav_t)], gp_sys_log->crc_val.len);
start_addr = gp_sys_ram->system_log_param_addr; /* If there is not enough remaining memory to write, start writing from the beginning address to implement circular storage functionality */ if ((start_addr + len) > flash_tmp->end_address) { start_addr = flash_tmp->start_address; } gp_sys_ram->system_log_param_addr = start_addr + len; /* Store from the first address, erase the entire system log parameter storage area. If the allocated memory is larger, the first erase may take longer, but in actual applications, embedded devices should not occupy too much memory to store system logs, only as auxiliary use, and additional applications can be implemented by themselves */ if (flash_tmp->start_address == start_addr) { /*for (i = flash_tmp->start_address; i < flash_tmp->end_address; i+= FLASH_SECTOR_SIZE) flash_erase(FLASH_SYSLOG_PARA_ZONE, SECTOR_BASE(i), FLASH_BLOCK_4K); */ addr = flash_tmp->start_address; do { if ((addr + FLASH_BLOCK_64K_SIZE) <= flash_tmp->end_address) { flash_erase(FLASH_SYSLOG_PARA_ZONE, BLOCK_64K_BASE(i), FLASH_BLOCK_64K); addr += FLASH_BLOCK_64K_SIZE; } else if ((addr + FLASH_BLOCK_32K_SIZE) <= flash_tmp->end_address) { flash_erase(FLASH_SYSLOG_PARA_ZONE, BLOCK_32K_BASE(i), FLASH_BLOCK_32K); addr += FLASH_BLOCK_32K_SIZE; } else if ((addr + FLASH_SECTOR_SIZE) <= flash_tmp->end_address) { flash_erase(FLASH_SYSLOG_PARA_ZONE, SECTOR_BASE(i), FLASH_BLOCK_4K); addr += FLASH_SECTOR_SIZE; } else { break; } } while (addr < flash_tmp->end_address); }
remainbyte = FLASH_SECTOR_SIZE - (start_addr % FLASH_SECTOR_SIZE); if (remainbyte > len) { remainbyte = len; } while (1) { flash_write(FLASH_SYSLOG_PARA_ZONE, start_addr, pdata, remainbyte); if (remainbyte == len) { break; } else { pdata += remainbyte; start_addr += remainbyte; len -= remainbyte; remainbyte = (len > FLASH_SECTOR_SIZE) ? FLASH_SECTOR_SIZE : len; } }}
void load_system_log_default_param(void){ /* Default parameters for system logs */ /* Directory circular write status flag */ gp_sys_log->system_log.catalog_cyclic_status = 0x00; /* Number of directory items */ gp_sys_log->system_log.catalog_num = 0; /* Circular write flag for logs, 1: circular write status */ gp_sys_log->system_log.log_cyclic_status = 0; /* Set default values, actual will re-obtain the latest time from RTC */ gp_sys_log->system_log.log_latest_time.Year = 2019; gp_sys_log->system_log.log_latest_time.Month = 5; gp_sys_log->system_log.log_latest_time.Day = 8; gp_sys_log->system_log.log_latest_time.Hour = 13; gp_sys_log->system_log.log_latest_time.Minute = 14; gp_sys_log->system_log.log_latest_time.Second = 10; /* Log write position starts from 0 */ gp_sys_log->system_log.write_pos = 0;
gp_sys_log->system_catalog.log_addr = 0; gp_sys_log->system_catalog.log_id = 0; gp_sys_log->system_catalog.log_offset = 0; gp_sys_log->system_catalog.log_time.Year = 2019; gp_sys_log->system_catalog.log_time.Month = 5; gp_sys_log->system_catalog.log_time.Day = 8; gp_sys_log->system_catalog.log_time.Hour = 12; gp_sys_log->system_catalog.log_time.Minute = 12; gp_sys_log->system_catalog.log_time.Second = 14;
gp_sys_log->crc_val.magic = SYSTEM_LOG_MAGIC_PARAM;
/* Save after importing default parameters */ save_system_log_param();}
/* Parameter initialization, called at terminal startup */int load_system_log_param(void){ uint32_t i = 0; single_sav_t psav; uint32_t end_addr; uint32_t interal = sizeof(sys_log_param_t); int data_len = sizeof(sys_log_param_t) - sizeof(single_sav_t); uint8_t *pram = (uint8_t *)&SysLogParam; flash_table_t *flash_tmp = get_flash_table(FLASH_SYSLOG_PARA_ZONE);
end_addr =flash_tmp->end_address - (flash_tmp->end_address - flash_tmp->start_address) % interal; for (i = end_addr - interal; i > flash_tmp->start_address; i -= interal) { flash_read(FLASH_SYSLOG_PARA_ZONE, i, (uint8_t *)&psav, sizeof(single_sav_t)); if ((psav.magic == SYSTEM_LOG_MAGIC_PARAM) && (psav.len ==data_len)) { flash_read(FLASH_SYSLOG_PARA_ZONE, i + sizeof(single_sav_t), &pram[sizeof(single_sav_t)], data_len); if (psav.crc != CRC16(&pram[sizeof(single_sav_t)], data_len)) continue; gp_sys_ram->system_log_param_addr = i; log_info("Load System Log Param Addr[0x%08x]!", gp_sys_ram->system_log_param_addr); return 0; } }
/* If no valid parameters are found, import default system log parameters */ load_system_log_default_param(); /* Get log write address */ gp_sys_ram->system_log_param_addr = flash_tmp->start_address; log_info("Load System Log Param Addr(Default)[0x%08x]!", gp_sys_ram->system_log_param_addr); return 1;}
/* Read specified log index directory information from the log directory area */int system_catalog_read(system_catalog_t *catalog, uint32_t id){ uint32_t addr; int rlen = sizeof(system_catalog_t); uint8_t *pbuf = (uint8_t *)catalog; flash_table_t *flash_tmp = get_flash_table(FLASH_CATALOG_ZONE);
if (0 == id) return -1; addr = flash_tmp->start_address + (rlen * (id - 1)); if (addr > flash_tmp->end_address) return -1;
return flash_read(FLASH_CATALOG_ZONE, addr, pbuf, rlen);}
/* Write directory information to the log directory area */int system_catalog_write(system_catalog_t *catalog, uint32_t id){ uint32_t start_offset; uint32_t start_addr; uint32_t start_base; uint32_t remainbyte; int wlen = sizeof(system_catalog_t); uint8_t *pdata = (uint8_t *)catalog; flash_table_t *flash_tmp = get_flash_table(FLASH_CATALOG_ZONE);
if (0 == id) return -1; start_addr = flash_tmp->start_address + wlen * (id - 1); if ((start_addr + wlen) > flash_tmp->end_address) { start_addr = flash_tmp->start_address; }
/* Remaining space size in this sector */ remainbyte = FLASH_SECTOR_SIZE - (start_addr % FLASH_SECTOR_SIZE); /* If the data length to be written is less than the remaining length of this sector, write directly */ if (remainbyte > wlen) { remainbyte = wlen; } /* The number of times to write the directory will not be too frequent, modify the implementation according to specific conditions */ while (1) { start_base = SECTOR_BASE(start_addr); start_offset = SECTOR_OFFSET(start_addr); flash_read(FLASH_CATALOG_ZONE, start_base, sector_buf, FLASH_SECTOR_SIZE); flash_erase(FLASH_CATALOG_ZONE, start_base, FLASH_BLOCK_4K); memcpy((char *)§or_buf[start_offset], pdata, remainbyte); flash_write(FLASH_CATALOG_ZONE, start_base, sector_buf, FLASH_SECTOR_SIZE); if (remainbyte == wlen) { break; } else { pdata += remainbyte; start_addr += remainbyte; wlen -= remainbyte; remainbyte = (wlen > FLASH_SECTOR_SIZE) ? FLASH_SECTOR_SIZE : wlen; } }
return 0;}
int system_catalog_all_print(void){ int i = 0; system_catalog_t catalog;
printf("System Log Command Information:\r\n"); printf("Query Specifies Log : AT+CATALOG=<LOG_ID><CR><LF>\r\n"); printf("Query All Log : AT+CATALOG=<0><CR><LF>\r\n\r\n"); printf("Query All System Catalog:\r\n"); printf("LOG_ID LOG_DATE LOG_ADDR LOG_OFFSET \r\n"); for (i = 0; i < gp_sys_log->system_log.catalog_num; i++) { /* Current latest directory information */ if (i == (gp_sys_log->system_catalog.log_id - 1)) { catalog = gp_sys_log->system_catalog; /* Get current latest directory information */ } else { system_catalog_read(&catalog, i + 1); } printf("%d %04d-%02d-%02d 0x%08X %d \r\n", catalog.log_id, catalog.log_time.Year, catalog.log_time.Month, catalog.log_time.Day, catalog.log_addr, catalog.log_offset); memset((char *)&catalog, 0, sizeof(system_catalog_t)); } return 0;}
int system_log_task(int argc){ int rlen = 0; uint32_t offset, start_addr, end_addr; system_catalog_t catalog; flash_table_t *flash_tmp =get_flash_table(FLASH_SYSLOG_ZONE);
if (0 == gp_sys_ram->system_log_print_enable) return 1;
gp_sys_ram->system_log_print_enable = 0x00; if (gp_sys_ram->system_log_print_id == ALL_LOG_PRINT) { /* log circular write flag, print the entire LOG storage area */ if (0x01 == gp_sys_log->system_log.log_cyclic_status) { start_addr = flash_tmp->start_address; end_addr = flash_tmp->end_address; offset = end_addr - start_addr; } else { start_addr = flash_tmp->start_address; end_addr = start_addr + gp_sys_log->system_log.write_pos; offset = gp_sys_log->system_log.write_pos; } } else { /* Read specified ID log */ if (gp_sys_ram->system_log_print_id == gp_sys_log->system_catalog.log_id) { catalog = gp_sys_log->system_catalog; } else { system_catalog_read(&catalog, gp_sys_ram->system_log_print_id); } start_addr = catalog.log_addr; offset = catalog.log_offset; }
if (0 == offset) return 1;
while (1) { rlen = (offset > 512) ? 512 : offset; system_log_read(sector_buf, start_addr, rlen); HAL_Delay(80); /* Directory information printed through the debugging serial port */ bsp_debug_send(sector_buf, rlen); start_addr += rlen; offset -= rlen; if (0 == offset) break; } return 0;}
int system_log_write(uint8_t *wbuf, int wlen){ uint32_t start_addr; uint8_t *pdata = wbuf; uint32_t remainbyte; int system_catalog_max_id; flash_table_t *flash_tmp =get_flash_table(FLASH_SYSLOG_ZONE);
/* Calculate the maximum number of directory items that can be stored in the directory area */ system_catalog_max_id = ((flash_tmp->end_address - flash_tmp->start_address) / sizeof(system_catalog_t)); start_addr = flash_tmp->start_address + gp_sys_log->system_log.write_pos; /* Handle when the storage data address exceeds the planned memory address range */ if ((start_addr + wlen) > flash_tmp->end_address) { start_addr = flash_tmp->start_address; /* Reset write position offset */ gp_sys_log->system_log.write_pos = 0; /* LOG circular storage flag set */ gp_sys_log->system_log.log_cyclic_status = 0x01; } /* Write position offset */ gp_sys_log->system_log.write_pos += wlen;
if ((gp_sys_log->system_log.log_latest_time.Year != gp_sys_log->system_catalog.log_time.Year) || (gp_sys_log->system_log.log_latest_time.Month != gp_sys_log->system_catalog.log_time.Month) || (gp_sys_log->system_log.log_latest_time.Day != gp_sys_log->system_catalog.log_time.Day)) {
/* Date changed, record directory information; when log_id is 0, do not write */ system_catalog_write(&gp_sys_log->system_catalog, gp_sys_log->system_catalog.log_id); /* Record storage date */ gp_sys_log->system_catalog.log_time = gp_sys_log->system_log.log_latest_time;
if ((gp_sys_log->system_catalog.log_id + 1) >= system_catalog_max_id) { gp_sys_log->system_log.catalog_num = system_catalog_max_id; /* Directory circular write, the number of directories should be maximum */ gp_sys_log->system_log.catalog_cyclic_status = 1; /* Directory circular write flag */ } else { if (0 == gp_sys_log->system_log.catalog_cyclic_status) { /* Get directory count */ gp_sys_log->system_log.catalog_num = gp_sys_log->system_catalog.log_id + 1; } }
/* Store the latest directory item information */ gp_sys_log->system_catalog.log_id = (gp_sys_log->system_catalog.log_id + 1) % system_catalog_max_id; gp_sys_log->system_catalog.log_addr = start_addr; gp_sys_log->system_catalog.log_offset = wlen; } else { gp_sys_log->system_catalog.log_offset += wlen; }
/* Write position is the storage starting address and not the sector head address */ if ((flash_tmp->start_address == start_addr) && (SECTOR_OFFSET(flash_tmp->start_address))){ flash_read(FLASH_SYSLOG_ZONE, SECTOR_BASE(start_addr), sector_buf, FLASH_SECTOR_SIZE); flash_erase(FLASH_SYSLOG_ZONE, SECTOR_BASE(start_addr), FLASH_BLOCK_4K); /* Write back data from the sector head to the starting address */ flash_write(FLASH_SYSLOG_ZONE, SECTOR_BASE(start_addr), §or_buf[0], SECTOR_OFFSET(start_addr)); }
/* Write position is the sector head address, erase a sector storage area */ if (0 == SECTOR_OFFSET(start_addr)) { flash_erase(FLASH_SYSLOG_ZONE, SECTOR_BASE(start_addr), FLASH_BLOCK_4K); }
/* Remaining space size in this sector */ remainbyte = FLASH_SECTOR_SIZE - (start_addr % FLASH_SECTOR_SIZE); /* If the data length to be written is less than the remaining length of this sector, write directly */ if (remainbyte > wlen) { remainbyte = wlen; } while (1) { flash_write(FLASH_SYSLOG_ZONE, start_addr, pdata, remainbyte); if (remainbyte == wlen) { break; } else { pdata += remainbyte; start_addr += remainbyte; wlen -= remainbyte; remainbyte = (wlen > FLASH_SECTOR_SIZE) ? FLASH_SECTOR_SIZE : wlen; /* If the sector head address, erase the entire sector, this sector data is not saved */ if (0 == SECTOR_OFFSET(start_addr)) { flash_erase(FLASH_SYSLOG_ZONE, SECTOR_BASE(start_addr), FLASH_BLOCK_4K); } } }
/* Circular storage parameters */ save_system_log_param(); return 0;}
5. System Debugging Interface
#define LOG_CLOSE_LEVEL 0x00 /* Close debugging information */#define LOG_ERROR_LEVEL 0x01 /* Error debugging information */#define LOG_WARN_LEVEL 0x02 /* Warning debugging information */#define LOG_INFO_LEVEL 0x03 /* Critical debugging information */#define LOG_DEBUG_LEVEL 0x04 /* Debug debugging information */#define LOG_RECORD_LEVEL 0x10 /* Save logs and output information */ #define LOG_PRINT_LEVEL 0xff
#define SET_LOG_LEVEL(LEVEL) (gp_sys_param->system_print_level = LEVEL)#define GET_LOG_LEVEL() (gp_sys_param->system_print_level)
#define log_debug(fmt, args...) log_format(LOG_DEBUG_LEVEL, fmt, ##args)#define log_info(fmt, args...) log_format(LOG_INFO_LEVEL, fmt, ##args)#define log_warn(fmt, args...) log_format(LOG_WARN_LEVEL, fmt, ##args)#define log_error(fmt, args...) log_format(LOG_ERROR_LEVEL, fmt, ##args)#define log_record(fmt, args...) log_format(LOG_RECORD_LEVEL, fmt, ##args)#define printf(fmt, args...) log_format(LOG_PRINT_LEVEL, fmt, ##args)
typedef struct { int level; char *fmt_str;}system_print_fmt_t;
system_print_fmt_t system_print_fmt_list[] = { { .level = LOG_ERROR_LEVEL, .fmt_str = "<error>:"}, { .level = LOG_WARN_LEVEL, .fmt_str = "<warn>:"}, { .level = LOG_INFO_LEVEL, .fmt_str = "<info>:"}, { .level = LOG_DEBUG_LEVEL, .fmt_str = "<debug>:"}, { .level = LOG_RECORD_LEVEL, .fmt_str = "<record>:"},};
int log_format(uint8_t level, const char *fmt, ...){ #define TIME_PREFIX_SIZE (21) #define PRINT_MAX_SIZE (1024 + TIME_PREFIX_SIZE)
va_list args; int num = 0, i = 0, fmt_index = 0; int fmt_str_len = 0, ret = -1; int file_str_len = 0, line_str_len = 0; char line_buf[20] = {0}; static char buf[PRINT_MAX_SIZE]; static QueueHandle_t sem = NULL; time_t time = {0};
/* For OS system */ if (NULL == sem) { sem = xSemaphoreCreateCounting(1, 1); /* always think of success */ }
xSemaphoreTake(sem, portMAX_DELAY);
ret = -1; fmt_str_len = 0; if (level != LOG_PRINT_LEVEL) { if ((GET_LOG_LEVEL() < level) && (level != LOG_RECORD_LEVEL) && (level != LOG_ERROR_LEVEL)) goto exit_end;
for (i = 0; i < SYSTEM_PRINT_FMT_LIST_MAX; i++) { if (level == system_print_fmt_list[i].level) { fmt_index = i; break; } }
if (i > SYSTEM_PRINT_FMT_LIST_MAX) { goto exit_end; }
fmt_str_len = strlen(system_print_fmt_list[fmt_index].fmt_str); strncpy((char *)&buf[TIME_PREFIX_SIZE], system_print_fmt_list[fmt_index].fmt_str, fmt_str_len); }
va_start(args, fmt); num = vsnprintf((char *)&buf[fmt_str_len + TIME_PREFIX_SIZE], PRINT_MAX_SIZE - fmt_str_len - TIME_PREFIX_SIZE - 2, fmt, args); va_end(args);
if (num <= 0) { goto exit_end; }
if (level != LOG_PRINT_LEVEL) { num += fmt_str_len; buf[num + TIME_PREFIX_SIZE] = '\r'; buf[num + TIME_PREFIX_SIZE + 1] = '\n'; num += 2; }
if ((GET_LOG_LEVEL() < level) && (level == LOG_ERROR_LEVEL)) { //do nothing } else { ret = bsp_debug_send((uint8_t*)&buf[TIME_PREFIX_SIZE], num); }
if ((LOG_ERROR_LEVEL == level) || (LOG_RECORD_LEVEL == level)) { bsp_rtc_get_time(&time); sprintf(&buf[0], "[%04d-%02d-%02d %02d:%02d:%02d", time.Year, time.Month, time.Day,time.Hour, time.Minute, time.Second); buf[TIME_PREFIX_SIZE - 1] = ']'; gp_sys_log->system_log.log_latest_time = time; system_log_write((uint8_t *)buf, num + TIME_PREFIX_SIZE); }
exit_end: xSemaphoreGive(sem); return ret;}
6. Conclusion
Source:
https://blog.csdn.net/LiaRonBob/article/details/102766871
Declaration: The materials in this article are sourced from the internet, and the copyright belongs to the original author. If there are any copyright issues, please contact me for deletion.
------------ END ------------
● Column "Embedded Tools"
● Column "Embedded Development"
● Column "Keil Tutorial"
● Selected tutorials from the embedded column
Follow the public account and reply "join group" to join the technical exchange group according to the rules, reply "1024" to see more content.
Click "Read the original" to see more sharing.