flashaddr_t flashSectorBegin(flashsector_t sector) { flashaddr_t address = FLASH_BASE; while (sector > 0) { --sector; address += flashSectorSize(sector); } return address; }
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 flashSectorErase(flashsector_t sector) { /* Unlock flash for write access */ if (flashUnlock() == CH_FAILED) return FLASH_RETURN_NO_PERMISSION; /* Wait for any busy flags. */ flashWaitWhileBusy(); /* Setup parallelism before any program/erase */ FLASH->CR &= ~FLASH_CR_PSIZE_MASK; FLASH->CR |= FLASH_CR_PSIZE_VALUE; /* Start deletion of sector. * SNB(3:1) is defined as: * 0000 sector 0 * 0001 sector 1 * ... * 1011 sector 11 * others not allowed */ FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3); if (sector & 0x1) FLASH->CR |= FLASH_CR_SNB_0; if (sector & 0x2) FLASH->CR |= FLASH_CR_SNB_1; if (sector & 0x4) FLASH->CR |= FLASH_CR_SNB_2; if (sector & 0x8) FLASH->CR |= FLASH_CR_SNB_3; FLASH->CR |= FLASH_CR_SER; FLASH->CR |= FLASH_CR_STRT; /* Wait until it's finished. */ flashWaitWhileBusy(); /* Sector erase flag does not clear automatically. */ FLASH->CR &= ~FLASH_CR_SER; /* Lock flash again */ flashLock() ; /* Check deleted sector for errors */ if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE) return FLASH_RETURN_BAD_FLASH; /* Sector is not empty despite the erase cycle! */ /* Successfully deleted sector */ 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; }