int flashErase(flashaddr_t address, size_t size) { while (size > 0) { flashsector_t sector = flashSectorAt(address); int err = flashSectorErase(sector); if (err != FLASH_RETURN_SUCCESS) return err; address = flashSectorEnd(sector); size_t sector_size = flashSectorSize(sector); if (sector_size >= size) break; size -= sector_size; } return FLASH_RETURN_SUCCESS; }
int flashIHexFile(FIL* file) { IHexRecord irec; flashsector_t sector; bool erasedSectors[FLASH_SECTOR_COUNT] = { FALSE }; flashaddr_t baseAddress = 0; flashaddr_t address = 0; while (Read_IHexRecord(&irec, file) == IHEX_OK) { switch (irec.type) { case IHEX_TYPE_00: /**< Data Record */ /* Compute the target address in flash */ address = baseAddress + irec.address; /* Erase the corresponding addresses if needed */ for (sector = flashSectorAt(address); sector <= flashSectorAt(address + irec.dataLen - 1); ++sector) { /* Check if the sector has been erased during this IHex flashing procedure to prevent erasing already written data */ if (erasedSectors[sector] == TRUE) continue; /* Check if the sector in flash needs to be erased */ if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE) { /* Erase the sector */ if (flashSectorErase(sector) != FLASH_RETURN_SUCCESS) return BOOTLOADER_ERROR_BADFLASH; } /* Set the erased flag to prevent erasing the same sector twice during the IHex flashing procedure */ erasedSectors[sector] = TRUE; } /* Write the data in flash */ if (flashWrite(address, (const char*)irec.data, irec.dataLen) != FLASH_RETURN_SUCCESS) return BOOTLOADER_ERROR_BADFLASH; break; case IHEX_TYPE_04: /**< Extended Linear Address Record */ /* Compute the base address of the following data records */ baseAddress = irec.data[0]; baseAddress <<= 8; baseAddress += irec.data[1]; baseAddress <<= 16; break; case IHEX_TYPE_01: /**< End of File Record */ /* Check that the end of file record is at the end of the file... */ return f_eof(file) ? BOOTLOADER_SUCCESS : BOOTLOADER_ERROR_BADHEX; case IHEX_TYPE_05: /**< Start Linear Address Record */ /* Ignored */ break; case IHEX_TYPE_02: /**< Extended Segment Address Record */ case IHEX_TYPE_03: /**< Start Segment Address Record */ /* Not supported */ return BOOTLOADER_ERROR_BADHEX; } } return BOOTLOADER_ERROR_BADHEX; }
void cmd_flash(BaseSequentialStream *chp, int argc, char *argv[]) { int j, blockoffset; int status, address; char readBufferBefore[32]; flashsector_t i; chprintf(chp, "Flash test UTIL\r\n"); /* Handle warnings: */ if (argc >= 1) { if (strncmp(argv[0], "write", sizeof("write")) == 0) { if (argc >= 3) { blockoffset = atoi(argv[1]); if (blockoffset < 0 || blockoffset > FLASH_BLOCK_TESTCASE_COUNT) { chprintf(chp, "Offset must between %d and %d. Actual one was: %d \r\n", 0, FLASH_BLOCK_TESTCASE_COUNT, blockoffset); return; } /* use the fourth memory block for the tests */ address = FLASH_BASEADDR + (blockoffset * FLASH_BLOCKSIZE); /* extract the new value to store into it */ readBufferBefore[0] = atoi(argv[2]); status = flashWrite(address, readBufferBefore, FLASH_BLOCKSIZE); if (status != FLASH_RETURN_SUCCESS) { chprintf(chp, "Writing returned %d \r\n", status); return; } chprintf(chp, "test sector %u : stored at 0x%x %d\r\n", flashSectorAt(address), address, readBufferBefore[0]); } else { chprintf(chp, "flash needs additional parameter\r\n"); } } else if (strncmp(argv[0], "read", sizeof("read")) == 0) { for (i = 0; i < FLASH_BLOCK_TESTCASE_COUNT; ++i) { address = FLASH_BASEADDR + (i * FLASH_BLOCKSIZE); chprintf(chp, "test sector %u\t: 0x%x -> 0x%x (%u bytes)\r\n", flashSectorAt(address), address, address + FLASH_BLOCKSIZE, FLASH_BLOCKSIZE); status = flashRead(address, readBufferBefore, FLASH_BLOCKSIZE); if (status != FLASH_RETURN_SUCCESS) { chprintf(chp, "Reading returned %d\r\n", status); return; } for (j = 0; j < FLASH_BLOCKSIZE; j++) { chprintf(chp, "%02X ", readBufferBefore[j]); } chprintf(chp, "\r\n"); } } } else { flash_usage(chp); } }