Other Parts Discussed in Thread: UNIFLASH, C2000WARE
Hi All,
I am using flash api to update firmware over CAN on device using f280041 (it is a port of project on f28035).
And I ran into several issues with flashed data to be NOT correct and it seems that it comes down to the erase, because if I use uniflash to erase given sections, the data is correct.
The second problem problem is coupled to the fist one, and that is that both Fapi_doBlankCheck() and Fapi_doVerify() return success when clearly at least one of them should fail (if the contents of the flash are incorrect).
CPU is running from external crystal at frequency 100MHz, all "bootloader" code runs in RAM, so all further snippets are running from RAM.
I will include code snippets and describe situation:
First the initialisation:
static int flash_internal_init(struct net_dev *dev) { int ret = 0; struct system * sys = system_handle(); int clk_mhz = sys->clk.cpu.freq / 1000000; // sys->clk.cpu.freq holds CPU clock speed in Hz Fapi_StatusType f_api_status; EALLOW; // Increase wait states of flash for write/erase operations
// (4 should be enough for 100MHz and external XTAL, but use 5 to be sure... Flash_setWaitstates(FLASH0CTRL_BASE, 5); f_api_status = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, clk_mhz); if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_INIT); goto flash_init_exit; } f_api_status = Fapi_setActiveFlashBank(Fapi_FlashBank0); if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_SELECT); goto flash_init_exit; } flash_init_exit: EDIS; return ret; }
Then the erase ...
const uint16_t SECT_COUNT = 32; // Base of each flash sector const uint32_t SECT_BASE[32] = { 0x80000, 0x81000, 0x82000, 0x83000, 0x84000, 0x85000, 0x86000, 0x87000, 0x88000, 0x89000, 0x8a000, 0x8b000, 0x8c000, 0x8d000, 0x8e000, 0x8f000, 0x90000, 0x91000, 0x92000, 0x93000, 0x94000, 0x95000, 0x96000, 0x97000, 0x98000, 0x99000, 0x9a000, 0x9b000, 0x9c000, 0x9d000, 0x9e000, 0x9f000, }; const uint32_t SECT_LEN[32] = { 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, 0x01000, }; const uint32_t SECT_MASK[32] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, }; static int flash_internal_erase(uint32_t sector) { int i, ret = 0; Fapi_StatusType f_api_status; Fapi_FlashStatusType f_api_status_flash; Fapi_FlashStatusWordType f_api_flash_status_word; EALLOW; /* Walk through all sectors masked */ for (i = 0; i < SECT_COUNT; ++i) { if (sector & SECT_MASK[i]) { /* We have match, erase */ f_api_status = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *)SECT_BASE[i]); /* Wait for the fapi command */ while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady) { } if (f_api_status != Fapi_Status_Success) { ret = -(FLASH_E_ERASE | f_api_status); goto flash_erase_exit; } f_api_status_flash = Fapi_getFsmStatus(); if (f_api_status_flash != 0) { ret = -(FLASH_E_FSM_STATUS_ERASE | f_api_status_flash); goto flash_erase_exit; } f_api_status = Fapi_doBlankCheck((uint32_t *)(SECT_BASE[i]), B_8KSector_u32length, &f_api_flash_status_word); if (f_api_status != Fapi_Status_Success) { ret = -(FLASH_E_BLANK | f_api_status); goto flash_erase_exit; } } } flash_erase_exit: EDIS; return ret; }
and finally flash
#define FLASH_STRIDE 4
int flash_internal_write(struct net_dev *dev, struct net_buf *buf) { struct hal * hal = hal_inst(); struct system * sys = system_handle(); struct flash_buf * fls = (struct flash_buf *)buf->data; uint32_t * to_verify = (uint32_t *)fls->buf; uint16_t i; int ret = 0; Fapi_StatusType f_api_status; Fapi_FlashStatusType f_api_status_flash; Fapi_FlashStatusWordType f_api_flash_status_word; EALLOW; for (i = 0; i < fls->len; i += FLASH_STRIDE) { f_api_status = Fapi_issueProgrammingCommand((uint32_t *)(fls->addr + i), (fls->buf + i), FLASH_STRIDE, 0, 0, Fapi_AutoEccGeneration); while (Fapi_checkFsmForReady() == Fapi_Status_FsmBusy) ; if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_PROGRAM); goto flash_write_exit; } f_api_status_flash = Fapi_getFsmStatus(); if (f_api_status_flash != 0) { ret = -(FLASH_E_FSM_STATUS_WRITE | f_api_status_flash); goto flash_write_exit; } // Verify f_api_status = Fapi_doVerify((uint32_t *)(fls->addr + i), FLASH_STRIDE / 2, to_verify + (i / 2), &f_api_flash_status_word); if (f_api_status != Fapi_Status_Success) { ret = -(f_api_status | FLASH_E_VERIFY); goto flash_write_exit; } } flash_write_exit: EDIS; return ret; }
All the rest of the code is correctly working on f28035
EDIT:
Noteworthy thing is also that when the firmware is loaded by Flash API (regardless if successful or not) and I want to see the actual data in the flash and I do memory readback (actual readback OR verify of a hex file that I have loaded using my bootloader) in Uniflash I get this error:
[ERROR] C28xx_CPU1: File Loader: Verification failed: Memory map prevented reading 0x88000@Program
or for readback:
Which seems to randomly appear on 88000, 89000 or 8a0000 start address... Which makes whole debugging more difficult..
Now the exact same happens now if I load the hex file using Uniflash (but the firmware boots which means that it successfully loads.
---
And it also happend if I ask flash api to erase sectors (Bank0 sector 3 through 10) all sectors before sector 8 read back 0xFFFF on all addresses, but sector 8 again shows ???? instead with error message about memory map preventing reading.
And this is only cured (i.e. I see 0xFFFF if I do erase of sectors 3 thorugh 10 using Uniflash instead... (after this bootloader also successfully loads firmware which makes sense a sector 8 is now correctly erased...)
In conclusion there are several questions to me..
Why does Flash API proceed programming if sector 8 would not be erased correctly?
Why does not blank check reveal that it was not erased?
And finally why is uniflash unable to read back? (it could be that the sector is really erased, but I cannot know without readback...)
Also why does it only happens on sectors 8 and higher?