mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-12-14 01:08:49 +08:00
fix: FM25Q16B fails to run due to FM25Q16A patch
This commit is contained in:
@@ -43,7 +43,9 @@
|
|||||||
extern bool IRAM_FUNC_ATTR spi_user_cmd(spi_cmd_dir_t mode, spi_cmd_t *p_cmd);
|
extern bool IRAM_FUNC_ATTR spi_user_cmd(spi_cmd_dir_t mode, spi_cmd_t *p_cmd);
|
||||||
extern uint32_t IRAM_FUNC_ATTR spi_flash_get_id(void);
|
extern uint32_t IRAM_FUNC_ATTR spi_flash_get_id(void);
|
||||||
|
|
||||||
static void FLASH_PATCH_TEXT_ATTR fm_send_spi_cmd(uint8_t cmd, uint8_t cmd_len, uint32_t addr, uint8_t addr_len, void* mosi_data, int mosi_len, void* miso_data, int miso_len, uint8_t dummy_bits)
|
static bool FLASH_PATCH_TEXT_ATTR double_check_fm25q16a(void);
|
||||||
|
|
||||||
|
static void FLASH_PATCH_TEXT_ATTR fm_send_spi_cmd(uint8_t cmd, uint8_t cmd_len, uint32_t addr, uint8_t addr_len, const void* mosi_data, int mosi_len, void* miso_data, int miso_len, uint8_t dummy_bits)
|
||||||
{
|
{
|
||||||
bool write_mode = false;
|
bool write_mode = false;
|
||||||
uint32_t data_bytes = 0;
|
uint32_t data_bytes = 0;
|
||||||
@@ -234,13 +236,6 @@ static void FLASH_PATCH_TEXT_ATTR fm_cam_read_pre(void)
|
|||||||
fm_cam_pre_cmd_generic(send_list, 7);
|
fm_cam_pre_cmd_generic(send_list, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FLASH_PATCH_TEXT_ATTR fm_soft_reset()
|
|
||||||
{
|
|
||||||
fm_send_spi_cmd(0x66, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
|
||||||
// patch_delay(1);
|
|
||||||
fm_send_spi_cmd(0x99, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool FLASH_PATCH_TEXT_ATTR fm_flash_wait_idle()
|
static bool FLASH_PATCH_TEXT_ATTR fm_flash_wait_idle()
|
||||||
{
|
{
|
||||||
uint8_t status = 0x1;
|
uint8_t status = 0x1;
|
||||||
@@ -250,6 +245,30 @@ static bool FLASH_PATCH_TEXT_ATTR fm_flash_wait_idle()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FLASH_PATCH_TEXT_ATTR fm_soft_reset()
|
||||||
|
{
|
||||||
|
fm_send_spi_cmd(0x66, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
||||||
|
// patch_delay(1);
|
||||||
|
fm_send_spi_cmd(0x99, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
||||||
|
fm_flash_wait_idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t FLASH_PATCH_RODATA_ATTR uid_cmd[4] = {0x00, 0x03, 0xc0, 0x40};
|
||||||
|
static const uint8_t FLASH_PATCH_RODATA_ATTR uid_data[4] = {0x00, 0x01, 0x00, 0x8F};
|
||||||
|
|
||||||
|
static bool FLASH_PATCH_TEXT_ATTR fm_set_uid_flag(void)
|
||||||
|
{
|
||||||
|
fm_soft_reset();
|
||||||
|
fm_cam_cmd_start();
|
||||||
|
fm_send_spi_cmd(0x32, 8, 0, 0, uid_cmd, 4 * 8, NULL, 0, 0);
|
||||||
|
fm_cam_cmd_end();
|
||||||
|
fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
||||||
|
fm_send_spi_cmd(0x02, 8, 0, 0, uid_data, 4 * 8, 0, 0, 0);
|
||||||
|
fm_flash_wait_idle();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool FLASH_PATCH_TEXT_ATTR fm_erase_sector(uint32_t addr)
|
static bool FLASH_PATCH_TEXT_ATTR fm_erase_sector(uint32_t addr)
|
||||||
{
|
{
|
||||||
// write en
|
// write en
|
||||||
@@ -309,7 +328,7 @@ static bool FLASH_PATCH_TEXT_ATTR fm_cam_erase_and_fix(uint8_t (*buf)[32])
|
|||||||
fm_send_spi_cmd(0x03, 8, 0x20 * line, 24, 0, 0, cam_rd, 32*8, 0);
|
fm_send_spi_cmd(0x03, 8, 0x20 * line, 24, 0, 0, cam_rd, 32*8, 0);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (idx = 0;idx < 8; idx++) {
|
for (idx = 0;idx < 8; idx++) {
|
||||||
uint32_t* p = buf[line];
|
uint32_t* p = (uint32_t*)buf[line];
|
||||||
if (cam_rd[idx] != p[idx]) {
|
if (cam_rd[idx] != p[idx]) {
|
||||||
found_error = true;
|
found_error = true;
|
||||||
ERROR(FLASH_PATCH_STR("erase check error, retry...%d, %d, 0x%08x\n"), retry, idx, cam_rd[idx]);
|
ERROR(FLASH_PATCH_STR("erase check error, retry...%d, %d, 0x%08x\n"), retry, idx, cam_rd[idx]);
|
||||||
@@ -383,6 +402,7 @@ static bool FLASH_PATCH_TEXT_ATTR fm_cam_erase_and_fix(uint8_t (*buf)[32])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fm_set_uid_flag();
|
||||||
INFO(FLASH_PATCH_STR("CAM prog done !!!\n"));
|
INFO(FLASH_PATCH_STR("CAM prog done !!!\n"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -440,40 +460,62 @@ static bool FLASH_PATCH_TEXT_ATTR esp_fm_check_uid()
|
|||||||
static bool FLASH_PATCH_TEXT_ATTR fm_cam_check_buf_valid(uint8_t (*buf)[32])
|
static bool FLASH_PATCH_TEXT_ATTR fm_cam_check_buf_valid(uint8_t (*buf)[32])
|
||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
// cmd 1.
|
uint8_t count = 3;
|
||||||
fm_cam_read_pre();
|
|
||||||
|
|
||||||
int i = 0, j = 0;
|
while (!res && count--) {
|
||||||
for (i = 0; i < 20; i++) {
|
// cmd 1.
|
||||||
// read buf
|
fm_cam_read_pre();
|
||||||
fm_send_spi_cmd(0x03, 8, 0x20 * i, 24, 0, 0, &buf[i][0], 32*8, 0);
|
|
||||||
for (j = 0; j < 32; j++) {
|
int i = 0, j = 0;
|
||||||
DEBUG(FLASH_PATCH_STR("%02x "), buf[i][j]);
|
for (i = 0; i < 20; i++) {
|
||||||
if ((j + 1) % 16 == 0) {
|
// read buf
|
||||||
DEBUG(FLASH_PATCH_STR("\n"));
|
fm_send_spi_cmd(0x03, 8, 0x20 * i, 24, 0, 0, &buf[i][0], 32*8, 0);
|
||||||
INFO(FLASH_PATCH_STR("\r"));
|
for (j = 0; j < 32; j++) {
|
||||||
|
DEBUG(FLASH_PATCH_STR("%02x "), buf[i][j]);
|
||||||
|
if ((j + 1) % 16 == 0) {
|
||||||
|
DEBUG(FLASH_PATCH_STR("\n"));
|
||||||
|
INFO(FLASH_PATCH_STR("\r"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buf[0][0] == 0x55 && buf[0][4] == 0xaa \
|
||||||
|
&& buf[4][0] == 0x00 \
|
||||||
|
&& buf[10][0] == 0x1 && buf[10][20] == 0xff\
|
||||||
|
&& buf[11][0] == 0x1 && buf[11][20] == 0xff\
|
||||||
|
&& buf[12][0] == 0x1 && buf[12][20] == 0xff\
|
||||||
|
&& buf[13][0] == 0x1 && buf[13][20] == 0xff\
|
||||||
|
&& buf[14][0] == 0x1 && buf[14][20] == 0xff\
|
||||||
|
&& buf[15][0] == 0x1 && buf[15][20] == 0xff\
|
||||||
|
&& buf[16][0] == 0x1 && buf[16][20] == 0xff\
|
||||||
|
&& buf[17][0] == 0x1 && buf[17][20] == 0xff
|
||||||
|
) {
|
||||||
|
INFO(FLASH_PATCH_STR("CAM buffer check valid !!!\n"));
|
||||||
|
res = true;
|
||||||
|
} else {
|
||||||
|
INFO(FLASH_PATCH_STR("CAM buffer check IN-Valid !!!\n"));
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// while(1);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool FLASH_PATCH_TEXT_ATTR fm_cam_check_uid(void)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
uint8_t count = 3;
|
||||||
|
uint8_t uid[8];
|
||||||
|
|
||||||
|
while (!res && count--) {
|
||||||
|
fm_send_spi_cmd(0x4B, 8, 0, 0, 0, 0, &uid[0], 8*8, 4*8);
|
||||||
|
DEBUG(FLASH_PATCH_STR("uid 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"), uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
|
||||||
|
if ((((uid[1]&0xf0) == 0x0) && ((uid[0]&0x70) == 0))
|
||||||
|
|| (((uid[1]&0xf0) != 0x0))) {
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0][0] == 0x55 && buf[0][4] == 0xaa \
|
|
||||||
&& buf[4][0] == 0x00 \
|
|
||||||
&& buf[10][0] == 0x1 && buf[10][20] == 0xff\
|
|
||||||
&& buf[11][0] == 0x1 && buf[11][20] == 0xff\
|
|
||||||
&& buf[12][0] == 0x1 && buf[12][20] == 0xff\
|
|
||||||
&& buf[13][0] == 0x1 && buf[13][20] == 0xff\
|
|
||||||
&& buf[14][0] == 0x1 && buf[14][20] == 0xff\
|
|
||||||
&& buf[15][0] == 0x1 && buf[15][20] == 0xff\
|
|
||||||
&& buf[16][0] == 0x1 && buf[16][20] == 0xff\
|
|
||||||
&& buf[17][0] == 0x1 && buf[17][20] == 0xff
|
|
||||||
) {
|
|
||||||
INFO(FLASH_PATCH_STR("CAM buffer check valid !!!\n"));
|
|
||||||
res = true;
|
|
||||||
} else {
|
|
||||||
INFO(FLASH_PATCH_STR("CAM buffer check IN-Valid !!!\n"));
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
// while(1);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,6 +523,14 @@ static bool FLASH_PATCH_TEXT_ATTR fm_fix_cam()
|
|||||||
{
|
{
|
||||||
uint8_t check_buf[20][32];
|
uint8_t check_buf[20][32];
|
||||||
|
|
||||||
|
if (fm_cam_check_uid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!double_check_fm25q16a()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (fm_cam_check_buf_valid(check_buf) == false) {
|
if (fm_cam_check_buf_valid(check_buf) == false) {
|
||||||
ERROR(FLASH_PATCH_STR("Cam buf not valid\n"));
|
ERROR(FLASH_PATCH_STR("Cam buf not valid\n"));
|
||||||
return esp_fm_check_uid();
|
return esp_fm_check_uid();
|
||||||
@@ -489,6 +539,7 @@ static bool FLASH_PATCH_TEXT_ATTR fm_fix_cam()
|
|||||||
|
|
||||||
if ((check_buf[3][0] & 0x08) == 0x08) {
|
if ((check_buf[3][0] & 0x08) == 0x08) {
|
||||||
INFO(FLASH_PATCH_STR("Bit3 == 1, already fixed....\n"));
|
INFO(FLASH_PATCH_STR("Bit3 == 1, already fixed....\n"));
|
||||||
|
fm_set_uid_flag();
|
||||||
fm_soft_reset();
|
fm_soft_reset();
|
||||||
} else {
|
} else {
|
||||||
check_buf[3][0] |= 0x08;
|
check_buf[3][0] |= 0x08;
|
||||||
@@ -515,25 +566,83 @@ static uint32_t FLASH_PATCH_TEXT_ATTR fm_flash_id(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool FLASH_PATCH_TEXT_ATTR double_check_fm25q16a(void)
|
||||||
|
{
|
||||||
|
uint32_t addr = 0x10;
|
||||||
|
uint8_t value[6];
|
||||||
|
fm_send_spi_cmd(0x9f, 8, 0, 0, 0, 0, NULL, 0, 0);
|
||||||
|
|
||||||
|
fm_cam_cmd_start();
|
||||||
|
fm_send_spi_cmd(0x90, 8, addr, 3 * 8, 0, 0, value, sizeof(value) * 8, 0);
|
||||||
|
fm_cam_cmd_end();
|
||||||
|
DEBUG(FLASH_PATCH_STR("fm25q16a confirm: "));
|
||||||
|
for (uint loop = 0; loop < sizeof(value); loop++) {
|
||||||
|
DEBUG(FLASH_PATCH_STR(" 0x%02x"), value[loop]);
|
||||||
|
if (value[loop] != 0xA1) {
|
||||||
|
DEBUG(FLASH_PATCH_STR("\r\n"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG(FLASH_PATCH_STR("\r\n"));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool FLASH_PATCH_TEXT_ATTR is_fm25q16a(void)
|
||||||
|
{
|
||||||
|
uint8_t status = 0x0;
|
||||||
|
uint8_t count = 3;
|
||||||
|
uint8_t value = 0;
|
||||||
|
|
||||||
|
while (((status&0x20) == 0x0) && count--) {
|
||||||
|
fm_send_spi_cmd(0x50, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
||||||
|
value = 0x80;
|
||||||
|
fm_send_spi_cmd(0x01, 1*8, 0, 0, &value, 1*8, NULL, 0, 0);
|
||||||
|
fm_send_spi_cmd(0x50, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
||||||
|
value = 0x03;
|
||||||
|
fm_send_spi_cmd(0x31, 1*8, 0, 0, &value, 1*8, NULL, 0, 0);
|
||||||
|
fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0);
|
||||||
|
value = 0x02;
|
||||||
|
fm_send_spi_cmd(0x31, 1*8, 0, 0, &value, 1*8, NULL, 0, 0);
|
||||||
|
|
||||||
|
fm_flash_wait_idle();
|
||||||
|
fm_send_spi_cmd(0x35, 1*8, 0x0, 0, NULL, 0, &status, 1*8, 0);
|
||||||
|
|
||||||
|
fm_soft_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status&0x20) == 0) {
|
||||||
|
DEBUG(FLASH_PATCH_STR("It's FM25Q16A\n"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(FLASH_PATCH_STR("It's FM25Q16B\n"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int FLASH_PATCH_TEXT_ATTR fm25q16a_apply_patch_0()
|
int FLASH_PATCH_TEXT_ATTR fm25q16a_apply_patch_0()
|
||||||
{
|
{
|
||||||
bool res = false;
|
bool res = true;
|
||||||
|
|
||||||
spi_state_t state;
|
spi_state_t state;
|
||||||
spi_enter(&state);
|
spi_enter(&state);
|
||||||
|
|
||||||
uint32_t flash_id = fm_flash_id();
|
uint32_t flash_id = fm_flash_id();
|
||||||
DEBUG(FLASH_PATCH_STR("Flash id: 0x%x\n"), flash_id);
|
DEBUG(FLASH_PATCH_STR("Flash id: 0x%x\n"), flash_id);
|
||||||
|
|
||||||
WDT_FEED();
|
WDT_FEED();
|
||||||
if (flash_id == 0xa14015) {
|
if (flash_id == 0xa14015) {
|
||||||
INFO(DRAM_STR("Found FM25Q16A, check CAM buf\n"));
|
fm_soft_reset();
|
||||||
res = fm_fix_cam();
|
INFO(DRAM_STR("Found FM25Q16A or FM25Q16B\n"));
|
||||||
|
if(is_fm25q16a()) {
|
||||||
|
INFO(DRAM_STR("Found FM25Q16A, check CAM buf\n"));
|
||||||
|
res = fm_fix_cam();
|
||||||
|
}
|
||||||
} else if ((flash_id&0xffffff) == 0x0 || (flash_id&0xffffff) == 0xffffff) {
|
} else if ((flash_id&0xffffff) == 0x0 || (flash_id&0xffffff) == 0xffffff) {
|
||||||
INFO(FLASH_PATCH_STR("Found ID error, recover default CAM buf\n"));
|
INFO(FLASH_PATCH_STR("Found ID error, recover default CAM buf\n"));
|
||||||
res = esp_fm_check_uid();
|
res = esp_fm_check_uid();
|
||||||
} else {
|
} else {
|
||||||
INFO(FLASH_PATCH_STR("Normal flash, continue...\n"));
|
INFO(FLASH_PATCH_STR("Normal flash, continue...\n"));
|
||||||
res = true;
|
|
||||||
}
|
}
|
||||||
WDT_FEED();
|
WDT_FEED();
|
||||||
|
|
||||||
@@ -541,7 +650,8 @@ int FLASH_PATCH_TEXT_ATTR fm25q16a_apply_patch_0()
|
|||||||
|
|
||||||
if (res != true) {
|
if (res != true) {
|
||||||
fm_printf(FLASH_PATCH_STR("fix fail\n"));
|
fm_printf(FLASH_PATCH_STR("fix fail\n"));
|
||||||
return 1;
|
// we should keep running
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fm_printf(FLASH_PATCH_STR("fix done\n"));
|
fm_printf(FLASH_PATCH_STR("fix done\n"));
|
||||||
|
|||||||
Reference in New Issue
Block a user