2024-03-16 22:28:04 +08:00
|
|
|
#include "ff.h"
|
|
|
|
|
#include "file.h"
|
|
|
|
|
#include "sdio_sd.h"
|
|
|
|
|
#include "partition.h"
|
2024-12-29 15:41:38 +08:00
|
|
|
#include "led.h"
|
2024-03-16 22:28:04 +08:00
|
|
|
|
|
|
|
|
#define RETRY_MAX (5)
|
|
|
|
|
|
|
|
|
|
FATFS fs;
|
|
|
|
|
FIL f;
|
|
|
|
|
uint8_t file_buffer[FILE_BUFF_SIZE];
|
|
|
|
|
TCHAR file_name[FILE_IDX_MAX][FILE_NAME_LEN];
|
|
|
|
|
|
|
|
|
|
static void file_copy_name(TCHAR *dst, TCHAR *src)
|
|
|
|
|
{
|
|
|
|
|
for (uint32_t i=0; i<FILE_NAME_LEN; i++) {
|
|
|
|
|
dst[i] = src[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t file_compare(TCHAR *name)
|
|
|
|
|
{
|
|
|
|
|
if (name[0] == '\0') {
|
|
|
|
|
return FILE_IDX_END;
|
|
|
|
|
} else if ((name[0] == 'C' || name[0] == 'c') && \
|
|
|
|
|
(name[1] == 'O' || name[1] == 'o') && \
|
|
|
|
|
(name[2] == 'N' || name[2] == 'n') && \
|
|
|
|
|
(name[3] == 'F' || name[3] == 'f') && \
|
|
|
|
|
(name[4] == 'I' || name[4] == 'i') && \
|
|
|
|
|
(name[5] == 'G' || name[5] == 'g') && \
|
|
|
|
|
(name[6] == '.' ) && \
|
|
|
|
|
(name[7] == 'T' || name[7] == 't') && \
|
|
|
|
|
(name[8] == 'X' || name[8] == 'x') && \
|
|
|
|
|
(name[9] == 'T' || name[9] == 't')) {
|
|
|
|
|
return FILE_IDX_CONFIG;
|
|
|
|
|
} else if ((name[0] == 'M' || name[0] == 'm') && \
|
|
|
|
|
(name[1] == 'A' || name[1] == 'a') && \
|
|
|
|
|
(name[2] == 'I' || name[2] == 'i') && \
|
|
|
|
|
(name[3] == 'N' || name[3] == 'n') && \
|
|
|
|
|
(name[8] == '.' ) && \
|
|
|
|
|
(name[9] == 'B' || name[9] == 'b') && \
|
|
|
|
|
(name[10] == 'I' || name[10] == 'i') && \
|
|
|
|
|
(name[11] == 'N' || name[11] == 'n')) {
|
|
|
|
|
return FILE_IDX_MAIN;
|
|
|
|
|
} else if ((name[0] == 'G' || name[0] == 'g') && \
|
|
|
|
|
(name[1] == 'A' || name[1] == 'a') && \
|
|
|
|
|
(name[2] == 'S' || name[2] == 's') && \
|
|
|
|
|
(name[8] == '.' ) && \
|
|
|
|
|
(name[9] == 'B' || name[9] == 'b') && \
|
|
|
|
|
(name[10] == 'I' || name[10] == 'i') && \
|
|
|
|
|
(name[11] == 'N' || name[11] == 'n')) {
|
|
|
|
|
if (name[3] == '1') {
|
|
|
|
|
return FILE_IDX_GAS1;
|
|
|
|
|
} else if (name[3] == '2') {
|
|
|
|
|
return FILE_IDX_GAS2;
|
|
|
|
|
} else if (name[3] == '3') {
|
|
|
|
|
return FILE_IDX_GAS3;
|
|
|
|
|
} else if (name[3] == '4') {
|
|
|
|
|
return FILE_IDX_GAS4;
|
|
|
|
|
} else {
|
|
|
|
|
return FILE_IDX_OTHER;
|
|
|
|
|
}
|
|
|
|
|
} else if ((name[0] == 'L' || name[0] == 'l') && \
|
|
|
|
|
(name[1] == 'A' || name[1] == 'a') && \
|
|
|
|
|
(name[2] == 'R' || name[2] == 'r') && \
|
|
|
|
|
(name[3] == 'K' || name[3] == 'k') && \
|
|
|
|
|
(name[4] == '1' ) && \
|
|
|
|
|
(name[5] == 'F' || name[5] == 'f') && \
|
|
|
|
|
(name[6] == 'Q' || name[6] == 'q') && \
|
|
|
|
|
(name[7] == '.' || name[7] == '.') && \
|
|
|
|
|
(name[8] == 'B' || name[8] == 'b') && \
|
|
|
|
|
(name[9] == 'I' || name[9] == 'i') && \
|
|
|
|
|
(name[10] == 'N' || name[10] == 'n')) {
|
|
|
|
|
return FILE_IDX_FW;
|
|
|
|
|
} else {
|
|
|
|
|
return FILE_IDX_OTHER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t file_init(void)
|
|
|
|
|
{
|
|
|
|
|
SD_Error sd_err;
|
|
|
|
|
FRESULT ret;
|
|
|
|
|
uint32_t retry;
|
|
|
|
|
DIR dir;
|
|
|
|
|
FILINFO fileinfo;
|
|
|
|
|
TCHAR name[FILE_NAME_LEN];
|
|
|
|
|
uint32_t mask = FILE_MASK_NULL;
|
|
|
|
|
|
|
|
|
|
retry = RETRY_MAX;
|
|
|
|
|
while (retry--) {
|
|
|
|
|
sd_err = SD_Init();
|
|
|
|
|
if (sd_err == SD_OK) {
|
|
|
|
|
break;
|
|
|
|
|
} else if (retry == 0) {
|
|
|
|
|
return FILE_MASK_NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retry = RETRY_MAX;
|
|
|
|
|
while (retry--) {
|
|
|
|
|
ret = f_mount(0, &fs);
|
|
|
|
|
if (ret == FR_OK) {
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
return FILE_MASK_NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retry = RETRY_MAX;
|
|
|
|
|
while (retry--) {
|
|
|
|
|
ret = f_getcwd (name, sizeof(name));
|
|
|
|
|
if (ret == FR_OK) {
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
return FILE_MASK_NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retry = RETRY_MAX;
|
|
|
|
|
while (retry--) {
|
|
|
|
|
ret = f_opendir(&dir, name);
|
|
|
|
|
if (ret == FR_OK) {
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
return FILE_MASK_NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
ret = f_readdir(&dir, &fileinfo);
|
|
|
|
|
if (ret == FR_OK) {
|
|
|
|
|
uint32_t idx = file_compare(fileinfo.fname);
|
|
|
|
|
if (idx == FILE_IDX_OTHER) {
|
|
|
|
|
continue;
|
|
|
|
|
} else if (idx == FILE_IDX_END) {
|
|
|
|
|
return mask;
|
|
|
|
|
} else if (idx == FILE_IDX_CONFIG) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_CONFIG;
|
|
|
|
|
} else if (idx == FILE_IDX_MAIN) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_MAIN;
|
|
|
|
|
} else if (idx == FILE_IDX_GAS1) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_GAS1;
|
|
|
|
|
} else if (idx == FILE_IDX_GAS2) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_GAS2;
|
|
|
|
|
} else if (idx == FILE_IDX_GAS3) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_GAS3;
|
|
|
|
|
} else if (idx == FILE_IDX_GAS4) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_GAS4;
|
|
|
|
|
} else if (idx == FILE_IDX_FW) {
|
|
|
|
|
file_copy_name(file_name[idx], fileinfo.fname);
|
|
|
|
|
mask |= FILE_MASK_FW;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return FILE_MASK_NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FILE_MASK_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void file_secctor_erase(uint16_t sector)
|
|
|
|
|
{
|
|
|
|
|
uint32_t addr, size;
|
|
|
|
|
|
|
|
|
|
if (sector == SECTOR_CONFIG) {
|
|
|
|
|
addr = ADDR_CONFIG;
|
|
|
|
|
size = SIZE_CONFIG;
|
|
|
|
|
} else if (sector == SECTOR_BITMAP) {
|
|
|
|
|
addr = ADDR_BITMAP;
|
|
|
|
|
size = SIZE_BITMAP;
|
|
|
|
|
} else if (sector == SECTOR_FW0) {
|
|
|
|
|
addr = ADDR_FW + SIZE_FW_SECTOR * 0;
|
|
|
|
|
size = SIZE_FW_SECTOR;
|
|
|
|
|
} else if (sector == SECTOR_FW1) {
|
|
|
|
|
addr = ADDR_FW + SIZE_FW_SECTOR * 1;
|
|
|
|
|
size = SIZE_FW_SECTOR;
|
|
|
|
|
} else if (sector == SECTOR_FW2) {
|
|
|
|
|
addr = ADDR_FW + SIZE_FW_SECTOR * 2;
|
|
|
|
|
size = SIZE_FW_SECTOR;
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
FLASH_Unlock();
|
|
|
|
|
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
|
|
|
|
|
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
|
|
|
|
|
if (FLASH_EraseSector(sector, VoltageRange_3) != FLASH_COMPLETE) {
|
2024-12-29 15:41:38 +08:00
|
|
|
led_indicate_error();
|
2024-03-16 22:28:04 +08:00
|
|
|
}
|
|
|
|
|
FLASH_Lock();
|
|
|
|
|
for (uint32_t i = 0; i < size; i += 4) {
|
|
|
|
|
if (*(volatile uint32_t *)(addr + i) == 0xFFFFFFFF) {
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
2024-12-29 15:41:38 +08:00
|
|
|
led_indicate_error();
|
2024-03-16 22:28:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* unit of len is byte, len must multiple of 4 */
|
|
|
|
|
void file_write_flash(uint32_t flash, uint8_t *buff, uint32_t len)
|
|
|
|
|
{
|
|
|
|
|
uint32_t i;
|
|
|
|
|
uint32_t *p_buff;
|
|
|
|
|
volatile uint32_t *p_flash;
|
|
|
|
|
|
|
|
|
|
/* program data */
|
|
|
|
|
p_buff = (uint32_t *)buff;
|
|
|
|
|
FLASH_Unlock();
|
|
|
|
|
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
|
|
|
|
|
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
|
|
|
|
|
for (i = 0; i < len / 4; i++) {
|
|
|
|
|
if (FLASH_ProgramWord(flash + i * 4, p_buff[i]) != FLASH_COMPLETE) {
|
2024-12-29 15:41:38 +08:00
|
|
|
led_indicate_error();
|
2024-03-16 22:28:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FLASH_Lock();
|
|
|
|
|
/* check data */
|
|
|
|
|
p_flash = (volatile uint32_t *)flash;
|
|
|
|
|
for (i = 0; i < len / 4; i++) {
|
|
|
|
|
if (p_flash[i] != p_buff[i]) {
|
2024-12-29 15:41:38 +08:00
|
|
|
led_indicate_error();
|
2024-03-16 22:28:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|