| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770 | #include "log.h"#include "rtc.h"#include "ringfs.h"#include "spi_flash.h"#include "FreeRTOS.h"#include "task.h"#include "semphr.h"#include "rtc.h"#include "settings_api.h"#include <string.h>#include <stdio.h>#include <inttypes.h>#undef DBG#define DBG if(1)static bool archive_state = true;static bool log_state = true;struct ringfs fs_log;struct ringfs fs_archive;SemaphoreHandle_t log_mutex;uint16_t log_entries_capacity;uint16_t archive_entries_capacity;void log_task(void *params);//static int op_sector_erase(struct ringfs_flash_partition *flash, int address) {	(void)flash;	int ret;	ret = spi_flash_erase_sector(address, 0);	return ret;}//static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size) {	(void)flash;	int ret;	ret = spi_flash_write(address, data, size, 0);	return ret;}//static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size) {	(void)flash;	int ret;	ret = spi_flash_read(address, data, size, 0);	return ret;}//static struct ringfs_flash_partition ringfs_flash_log = {	.sector_offset = LOG_FLASH_SECTOR_OFFSET,	.sector_erase = op_sector_erase,	.program = op_program,	.read = op_read,};//static struct ringfs_flash_partition ringfs_flash_archive = {	.sector_offset = ARCHIVE_FLASH_SECTOR_OFFSET,	.sector_erase = op_sector_erase,	.program = op_program,	.read = op_read,};//void log_init(bool format) {	DBG printf("[LOG] Init...\r\n");	if (!spi_flash_desc.present)		return;        // ---------------------------------------------------------------------- //    // Журнал        	ringfs_flash_log.sector_size = spi_flash_desc.sector_size;	ringfs_flash_log.sector_count = LOG_FLASH_SECTOR_COUNT;	ringfs_init(&fs_log, &ringfs_flash_log, LOG_ENTRY_VERSION, sizeof(log_entry_t));    	if (format || ringfs_scan(&fs_log) != 0) {		DBG printf("FAT1 false\r\n");		ringfs_format(&fs_log);	}	DBG printf("FAT1 true\r\n");        // ---------------------------------------------------------------------- //    // Архив    	ringfs_flash_archive.sector_size = spi_flash_desc.sector_size;	ringfs_flash_archive.sector_count = ARCHIVE_FLASH_SECTOR_COUNT;	ringfs_init(&fs_archive, &ringfs_flash_archive, ARCHIV_ENTRY_VERSION, sizeof(archive_entry_t));    	if (format || ringfs_scan(&fs_archive) != 0) {		DBG printf("FAT2 false\r\n");		ringfs_format(&fs_archive);	}	DBG printf("FAT2 true\r\n");	    // ---------------------------------------------------------------------- //        //fLogInit = true;	log_mutex = xSemaphoreCreateMutex();    log_entries_capacity = ringfs_capacity(&fs_log);        archive_entries_capacity = ringfs_capacity(&fs_archive);    	xTaskCreate(log_task, "log_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);}//int log_fetch(void *entry, entry_type_t entry_type, uint32_t timeout) {    int ret;        ret = xSemaphoreTake(log_mutex, (TickType_t)timeout);        if (ret == pdFALSE)        return ret;    if (entry_type == LOG_ENTRY)        ret = ringfs_fetch(&fs_log, entry);    else if (entry_type == ARCHIVE_ENTRY)        ret = ringfs_fetch(&fs_archive, entry);    else ret = -1;    xSemaphoreGive(log_mutex);    return ret;   }//int log_discard(void *entry, entry_type_t entry_type, uint32_t timeout){    int ret;          ret = xSemaphoreTake(log_mutex, (TickType_t)timeout);        if (ret == pdFALSE)        return ret;    if (entry_type == LOG_ENTRY)        ret = ringfs_discard(&fs_log);    else if (entry_type == ARCHIVE_ENTRY)        ret = ringfs_discard(&fs_archive);    else ret = -1;        xSemaphoreGive(log_mutex);    return ret; }//int log_append(void *entry, entry_type_t entry_type){    int ret;    TM_RTC_t time;    common_entry_t *entry_ptr = entry;    log_entry_t *log_etnry_ptr;    archive_entry_t *archive_etnry_ptr;        ret = xSemaphoreTake(log_mutex, portMAX_DELAY);        if (ret == pdFALSE)        return ret;      entry_ptr->timestamp = rtc_get_ms();        if (entry_type == LOG_ENTRY)     {        log_etnry_ptr = (log_entry_t*)entry;        log_etnry_ptr->crc = crc_8(entry, sizeof(log_entry_t) - 1);        ret = ringfs_append(&fs_log, entry);    }    else if (entry_type == ARCHIVE_ENTRY)     {        archive_etnry_ptr = (archive_entry_t*)entry;        archive_etnry_ptr->crc = crc_8(entry, sizeof(archive_entry_t) - 1);        ret = ringfs_append(&fs_archive, entry);    }    else ret = -1;        xSemaphoreGive(log_mutex);    return ret;    }//uint16_t log_capacity(void){    return ringfs_count_estimate(&fs_log);}//uint16_t log_arch_capacity(void){    return ringfs_count_estimate(&fs_archive);}// -------------------------------------------------------------------------- //// miscuint8_t crc_8(uint8_t *data, int length){    uint8_t crc = 0x00;    uint8_t extract;    uint8_t sum;        for (int i = 0; i < length; i++) {        extract = *data;        for (uint8_t tmp = 8; tmp; tmp--) {            sum = (crc ^ extract) & 0x01;            crc >>= 1;            if (sum)                crc ^= 0x8C;            extract >>= 1;        }        data++;    }    return crc;}// -------------------------------------------------------------------------- //// Tests// val - 0 - журнал// val - 1 - архивvoid log_info(uint8_t val){    if (val > 1)        return;      struct ringfs *fs = val == 0 ? &fs_log : &fs_archive;        int capacity_flash = 0;    int count_flash = 0;    int count_estimate = 0;        capacity_flash = ringfs_capacity(fs);    count_flash = ringfs_count_exact(fs);    count_estimate = ringfs_count_estimate(fs);        if (val == 0)    {        DBG printf("Log partition capacity: %u\r\n", capacity_flash);        DBG printf("Count log entry: %u\r\n", count_flash);        DBG printf("Estimate count: %u\r\n", count_estimate);    }    else     {        DBG printf("Archive partition capacity: %u\r\n", capacity_flash);        DBG printf("Count archive entry: %u\r\n", count_flash);        DBG printf("Estimate count: %u\r\n", count_estimate);    }}// val - 0 - журнал// val - 1 - архивvoid log_format(uint8_t val){    if (val == 0) {        DBG printf("Formating log partition...\r\n");        ringfs_format(&fs_log);    }     else if (val == 1) {        DBG printf("Formating archive partition...\r\n");        ringfs_format(&fs_archive);    }}// Добавить n архивных записейint log_add_random_entry(uint8_t val, uint32_t cnt_entry){    int ret;    log_entry_t log_entry = {0};    archive_entry_t archive_entry = {0};        static uint8_t log_index = 0;    static uint32_t archive_index = 0;        if (val == 0)    {        DBG printf("Appending %u archive entries\r\n", cnt_entry);                for (uint32_t i = 0; i < cnt_entry; i++)        {            log_entry.code_type = log_index;            log_entry.code_state = log_index;            log_entry.channel_number = log_index;            log_entry.value = (float)log_index++;                        ret = log_append((void*)&log_entry, LOG_ENTRY);        }        DBG printf("Result: %u\r\n", ret);    }          if (val == 1)    {        DBG printf("Appending %u archive entries\r\n", cnt_entry);        for (uint32_t i = 0; i < cnt_entry; i++)        {            archive_entry.input_value = archive_index++;            ret = log_append((void*)&archive_entry, ARCHIVE_ENTRY);        }        DBG printf("Result: %u\r\n", ret);    }    return ret;}//void test_fetch(void){    archive_entry_t entry = {0};    log_fetch(&entry, ARCHIVE_ENTRY, portMAX_DELAY);    //printf("\r\n%" PRId64 " [ms]\r\n", rtc_get_ms());    printf("[entry] timestamp = % " PRId64 ", value = %u, crc = %u\r\n", entry.timestamp, entry.input_value, entry.crc);}//void log_archive_state(bool state){    archive_state = state;}//void log_log_state(bool state){    log_state = state;}void log_task(void *params){    int ret = 0;    archive_entry_t entry = {0};        for (;;)    {        if (!archive_state) {            vTaskDelay(1000);            continue;        }                entry.input_value = (uint8_t)input_state_bit;                DBG printf("Append archive entry...");                ret = log_append((void*)&entry, ARCHIVE_ENTRY);                      if (ret != 0) {            DBG printf("FAIL\r\n");        }        else {            DBG printf("OK\r\n");        }                vTaskDelay(settings.period_archive*1000);    }}#if 0char logFileBuf[FILE_BUF_MAX_LEN];char name_login[50];extern const char* logsStrShortRu[];bool flUpdateLog = false;static bool fLogInit = false;  // Флаг инициализации журнала#define LOG_TIME	1000*60*10static int op_sector_erase(struct ringfs_flash_partition *flash, int address) {	(void)flash;	int ret;	ret = spi_flash_erase_sector(address, 0);	return ret;}static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size) {	(void)flash;	int ret;	ret = spi_flash_write(address, data, size, 0);	return ret;}static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size) {	(void)flash;	int ret;	ret = spi_flash_read(address, data, size, 0);	return ret;}static struct ringfs_flash_partition ringfs_flash = {	.sector_offset = LOG_FLASH_SECTOR_OFFSET,	.sector_erase = op_sector_erase,	.program = op_program,	.read = op_read,};static struct ringfs fs;static struct ringfs_flash_partition ringfs_flash2 = {	.sector_offset = ALARM_LOG_FLASH_SECTOR_OFFSET,	.sector_erase = op_sector_erase,	.program = op_program,	.read = op_read,};static struct ringfs fs2;static SemaphoreHandle_t log_mutex;/**  * @brief  Отключает журнал для безопасной перезагрузки  */bool LOG_Disable(void){    if (fLogInit) {        /* Ожидаем завершения работы с журнал */        if ( xSemaphoreTake(log_mutex, 10000) == pdTRUE ) {            //fLogInit = false;            //xSemaphoreGive(logMutex);            return true;        }        else {           return false;        }    }    else {        return true;    }}void log_task(void* params){	for(;;){		flUpdateLog = true;		vTaskDelay(LOG_TIME);		/*vTaskDelay(50);		log_event_data(LOG_SYSTEM_BOOT, "Администратор");		log_add(")215.7;215.7;220.5;000;50.1;2.30;25.0;00000001;");*/	}}void log_init(bool format) {	DBG printf(">>> Event log\n");	if (!spi_flash_desc.present)		return;	ringfs_flash.sector_size = spi_flash_desc.sector_size;	ringfs_flash.sector_count = SECTOR_COUNT;	ringfs_init(&fs, &ringfs_flash, LOG_ENTRY_VERSION, sizeof(log_entry_t));	if (format || ringfs_scan(&fs) != 0){		DBG printf("FAT1 false\r\n");		ringfs_format(&fs);	}	DBG printf("FAT1 true\r\n");	ringfs_flash2.sector_size = spi_flash_desc.sector_size;	ringfs_flash2.sector_count = SECTOR_COUNT;	ringfs_init(&fs2, &ringfs_flash2, LOG_ENTRY_VERSION, sizeof(log_entry_t));	if (format || ringfs_scan(&fs2) != 0){		DBG printf("FAT2 false\r\n");		ringfs_format(&fs2);	}	DBG printf("FAT2 true\r\n");	fLogInit = true;	log_mutex = xSemaphoreCreateMutex();	xTaskCreate(log_task, ( char * ) "log_task", configMINIMAL_STACK_SIZE * 2, NULL, tskIDLE_PRIORITY, NULL);}int capacity_flash = 0;int count_flash = 0;int log_test(void) {	int ret;	log_entry_t entry;	log_init(false);	capacity_flash = ringfs_capacity(&fs);	count_flash = ringfs_count_exact(&fs);	DBG printf("\tCapacity:   %d\n", capacity_flash);	DBG printf("\tCount:      %d\n", count_flash);	DBG printf("\tAppending   ");//	ret = log_event(LOG_SYSTEM_DEFCONFIG, 0, 0);	DBG printf("%s\n", ret == 0 ? "ok" : "error");	if (ret == 0)		return -1;//	ret = log_event(LOG_SYSTEM_DEFCONFIG, 0, 512);	entry.timestamp = 0;	entry.type = 0;	DBG printf("\tFetching    ");	if (log_fetch(&entry, portMAX_DELAY) == 0){		DBG printf("ok, time=%d, type=%d\n", entry.timestamp, entry.type);		log_fetch(&entry, portMAX_DELAY);		entry.timestamp = 0;			entry.type = 0;		log_fetch(&entry, portMAX_DELAY);		entry.timestamp = 0;					entry.type = 0;				log_fetch(&entry, portMAX_DELAY);				entry.timestamp = 0;							entry.type = 0;						log_fetch(&entry, portMAX_DELAY);		return 0;	}	else {		DBG printf("fail\n");		return -1;	}	DBG printf("\tDiscarding  ");	if (log_discard(&entry,portMAX_DELAY) == 0)		DBG printf("ok\n");	else {		DBG printf("fail\n");		return -1;	}	return 0;}int log_append(log_entry_t *entry) {	int ret;	TM_RTC_t data;	ret = xSemaphoreTake( log_mutex, portMAX_DELAY );	if (ret == pdFALSE)		return ret;	if (!entry->timestamp){		TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);		entry->timestamp = data.unix;	}	if(entry->type == LOG_VALUE)		ringfs_append(&fs, entry);	else		ringfs_append(&fs2, entry);	xSemaphoreGive(log_mutex);	return ret;}int log_fetch(log_entry_t *entry, uint32_t timeout) {	int ret;	ret = xSemaphoreTake( log_mutex, (TickType_t)timeout );	if (ret == pdFALSE)		return ret;	if(entry->type == LOG_VALUE)		ret = ringfs_fetch(&fs, entry);	else		ret = ringfs_fetch(&fs2, entry);	xSemaphoreGive(log_mutex);	return ret;}int log_rewind(log_entry_t *entry, uint32_t timeout) {	int ret;	ret = xSemaphoreTake( log_mutex, (TickType_t)timeout );	if (ret == pdFALSE)		return ret;	if(entry->type == LOG_VALUE)		ret = ringfs_rewind(&fs);	else		ret = ringfs_rewind(&fs2);	xSemaphoreGive(log_mutex);	return ret;}int log_discard(log_entry_t *entry, uint32_t timeout) {	int ret;	ret = xSemaphoreTake( log_mutex, (TickType_t)timeout );	if (ret == pdFALSE)		return ret;	if(entry->type == LOG_VALUE)		ret = ringfs_discard(&fs);	else		ret = ringfs_discard(&fs2);	xSemaphoreGive(log_mutex);	return ret;}void log_event_data(log_type_t type, char *data){	log_entry_t entry_data;	entry_data.timestamp = 0;	entry_data.type = type;	strncpy(entry_data.data, data, 49);	if (fLogInit)		log_append(&entry_data);}void log_add(char *log_data){	char buf_value[50];	uint8_t i, len;	memset(buf_value, 0, 50);	len = strlen(log_data);	if (len != UPS_DATA_STRING_SIZE) {		//len = UPS_DATA_STRING_SIZE;		return;	}	strncpy(buf_value, log_data, len);	DBG printf("UPS log data: %s\r\n", log_data);	buf_value[0] = '\"';	for(i = 0; i < len; i++)	{		if(buf_value[i] == ' ')			buf_value[i] = ';';	}	buf_value[len - 1] = ';';	if(fLogInit){		if(fs.write.slot>67)		{			log_entry_t entry_data;			entry_data.timestamp = 0;			log_event_data(LOG_VALUE, buf_value);		}		else		log_event_data(LOG_VALUE, buf_value);	}}/**  * @brief  Возвращает true если журнал проинициализирован  */bool LOG_IsInit(){  return fLogInit;}/**  * @brief  Возвращает общее количество страниц  */uint32_t LOG_GetPageCount(void){  return (((ringfs_count_estimate(&fs)) / 10) + 1);}uint32_t LOG_GetTotalSTRCount(void){	return ringfs_count_estimate(&fs);}void LOG_GetPage_tabs(char *str, uint32_t page){	TM_RTC_t rtc_data;	log_entry_t entry;	char buf[20];	uint8_t i;	int start =LOG_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot);	memset(buf, 0, 20);	for(i=0; i < 10; i++){		fs.cursor_position =  start - 10*(page-1) - 1 - i;		if(fs.cursor_position < 0)			break;		else{			fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count;			fs.cursor.slot = fs.cursor_position%fs.slots_per_sector;		}		entry.type = LOG_VALUE;		log_fetch(&entry, portMAX_DELAY);		entry.data[49] = 0;		strncat(str, entry.data, strlen(entry.data));		TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);		sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i",  rtc_data.date, rtc_data.month,		rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);		strcat(str, buf);		strcat(str, "\",");		strcat(str, "\r\n");	}}void LOG_GetPage(char *str, uint32_t page){	TM_RTC_t rtc_data;	log_entry_t entry;	char buf[20];	uint8_t i;	int start =LOG_GetTotalSTRCount();//(fs.write.sector*fs.slots_per_sector + fs.write.slot);	memset(buf, 0, 20);	for(i=0; i < 10; i++){		fs.cursor_position =  start - 10*(page-1) - 1 - i;		if(fs.cursor_position < 0)			break;		else{			fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count;			fs.cursor.slot = fs.cursor_position%fs.slots_per_sector;		}		entry.type = LOG_VALUE;		log_fetch(&entry, portMAX_DELAY);		entry.data[49] = 0;		strncat(str, entry.data, strlen(entry.data));		TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);		sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i",  rtc_data.date, rtc_data.month,		rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);		strcat(str, buf);		strcat(str, "\",");	}}uint32_t LOG_GetData(int ptr, char *str, uint32_t size, bool start){	TM_RTC_t rtc_data;	log_entry_t entry;	char buf[20];	uint8_t i;	entry.type = LOG_VALUE;	if(start)		log_rewind(&entry, portMAX_DELAY);	fs.cursor_position =  ptr/STRING_SIZE;	fs.cursor.sector = (fs.read.sector + fs.cursor_position/fs.slots_per_sector)%fs.flash->sector_count;	fs.cursor.slot = fs.cursor_position%fs.slots_per_sector;	for(i = 0; i < size/STRING_SIZE; i++)	{		entry.type = LOG_VALUE;		log_fetch(&entry, portMAX_DELAY);		entry.data[49] = 0;		strncat(str, &entry.data[1], (strlen(entry.data) - 1));		TM_RTC_GetDateTimeFromUnix(&rtc_data, entry.timestamp);		sprintf(buf, "%02i.%02i.%02i %02i:%02i:%02i",  rtc_data.date, rtc_data.month,		rtc_data.year, rtc_data.hours, rtc_data.minutes, rtc_data.seconds);		strcat(str, buf);		strcat(str, "\n");	}	return strlen(str);}#endif
 |