#include "stm32f4xx_flash.h" #include "partition.h" #include "file.h" #include "config.h" #include "ff.h" static struct file_config_s file_config_flash; static struct file_config_s file_config_sd; static void file_config_write(uint32_t addr, struct file_config_s *cfg) { volatile uint32_t *p; p = (volatile uint32_t *)cfg; FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); for (uint32_t i = 0; i < 4; i++) { if (FLASH_ProgramWord(addr + i * 4, p[i]) != FLASH_COMPLETE) { while (1); } } FLASH_Lock(); p = (volatile uint32_t *)addr; if (p[0] != addr || (p[0] + p[1] + p[2]) != p[3]) { /* program flash error */ while (1); } } static uint32_t str10_to_uint(uint8_t *str) { uint32_t val = 0; uint32_t i = 0; while (1) { uint8_t c = str[i++]; if (c >= '0' && c <= '9') { c = c - '0'; val *= 10; val += c; } else { return val; } } return val; } static uint32_t str16_to_uint(uint8_t *str) { uint32_t val = 0; uint32_t i = 0; while (1) { uint8_t c = str[i++]; if (c >= '0' && c <= '9') { c = c - '0'; } else if (c >= 'A' && c <= 'F') { c = c - 'A' + 10; } else if (c >= 'a' && c <= 'f') { c = c - 'a' + 10; } else { return val; } val *= 16; val += c; } return val; } static void file_config_parse(uint8_t *p, uint32_t len, struct file_config_s *cfg) { uint32_t item = 0; /* 0:null, 1:addr, 2:baudrate, 3:parity, 4:stopbits */ uint32_t stage = 0; /* 0:null, 1:name_ing, 2:name_end, 3:numing, 4:num_end */ uint32_t i = 0; /* index of every char */ uint32_t j = 0; /* index in one word */ uint32_t val32; uint8_t val[16]; for (uint32_t k=0; kbaudrate = UART_DEFAULT_BAUDRATE; cfg->parity = UART_DEFAULT_PARITY; cfg->stopbits = UART_DEFAULT_STOPBITS; cfg->addr = UART_DEFAULT_ADDR; /* state machine for parse config file */ while (1) { if (stage == 0) { /* null */ if (p[i] == 'a' || p[i] == 'A') { item = 1; /* addr */ stage = 1; /* name_ing */ j = 1; } else if (p[i] == 'b' || p[i] == 'B') { item = 2; /* baudrate */ stage = 1; /* name_ing */ j = 1; } else if (p[i] == 'p' || p[i] == 'P') { item = 3; /* parity */ stage = 1; /* name_ing */ j = 1; } else if (p[i] == 's' || p[i] == 'S') { item = 4; /* stopbits */ stage = 1; /* name_ing */ j = 1; } else { item = 0; /* null */ } } else if (stage == 1) { /* name_ing */ if (item == 1) { if (p[i] == "addr"[j] || p[i] == "ADDR"[j]) { if (j < 3) { j++; } else { j = 0; stage = 2; /* name_end */ } } else { j = 0; item = 0; stage = 0; } } else if (item == 2) { if (p[i] == "baudrate"[j] || p[i] == "BAUDRATE"[j]) { if (j < 7) { j++; } else { j = 0; stage = 2; /* name_end */ } } else { j = 0; item = 0; stage = 0; } } else if (item == 3) { if (p[i] == "parity"[j] || p[i] == "PARITY"[j]) { if (j < 5) { j++; } else { j = 0; stage = 2; /* name_end */ } } else { j = 0; item = 0; stage = 0; } } else if (item == 4) { if (p[i] == "stopbits"[j] || p[i] == "STOPBITS"[j]) { if (j < 7) { j++; } else { j = 0; stage = 2; /* name_end */ } } else { j = 0; item = 0; stage = 0; } } else { j = 0; item = 0; stage = 0; } } else if (stage == 2) { /* name_end */ if (item == 1 || item == 2 || item == 4) { /* addr, baudrate, stopbits */ if (p[i] >= '0' && p[i] <= '9') { stage = 3; /* numing */ j = 1; val[0] = p[i]; } } else if (item == 3) { /* parity */ if (p[i] == 'N' || p[i] == 'n') { cfg->parity = UART_PARITY_NONE; stage = 4; /* num_end */ } else if (p[i] == 'O' || p[i] == 'o') { cfg->parity = UART_PARITY_ODD; stage = 4; /* num_end */ } else if (p[i] == 'E' || p[i] == 'e') { cfg->parity = UART_PARITY_EVEN; stage = 4; /* num_end */ } else { if (p[i] == '\n' || p[i] == '\r') { j = 0; item = 0; stage = 0; } } } else { j = 0; item = 0; stage = 0; } } else if (stage == 3) { /* numing */ if ((p[i] >= '0' && p[i] <= '9') || \ (p[i] >= 'A' && p[i] <= 'F') || \ (p[i] >= 'a' && p[i] <= 'f') || \ p[i] == 'x' || p[i] == 'X') { val[j++] = p[i]; } else { /* num_end */ val[j] = 0; /* set 0 for the end of string */ if (val[1] == 'x' || val[1] == 'X') { /* 16, hexadecimal */ val32 = str16_to_uint(val + 2); } else { /* 10, decimalism */ val32 = str10_to_uint(val); } if (item == 1) { /* addr */ cfg->addr = (uint8_t)(val32 & 0xFF); } else if (item == 2) { /* baudrate */ cfg->baudrate = val32; } else if (item == 4) { /* stopbits */ cfg->stopbits = (uint8_t)(val32 & 0xFF); } stage = 4; /* num_end */ } } else if (stage == 4) { /* num_end */ j = 0; item = 0; stage = 0; } else { stage = 0; } i++; if (i > len) { return; } } } void file_config_copy(struct file_config_s *dst, struct file_config_s *src) { uint32_t *s, *d; s = (uint32_t *)src; d = (uint32_t *)dst; for (uint32_t i = 0; i < sizeof(struct file_config_s) / 4; i++) { *d = *s; s++; d++; } } uint32_t file_config_get_free_addr(struct file_config_s *cfg) { uint32_t addr; volatile uint32_t *p; addr = ADDR_CONFIG; p = (volatile uint32_t *)addr; /* first run or data was dirty */ if (p[0] != addr || (p[0] + p[1] + p[2]) != p[3]) { file_secctor_erase(SECTOR_CONFIG); p = (volatile uint32_t *)cfg; cfg->id = addr; cfg->baudrate = UART_DEFAULT_BAUDRATE; cfg->parity = UART_DEFAULT_PARITY; cfg->stopbits = UART_DEFAULT_STOPBITS; cfg->addr = UART_DEFAULT_ADDR; cfg->resv = UART_DEFAULT_RESV; cfg->checksum = p[0] + p[1] + p[2]; file_config_write(addr, cfg); } for (addr = ADDR_CONFIG; addr < (ADDR_CONFIG + SIZE_CONFIG - sizeof(struct file_config_s)); addr += sizeof(struct file_config_s)) { p = (volatile uint32_t *)addr; if (addr == p[0]) { continue; } else if (0xFFFFFFFF == p[0]) { file_config_copy(cfg, (struct file_config_s *)(addr - sizeof(struct file_config_s))); return addr; } else { return 0; } } return 0; } void file_config_update(void) { FRESULT ret; UINT bc; uint32_t addr; volatile uint32_t *p; ret = f_open(&f, file_name[FILE_IDX_CONFIG], FA_READ); if (ret != FR_OK) { return; } ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc); if (ret != FR_OK || bc == 0) { f_close(&f); return; } f_close(&f); file_config_parse(file_buffer, (uint32_t)bc, &file_config_sd); addr = file_config_get_free_addr(&file_config_flash); if ((file_config_sd.baudrate == file_config_flash.baudrate) && \ (file_config_sd.parity == file_config_flash.parity) && \ (file_config_sd.stopbits == file_config_flash.stopbits) && \ (file_config_sd.addr == file_config_flash.addr)) { return; } /* sector full or dtaa dirty */ if (addr == 0) { file_secctor_erase(SECTOR_CONFIG); addr = ADDR_CONFIG; } p = (volatile uint32_t *)(&file_config_sd); file_config_sd.id = addr; file_config_sd.resv = UART_DEFAULT_RESV; file_config_sd.checksum = p[0] + p[1] + p[2]; file_config_write(addr, &file_config_sd); }