void stm32_flash_unlock(void) { sem_lock(); flash_unlock(STM32_FLASH_BANK0_BASE); #if defined(STM32_FLASH_DUAL_BANK) flash_unlock(STM32_FLASH_BANK1_BASE); #endif sem_unlock(); }
/** Erase one sector starting at defined address * * The address should be at sector boundary. This function does not do any check for address alignments * @param obj The flash object * @param address The sector starting address * @return 0 for success, -1 for error */ int32_t flash_erase_sector(flash_t *obj, uint32_t address) { uint32_t number; sector_t sector_info; int32_t flash_state = 0; flash_unlock(); /* clear FLASH flag */ fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); /* make sure the address is a right page address */ sector_info = flash_sector_info_get(address); if (11U >= sector_info.sector_num) { number = sector_info.sector_num; } else if (23U >= sector_info.sector_num) { number = sector_info.sector_num + 4U; } else { number = sector_info.sector_num - 12U; } if (FMC_READY != fmc_sector_erase(CTL_SN(number))) { flash_state = -1; } flash_lock(); return flash_state; }
/** Program pages starting at defined address * * The pages should not cross multiple sectors. * This function does not do any check for address alignments or if size is aligned to a page size. * @param obj The flash object * @param address The sector starting address * @param data The data buffer to be programmed * @param size The number of bytes to program * @return 0 for success, -1 for error */ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) { uint32_t *p_data; p_data = (uint32_t *)data; uint32_t num = 0; int32_t flash_state = 0; flash_unlock(); /* clear FLASH flag */ fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); if (size % 4) { num = size / 4 + 1; } else { num = size / 4; } for (uint32_t i = 0; i < num; i++) { if (FMC_READY != fmc_word_program(address, *(p_data + i))) { flash_state = -1; break; } address += 4; } flash_lock(); return flash_state; }
boolean DueFlash::write(uint32_t address, byte value) { uint32_t retCode; uint32_t byteLength = 1; byte *data; retCode = flash_unlock((uint32_t)FLASH_START+address, (uint32_t)FLASH_START+address + byteLength - 1, 0, 0); if (retCode != FLASH_RC_OK) { _FLASH_DEBUG("Failed to unlock flash for write\n"); return false; } // write data retCode = flash_write((uint32_t)FLASH_START+address, &value, byteLength, 1); //retCode = flash_write((uint32_t)FLASH_START, data, byteLength, 1); if (retCode != FLASH_RC_OK) { _FLASH_DEBUG("Flash write failed\n"); return false; } // Lock page retCode = flash_lock((uint32_t)FLASH_START+address, (uint32_t)FLASH_START+address + byteLength - 1, 0, 0); if (retCode != FLASH_RC_OK) { _FLASH_DEBUG("Failed to lock flash page\n"); return false; } return true; }
static void mem_flash_write(isp_addr_t dst, const void *src, uint16_t nbytes) { uint32_t ul_rc; if (((dst - IFLASH0_ADDR) % LOCK_REGION_SIZE) == 0) { /* Unlock page */ //ul_rc = flash_unlock(dst, dst+nbytes-1, 0, 0); ul_rc = flash_unlock(dst, dst+LOCK_REGION_SIZE-1, 0, 0); if (ul_rc != FLASH_RC_OK) { return; } /* The EWP command is not supported for non-8KByte sectors in all devices * SAM4 series, so an erase command is requried before the write operation. */ //ul_rc = flash_erase_sector(dst); ul_rc = flash_erase_page(dst, IFLASH_ERASE_PAGES_16); if (ul_rc != FLASH_RC_OK) { return; } } /* Write page */ flash_write(dst, src, nbytes, 0); }
// Switch into boot mode and reset void EraseAndReset() { cpu_irq_disable(); #if SAM4S # define IFLASH_ADDR IFLASH0_ADDR # define IFLASH_PAGE_SIZE IFLASH0_PAGE_SIZE # define IFLASH_NB_OF_PAGES (IFLASH0_SIZE / IFLASH_PAGE_SIZE) #endif #if SAM3XA # define IFLASH_ADDR IFLASH0_ADDR # define IFLASH_PAGE_SIZE IFLASH0_PAGE_SIZE # define IFLASH_NB_OF_PAGES ((IFLASH1_ADDR + IFLASH1_SIZE - IFLASH_ADDR) / IFLASH_PAGE_SIZE) #endif for(size_t i = 0; i <= IFLASH_NB_OF_PAGES; i++) { wdt_restart(WDT); size_t pageStartAddr = IFLASH_ADDR + i * IFLASH_PAGE_SIZE; flash_unlock(pageStartAddr, pageStartAddr + IFLASH_PAGE_SIZE - 1, nullptr, nullptr); } flash_clear_gpnvm(1); // tell the system to boot from ROM next time rstc_start_software_reset(RSTC); for(;;) {} }
// Запись флага. modbus_rtu_error_t boot_modbus_on_write_coil(uint16_t address, modbus_rtu_coil_value_t value) { switch(address){ default: return MODBUS_RTU_ERROR_INVALID_ADDRESS; case BOOT_MODBUS_COIL_PAGE_ERASE: if(value == MODBUS_RTU_COIL_ON){ if(!flash_unlock()) return MODBUS_RTU_ERROR_NONRECOVERABLE; if(!flash_page_erase(flash_page_address(boot_modbus.page_number))){ flash_lock(); return MODBUS_RTU_ERROR_NONRECOVERABLE; } flash_lock(); } break; case BOOT_MODBUS_COIL_RUN_APP: if(value == MODBUS_RTU_COIL_ON){ if(!boot_modbus.run_app_callback) return MODBUS_RTU_ERROR_NONRECOVERABLE; boot_modbus.run_app_callback(); } break; } return MODBUS_RTU_ERROR_NONE; }
void flash_write_struct(uint32_t address, uint8_t *struct_p, uint32_t size){ uint16_t data=0; uint32_t i; flash_erase_page(params_addr); for(i=0; i<size; i+=2){ if(i == (size-1) && (size % 2) != 0){ data = 0xff; data = data << 8; data |= struct_p[i]; } else{ data = struct_p[i+1]; data = data << 8; data |= struct_p[i]; } flash_unlock(); FLASH->CR |= FLASH_CR_PG; //Разрешаем программирование флеша while(!flash_ready()) //Ожидаем готовности флеша к записи ; *(__IO uint16_t*)address = data; //Пишем младшие 2 бата while(!flash_ready()) ; FLASH->CR &= ~(FLASH_CR_PG); //Запрещаем программирование флеша FLASH->CR &= ~FLASH_CR_PER; //Сбрасываем бит обратно flash_lock(); address+=2; } }
OSStatus internalFlashErase(uint32_t start_address, uint32_t end_address) { platform_log_trace(); uint32_t i; OSStatus err = kNoErr; uint32_t page_start_address, page_end_address; uint32_t page_start_number, page_end_number; platform_mcu_powersave_disable(); require_action( flash_unlock( start_address, end_address, &page_start_address, &page_end_address ) == FLASH_RC_OK, exit, err = kGeneralErr ); page_start_number = page_start_address/512; page_end_number = page_end_address/512; require_action( page_end_number >= page_start_number + 16, exit, err = kUnsupportedErr); for ( i = page_start_number; i <= page_end_number; i+=16 ) { require_action( flash_erase_page( i * 512, IFLASH_ERASE_PAGES_16) == FLASH_RC_OK, exit, err = kGeneralErr ); } require_action( flash_lock( start_address, end_address, NULL, NULL ) == FLASH_RC_OK, exit, err = kGeneralErr ); exit: platform_mcu_powersave_enable(); return err; }
void config_updateToFlash() { uint16_t *dst = &_flashConfigROMBegin; uint16_t *src = &_flashConfigRAMBegin; bool canUpdateFlash = false; for (; src < &_flashConfigRAMEnd; ++src, ++dst) { if (*dst != *src) { canUpdateFlash = true; break; } } if (false != canUpdateFlash) { dst = &_flashConfigROMBegin; src = &_flashConfigRAMBegin; (void) flash_unlock(); flash_erase_sector(FLASH_CONFIG_SECTOR, FLASH_PROGRAMM_ACCESS_SIZE); for (; src < &_flashConfigRAMEnd; ++src, ++dst) { flash_program_half_word((uint32_t)dst, *src, FLASH_PROGRAMM_ACCESS_SIZE); } (void) flash_lock(); } }
void fis_update_directory(void) { int stat; void *err_addr; fis_endian_fixup(fis_work_block); #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); conf_endian_fixup((char *)fis_work_block+fisdir_size); #endif #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL // Ensure [quietly] that the directory is unlocked before trying to update flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr); #endif if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) { diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); } else { if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr)) != 0) { diag_printf("Error writing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); } } #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL // Ensure [quietly] that the directory is locked after the update flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr); #endif fis_endian_fixup(fis_work_block); }
/* write a new configuration item to config space in flash memory. * data will be 4-byte aligned when writing, but original length information * will be retained. * * @return 0 if successful, -2 when no space for storing data is available, * -1 when there is not enough space for the requested length */ int config_write(const uint32_t type, const uint32_t length, const void* data) { uint32_t *dst = (uint32_t*) config_find_item(CONFIG_UNSET); if(dst == NULL) return -2; if(dst + length + 3 >= (uint32_t*)(CONFIG_ADDRESS + CONFIG_SIZE)) return -1; flash_unlock(); /* write header information */ flash_program_word((uint32_t)(dst++), type); flash_program_word((uint32_t)(dst++), length); /* word-wise reading/writing */ uint32_t p = 0; for(; p + 3 < length; p+=sizeof(uint32_t)) { uint32_t v = *((uint32_t*)(data+p)); flash_program_word((uint32_t)(dst++), v); } /* read remainder of partial last word */ if(p < length) { uint32_t v = ((uint8_t*)data)[p++]; if(p < length) v = v | (((uint8_t*)data)[p++] << 8); if(p < length) v = v | (((uint8_t*)data)[p++] << 16); flash_program_word((uint32_t)(dst++), v); } flash_lock(); return 0; }
/* erase complete configuration store */ void config_erase(void) { flash_unlock(); for(void *config = (void*)CONFIG_ADDRESS; config < (void*)(CONFIG_ADDRESS + CONFIG_SIZE); config += FLASH_PAGE_SIZE) { flash_erase_page((uint32_t)config); } flash_lock(); }
static void fis_update_directory(void) { int stat; void *err_addr; #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); #endif #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL // Ensure [quietly] that the directory is unlocked before trying to update flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr); #endif if ((stat = fis_flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Error erasing FIS directory at %p: %s\n\r", err_addr, flash_errmsg(stat)); } else { if ((stat = fis_flash_program(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr)) != 0) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Error writing FIS directory at %p: %s\n\r", err_addr, flash_errmsg(stat)); } } #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL // Ensure [quietly] that the directory is locked after the update flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr); #endif }
void CopyPatchToFlash(void) { flash_unlock(); flash_Erase_sector(11); int src_addr = PATCHMAINLOC; int flash_addr = PATCHFLASHLOC; int c; for (c = 0; c < PATCHFLASHSIZE;) { flash_ProgramWord(flash_addr, *(int32_t *)src_addr); src_addr += 4; flash_addr += 4; c += 4; } // verify src_addr = PATCHMAINLOC; flash_addr = PATCHFLASHLOC; int err = 0; for (c = 0; c < PATCHFLASHSIZE;) { if (*(int32_t *)flash_addr != *(int32_t *)src_addr) err++; src_addr += 4; flash_addr += 4; c += 4; } if (err) { while (1) { // flash verify fail } } AckPending = 1; }
void storage_commit(void) { int i; uint32_t *w; // backup meta memcpy(meta_backup, (void *)FLASH_META_START, FLASH_META_LEN); flash_clear_status_flags(); flash_unlock(); // erase storage for (i = FLASH_META_SECTOR_FIRST; i <= FLASH_META_SECTOR_LAST; i++) { flash_erase_sector(i, FLASH_CR_PROGRAM_X32); } // modify storage memcpy(meta_backup + FLASH_META_DESC_LEN, "stor", 4); memcpy(meta_backup + FLASH_META_DESC_LEN + 4, storage_uuid, sizeof(storage_uuid)); memcpy(meta_backup + FLASH_META_DESC_LEN + 4 + sizeof(storage_uuid), &storage, sizeof(Storage)); // copy it back for (i = 0; i < FLASH_META_LEN / 4; i++) { w = (uint32_t *)(meta_backup + i * 4); flash_program_word(FLASH_META_START + i * 4, *w); } flash_lock(); // flash operation failed if (FLASH_SR & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) { layoutDialog(DIALOG_ICON_ERROR, NULL, NULL, NULL, "Storage failure", "detected.", NULL, "Please unplug", "the device.", NULL); for (;;) { } } }
static int32_t pflash_program_bytes(struct FlashInfo* flash, uint32_t src, uint32_t size, uint32_t chksum) { uint32_t i; /* erase */ flash_unlock(); flash_erase_page(flash->addr); flash_lock(); /* verify erase */ for (i=0; i<flash->page_size; i+=4) { if ((*(uint32_t*) (flash->addr + i)) != 0xFFFFFFFF) return -1; } flash_unlock(); /* write full 16 bit words */ for (i=0; i<(size & ~1); i+=2) { flash_program_half_word(flash->addr+i, (uint16_t)(*(uint8_t*)(src+i) | (*(uint8_t*)(src+i+1)) << 8)); } /* fill bytes with a zero */ if (size & 1) { flash_program_half_word(flash->addr+i, (uint16_t)(*(uint8_t*)(src+i))); } /* write size */ flash_program_half_word(flash->addr+flash->page_size-FSIZ, (uint16_t)(size & 0xFFFF)); flash_program_half_word(flash->addr+flash->page_size-FSIZ+2, (uint16_t)((size >> 16) & 0xFFFF)); /* write checksum */ flash_program_half_word(flash->addr+flash->page_size-FCHK, (uint16_t)(chksum & 0xFFFF)); flash_program_half_word(flash->addr+flash->page_size-FCHK+2, (uint16_t)((chksum >> 16) & 0xFFFF)); flash_lock(); /* verify data */ for (i=0; i<size; i++) { if ((*(uint8_t*) (flash->addr+i)) != (*(uint8_t*) (src+i))) return -2; } if (*(uint32_t*) (flash->addr+flash->page_size-FSIZ) != size) return -3; if (*(uint32_t*) (flash->addr+flash->page_size-FCHK) != chksum) return -4; return 0; }
void aseba_flash_erase_page(int aseba_page) { flash_unlock(); int sector = aseba_page_sector(aseba_page); if (sector != -1) { // first page in sector flash_erase_sector(sector, FLASH_CR_PROGRAM_X16); } }
int clear_all_lock_bits(ADDR addr) { void *err_addr; int stat; if ((stat = flash_unlock((void *)0, eeprom_size, (void **)&err_addr)) != 0) return stat; return OK; }
//Функция стирает одну страницу. В качестве адреса можно использовать любой //принадлежащий диапазону адресов той странице которую нужно очистить. void flash_erase_page(uint32_t address) { flash_unlock(); FLASH->CR|= FLASH_CR_PER; //Устанавливаем бит стирания одной страницы FLASH->AR = address; // Задаем её адрес FLASH->CR|= FLASH_CR_STRT; // Запускаем стирание while(!flash_ready()) ; //Ждем пока страница сотрется. FLASH->CR&= ~FLASH_CR_PER; //Сбрасываем бит обратно flash_lock(); }
/** * \brief * * \param * * \return void */ void f_config_handle(void) { uint32_t ul_last_page_addr = LAST_PAGE_ADDRESS; uint32_t *pul_last_page = (uint32_t *) ul_last_page_addr; uint32_t ul_page_buffer[IFLASH_PAGE_SIZE / sizeof(uint32_t)]; uint32_t unique_id[4]; memset( &f_ip_config, 0, sizeof(f_ip_config_t) ); /* Initialize flash: 6 wait states for flash writing. */ flash_init(FLASH_ACCESS_MODE_128, 6); /* Unlock page */ flash_unlock(ul_last_page_addr, ul_last_page_addr + IFLASH_PAGE_SIZE - 1, 0, 0); /* Read Flash page */ memcpy((uint8_t*)(&f_ip_config), (uint8_t*)pul_last_page, sizeof(f_ip_config_t)); flash_read_unique_id(unique_id, 4); /* read unique ID. */ f_ip_config.mac[0] = ETHERNET_CONF_ETHADDR0; f_ip_config.mac[1] = ETHERNET_CONF_ETHADDR1; f_ip_config.mac[2] = ETHERNET_CONF_ETHADDR2; f_ip_config.mac[3] = ETHERNET_CONF_ETHADDR3; f_ip_config.mac[4] = unique_id[3]>>8; f_ip_config.mac[5] = unique_id[3]; f_ip_config.mask[0] = ETHERNET_CONF_NET_MASK0; f_ip_config.mask[1] = ETHERNET_CONF_NET_MASK1; f_ip_config.mask[2] = ETHERNET_CONF_NET_MASK2; f_ip_config.mask[3] = ETHERNET_CONF_NET_MASK3; if (( f_ip_config.alloc != IP_CONFIG_ALLOC_TRUE ) || ( gpio_pin_is_low(RESTKEY_GPIO) == 1 )) /* net parameters init. */ { f_ip_config.mode = IP_CONFIG_MODE_FIXEDIP; f_ip_config.alloc = IP_CONFIG_ALLOC_TRUE; /* net parameters are occupied.. */ f_ip_config.ip[0] = ETHERNET_CONF_IPADDR0; f_ip_config.ip[1] = ETHERNET_CONF_IPADDR1; f_ip_config.ip[2] = ETHERNET_CONF_IPADDR2; f_ip_config.ip[3] = ETHERNET_CONF_IPADDR3; /* Copy information to FLASH buffer..*/ memcpy((uint8_t*)ul_page_buffer, (uint8_t *)(&f_ip_config), sizeof(f_ip_config_t)); /* Write page */ flash_write(ul_last_page_addr, ul_page_buffer, IFLASH_PAGE_SIZE, 1); } /* Lock page */ flash_lock(ul_last_page_addr, ul_last_page_addr + IFLASH_PAGE_SIZE - 1, 0, 0); }
void check_bootloader(void) { #if MEMORY_PROTECT uint8_t hash[32]; int r = memory_bootloader_hash(hash); if (!known_bootloader(r, hash)) { layoutDialog(&bmp_icon_error, NULL, NULL, NULL, _("Unknown bootloader"), _("detected."), NULL, _("Unplug your TREZOR"), _("contact our support."), NULL); shutdown(); } if (is_mode_unprivileged()) { return; } if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) { // all OK -> done return; } // ENABLE THIS AT YOUR OWN RISK // ATTEMPTING TO OVERWRITE BOOTLOADER WITH UNSIGNED FIRMWARE MAY BRICK // YOUR DEVICE. layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, _("Updating bootloader"), NULL, NULL, _("DO NOT UNPLUG"), _("YOUR TREZOR!"), NULL); // unlock sectors memory_write_unlock(); for (int tries = 0; tries < 10; tries++) { // replace bootloader flash_unlock(); for (int i = FLASH_BOOT_SECTOR_FIRST; i <= FLASH_BOOT_SECTOR_LAST; i++) { flash_erase_sector(i, FLASH_CR_PROGRAM_X32); } for (int i = 0; i < FLASH_BOOT_LEN / 4; i++) { const uint32_t *w = (const uint32_t *)(bl_data + i * 4); flash_program_word(FLASH_BOOT_START + i * 4, *w); } flash_lock(); // check whether the write was OK r = memory_bootloader_hash(hash); if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) { // OK -> show info and halt layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"), _("successfully."), NULL, _("Please reconnect"), _("the device."), NULL); shutdown(); return; } } // show info and halt layoutDialog(&bmp_icon_error, NULL, NULL, NULL, _("Bootloader update"), _("broken."), NULL, _("Unplug your TREZOR"), _("contact our support."), NULL); shutdown(); #endif }
void dfu_protect(dfu_mode_t mode) { if (mode == DFU_MODE) { #ifdef DFU_SELF_PROTECT if ((FLASH_WRPR & 0x03) != 0x00) { flash_unlock(); FLASH_CR = 0; flash_erase_option_bytes(); flash_program_option_bytes(FLASH_OBP_RDP, FLASH_OBP_RDP_KEY); /* CL Device: Protect 2 bits with (2 * 2k pages each)*/ /* MD Device: Protect 2 bits with (4 * 1k pages each)*/ flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } #endif } else if (mode == UPD_MODE) { flash_unlock(); FLASH_CR = 0; flash_erase_option_bytes(); } }
bool FlashStorage::write(uint32_t address, const void *data, uint32_t dataLength) { if ((uint32_t)FLASH_START + address < (uint32_t)&__flash_start__) { FLASH_DEBUG("Flash write address too low"); return false; } if ((uint32_t)FLASH_START + address + dataLength > (uint32_t)&__flash_end__) { FLASH_DEBUG("Flash write address too high"); return false; } if ((((uint32_t)FLASH_START + address) & 3) != 0) { FLASH_DEBUG("Flash start address must be on 4-byte boundary\n"); return false; } // The flash management code in the ASF is fragile and has a tendency to fail to return. Help it by disabling interrupts. efc_disable_frdy_interrupt(EFC); // should not be enabled already, but disable it just in case irqflags_t flags = cpu_irq_save(); // Unlock page uint32_t retCode = flash_unlock((uint32_t)FLASH_START + address, (uint32_t)FLASH_START + address + dataLength - 1, NULL, NULL); if (retCode != FLASH_RC_OK) { FLASH_DEBUG("Failed to unlock flash for write"); } else { // Write data retCode = flash_write((uint32_t)FLASH_START + address, data, dataLength, 1); if (retCode != FLASH_RC_OK) { FLASH_DEBUG("Flash write failed"); } else { // Lock page retCode = flash_lock((uint32_t)FLASH_START + address, (uint32_t)FLASH_START + address + dataLength - 1, NULL, NULL); if (retCode != FLASH_RC_OK) { FLASH_DEBUG("Failed to lock flash page"); } } } cpu_irq_restore(flags); return retCode == FLASH_RC_OK; }
flash_err_t flash_write(const void *addr, const void *data, int len_in_bytes) { flash_err_t err; if (RV_SUCCESS != flash_lock()) { return FLASH_ERR_PROTOCOL; } err = flash_write_sector_locked(addr, data, len_in_bytes); flash_unlock(); return err; }
static flash_err_t flash_erase_sectorinfo(const sector_info_t *sinfo) { flash_err_t err; if (RV_SUCCESS != flash_lock()) { return FLASH_ERR_PROTOCOL; } err = flash_erase_sectorinfo_locked(sinfo); flash_unlock(); return err; }
flash_result_t flash_program_word(const uint32_t *address, const uint32_t data) { flash_unlock(); if (FLASH_FAIL == flash_wait_for_idle()) return FLASH_FAIL; FLASH->CR |= FLASH_CR_PG; // set the programming bit FLASH->CR &= ~FLASH_CR_PSIZE; // wipe out PSIZE to get ready to set it FLASH->CR |= FLASH_CR_PSIZE_1; // we'll do 32-bit erases at a time *((volatile uint32_t *)address) = data; flash_result_t result = flash_wait_for_idle(); FLASH->CR &= ~FLASH_CR_PG; // disable the programming bit //flash_lock(); return result; }
void dfu_protect_enable(void) { #ifdef DFU_SELF_PROTECT if ((FLASH_WRPR & 0x03) != 0x00) { flash_unlock(); FLASH_CR = 0; flash_erase_option_bytes(); flash_program_option_bytes(FLASH_OBP_RDP, FLASH_OBP_RDP_KEY); /* CL Device: Protect 2 bits with (2 * 2k pages each)*/ /* MD Device: Protect 2 bits with (4 * 1k pages each)*/ flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } #endif }
/** Program one page starting at defined address * * The page should be at page boundary, should not cross multiple sectors. * This function does not do any check for address alignments or if size * is aligned to a page size. * @param obj The flash object * @param address The sector starting address * @param data The data buffer to be programmed * @param size The number of bytes to program * @return 0 for success, -1 for error */ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) { uint32_t StartAddress = 0; int32_t status = 0; if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) { return -1; } if ((size % 8) != 0) { /* L4 flash devices can only be programmed 64bits/8 bytes at a time */ return -1; } if (flash_unlock() != HAL_OK) { return -1; } /* Program the user Flash area word by word */ StartAddress = address; /* HW needs an aligned address to program flash, which data * parameters doesn't ensure */ if ((uint32_t) data % 4 != 0) { volatile uint64_t data64; while ((address < (StartAddress + size)) && (status == 0)) { for (uint8_t i =0; i < 8; i++) { *(((uint8_t *) &data64) + i) = *(data + i); } if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64) == HAL_OK) { address = address + 8; data = data + 8; } else { status = -1; } } } else { /* case where data is aligned, so let's avoid any copy */ while ((address < (StartAddress + size)) && (status == 0)) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *((uint64_t*) data)) == HAL_OK) { address = address + 8; data = data + 8; } else { status = -1; } } } flash_lock(); return status; }
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) { uint32_t StartAddress = 0; int32_t status = 0; if (!(IS_FLASH_PROGRAM_ADDRESS(address))) { return -1; } if ((size % MIN_PROG_SIZE) != 0) { return -1; } if (flash_unlock() != HAL_OK) { return -1; } /* Program the user Flash area word by word */ StartAddress = address; /* HW needs an aligned address to program flash, which data parameter doesn't ensure */ if ((uint32_t) data % 4 != 0) { volatile uint32_t data32; while (address < (StartAddress + size) && (status == 0)) { for (uint8_t i = 0; i < MIN_PROG_SIZE; i++) { *(((uint8_t *) &data32) + i) = *(data + i); } if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data32) == HAL_OK) { address = address + MIN_PROG_SIZE; data = data + MIN_PROG_SIZE; } else { status = -1; } } } else { /* case where data is aligned, so let's avoid any copy */ while ((address < (StartAddress + size)) && (status == 0)) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *((uint32_t*) data)) == HAL_OK) { address = address + MIN_PROG_SIZE; data = data + MIN_PROG_SIZE; } else { status = -1; } } } flash_lock(); return status; }