lark1fq/bootloader/src/config.c

318 lines
9.9 KiB
C
Raw Normal View History

2024-03-16 22:28:04 +08:00
#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; k<sizeof(val); k++) {
val[k] = 0;
}
p[len] = 0;
/* default value */
cfg->baudrate = 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);
}