static int get_mac_addr(u8 *addr) { struct spi_flash *flash; int ret; flash = spi_flash_probe(CFG_MAC_ADDR_SPI_BUS, CFG_MAC_ADDR_SPI_CS, CFG_MAC_ADDR_SPI_MAX_HZ, CFG_MAC_ADDR_SPI_MODE); if (!flash) { printf("Error - unable to probe SPI flash.\n"); return -1; } ret = spi_flash_read(flash, CFG_MAC_ADDR_OFFSET, 6, addr); if (ret) { printf("Error - unable to read MAC address from SPI flash.\n"); return -1; } return ret; }
void env_relocate_spec(void) { int ret; env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); if (!env_flash) goto err_probe; ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, env_ptr); if (ret) goto err_read; if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) goto err_crc; gd->env_valid = 1; return; err_read: puts("*** Warning - read\n"); spi_flash_free(env_flash); env_flash = NULL; err_probe: puts("*** Warning - probe\n"); err_crc: puts("*** Warning - CRC\n"); puts("*** Warning - bad CRC, using default environment\n\n"); if (default_environment_size > CONFIG_ENV_SIZE) { gd->env_valid = 0; puts("*** Error - default environment is too large\n\n"); return; } memset(env_ptr, 0, sizeof(env_t)); memcpy(env_ptr->data, default_environment, default_environment_size); env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); gd->env_valid = 1; }
uint32_t EspClass::getFlashChipSpeed(void) { uint32_t data; uint8_t * bytes = (uint8_t *) &data; // read first 4 byte (magic byte + flash config) if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) { switch(bytes[3] & 0x0F) { case 0x0: // 40 MHz return (40_MHz); case 0x1: // 26 MHz return (26_MHz); case 0x2: // 20 MHz return (20_MHz); case 0xf: // 80 MHz return (80_MHz); default: // fail? return 0; } } return 0; }
static int get_sh_eth_mac_raw(unsigned char *buf, int size) { struct spi_flash *spi; int ret; spi = spi_flash_probe(0, 0, 1000000, SPI_MODE_3); if (spi == NULL) { printf("%s: spi_flash probe failed.\n", __func__); return 1; } ret = spi_flash_read(spi, SH7753EVB_ETHERNET_MAC_BASE, size, buf); if (ret) { printf("%s: spi_flash read failed.\n", __func__); spi_flash_free(spi); return 1; } spi_flash_free(spi); return 0; }
int32_t MFSReadSector( uint8_t* data, struct MFSFileInfo * mfi ) { //returns # of bytes left tin file. if( !mfi->filelen ) { return 0; } int toread = mfi->filelen; if( toread > MFS_SECTOR ) toread = MFS_SECTOR; EnterCritical(); flashchip->chip_size = 0x01000000; spi_flash_read( mfs_at+mfi->offset, (uint32*)data, MFS_SECTOR ); flashchip->chip_size = 0x00080000; ExitCritical(); mfi->offset += toread; mfi->filelen -= toread; return mfi->filelen; }
ICACHE_FLASH_ATTR static s32_t esp_spiffs_readwrite(u32_t addr, u32_t size, u8 *p, int write) { /* * With proper configurarion spiffs never reads or writes more than * LOG_PAGE_SIZE */ if (size > LOG_PAGE_SIZE) { os_printf("Invalid size provided to read/write (%d)\n\r", (int) size); return SPIFFS_ERR_NOT_CONFIGURED; } char tmp_buf[LOG_PAGE_SIZE + FLASH_UNIT_SIZE * 2]; u32_t aligned_addr = addr & (-FLASH_UNIT_SIZE); u32_t aligned_size = ((size + (FLASH_UNIT_SIZE - 1)) & -FLASH_UNIT_SIZE) + FLASH_UNIT_SIZE; int res = spi_flash_read(aligned_addr, (u32_t *) tmp_buf, aligned_size); if (res != 0) { os_printf("spi_flash_read failed: %d (%d, %d)\n\r", res, (int) aligned_addr, (int) aligned_size); return res; } if (!write) { memcpy(p, tmp_buf + (addr - aligned_addr), size); return SPIFFS_OK; } memcpy(tmp_buf + (addr - aligned_addr), p, size); res = spi_flash_write(aligned_addr, (u32_t *) tmp_buf, aligned_size); if (res != 0) { os_printf("spi_flash_write failed: %d (%d, %d)\n\r", res, (int) aligned_addr, (int) aligned_size); return res; } return SPIFFS_OK; }
bool flash_rom_set_speed(uint32_t speed) { // Dangerous, here are dinosaur infested!!!!! // Reboot required!!! // If you don't know what you're doing, your nodemcu may turn into stone ... NODE_DBG("\nBEGIN SET FLASH HEADER\n"); uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR; uint8_t speed_type = SPEED_40MHZ; if (speed < 26700000) { speed_type = SPEED_20MHZ; } else if (speed < 40000000) { speed_type = SPEED_26MHZ; } else if (speed < 80000000) { speed_type = SPEED_40MHZ; } else if (speed >= 80000000) { speed_type = SPEED_80MHZ; } if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) { ((SPIFlashInfo *)(&data[0]))->speed = speed_type; if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE)) { NODE_DBG("\nERASE SUCCESS\n"); } if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) { NODE_DBG("\nWRITE SUCCESS, %u\n", speed_type); } } NODE_DBG("\nEND SET FLASH HEADER\n"); return true; }
int spiflash_logic_read(spiflash_logic_t *spiflash_logic, unsigned long long offset, unsigned int length, unsigned char *buf) { int ret; if (!length) { printf("Attempt to read 0 Bytes\n"); return -1; } if (offset > spiflash_logic->length) { printf("Attempt to read outside the flash handle area, " "flash handle size: 0x%08llx, offset: 0x%08llx\n", spiflash_logic->length, offset); return -1; } if ((offset + length) > spiflash_logic->length) { length = spiflash_logic->length - offset; printf("Read length is too large, " "paratition size: 0x%08llx, read offset: 0x%08llx\n" "Try to read 0x%08x instead!\n", spiflash_logic->length, offset, length); } ret = spi_flash_read(spiflash_logic->spiflash, spiflash_logic->address + offset, length, buf); if (!ret) return length; return ret; }
//Returns 0 on succses. //Returns size of file if non-empty //If positive, populates mfi. //Returns -1 if can't find file or reached end of file list. int8_t MFSOpenFile( const char * fname, struct MFSFileInfo * mfi ) { flashchip->chip_size = 0x01000000; uint32 ptr = MFS_START; struct MFSFileEntry e; while(1) { spi_flash_read( ptr, (uint32*)&e, sizeof( e ) ); ptr += sizeof(e); if( e.name[0] == 0xff || ets_strlen( e.name ) == 0 ) break; if( ets_strcmp( e.name, fname ) == 0 ) { mfi->offset = e.start; mfi->filelen = e.len; flashchip->chip_size = 0x00080000; return 0; } } flashchip->chip_size = 0x00080000; return -1; }
ICACHE_FLASH_ATTR void eeSetData(int address, void* buffer, int size) { // address, size in BYTES !!!! uint8_t* inbuf = buffer; while(1) { uint32_t sector = (EEPROM_START + address) & 0xFFF000; spi_flash_read(sector, (uint32 *)eebuf, 4096); spi_flash_erase_sector(sector >> 12); uint8_t* eebuf8 = (uint8_t*)eebuf; uint16_t startaddr = address & 0xFFF; uint16_t maxsize = 4096 - startaddr; uint16_t i; for(i=0; (i<size && i<maxsize); i++) eebuf8[i+startaddr] = inbuf[i]; spi_flash_write(sector, (uint32 *)eebuf, 4096); if(maxsize >= size) break; address += i; inbuf += i; size -= i; } }
bool flash_rom_set_size_type(uint8_t size) { // Dangerous, here are dinosaur infested!!!!! // Reboot required!!! // If you don't know what you're doing, your nodemcu may turn into stone ... NODE_DBG("\nBEGIN SET FLASH HEADER\n"); uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR; if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) { ((SPIFlashInfo *)(&data[0]))->size = size; if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE)) { NODE_DBG("\nERASE SUCCESS\n"); } if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) { NODE_DBG("\nWRITE SUCCESS, %u\n", size); } } NODE_DBG("\nEND SET FLASH HEADER\n"); return true; }
/****************************************************************************** * FunctionName : user_light_init * Description : light demo init, mainy init pwm * Parameters : none * Returns : none *******************************************************************************/ void user_light_init(void) { /*init to off*/ uint32 pwm_duty_init[PWM_CHANNEL]; light_param.pwm_period = 1000; memset(pwm_duty_init,0,PWM_CHANNEL*sizeof(uint32)); pwm_init(light_param.pwm_period, pwm_duty_init,PWM_CHANNEL,pwmio_info); /*set target valuve from memory*/ spi_flash_read((PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,(uint32 *)&light_param, sizeof(struct light_saved_param)); if(light_param.pwm_period>10000 || light_param.pwm_period <1000){ light_param.pwm_period = 1000; light_param.pwm_duty[0]= APP_MAX_PWM; light_param.pwm_duty[1]= APP_MAX_PWM; light_param.pwm_duty[2]= APP_MAX_PWM; light_param.pwm_duty[3]= APP_MAX_PWM; light_param.pwm_duty[4]= APP_MAX_PWM; } printf("LIGHT P:%d",light_param.pwm_period); printf(" R:%d",light_param.pwm_duty[LIGHT_RED]); printf(" G:%d",light_param.pwm_duty[LIGHT_GREEN]); printf(" B:%d",light_param.pwm_duty[LIGHT_BLUE]); if(PWM_CHANNEL>LIGHT_COLD_WHITE){ printf(" CW:%d",light_param.pwm_duty[LIGHT_COLD_WHITE]); printf(" WW:%d\r\n",light_param.pwm_duty[LIGHT_WARM_WHITE]); }else{ printf("\r\n"); } light_set_aim(light_param.pwm_duty[LIGHT_RED], light_param.pwm_duty[LIGHT_GREEN], light_param.pwm_duty[LIGHT_BLUE], light_param.pwm_duty[LIGHT_COLD_WHITE], light_param.pwm_duty[LIGHT_WARM_WHITE], light_param.pwm_period); return; }
uint32_t EspClass::getFlashChipSize(void) { uint32_t data; uint8_t * bytes = (uint8_t *) &data; // read first 4 byte (magic byte + flash config) if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) { switch((bytes[3] & 0xf0) >> 4) { case 0x0: // 4 Mbit (512KB) return (512_kB); case 0x1: // 2 MBit (256KB) return (256_kB); case 0x2: // 8 MBit (1MB) return (1_MB); case 0x3: // 16 MBit (2MB) return (2_MB); case 0x4: // 32 MBit (4MB) return (4_MB); default: // fail? return 0; } } return 0; }
bool platform_partition_info (uint8_t idx, platform_partition_t *info) { if (!possible_idx (idx)) return false; partition_info_t pi; esp_err_t err = spi_flash_read ( PARTITION_ADD + idx * sizeof(pi), (uint32_t *)&pi, sizeof (pi)); if (err != ESP_OK) { return false; } if (pi.magic != PARTITION_MAGIC) { return false; } memcpy (info->label, pi.label, sizeof (info->label)); info->offs = pi.pos.offset; info->size = pi.pos.size; info->type = pi.type; info->subtype = pi.subtype; return true; }
static int update_image_length(struct spi_flash *flash, unsigned int offset, unsigned char *dest, unsigned char flag) { unsigned int length = flash->page_size; int ret; ret = spi_flash_read(flash, offset, length, dest); if (ret) return -1; if (flag == KERNEL_IMAGE) return kernel_size(dest); #ifdef CONFIG_OF_LIBFDT else { ret = check_dt_blob_valid((void *)dest); if (!ret) return of_get_dt_total_size((void *)dest); } #endif return -1; }
static s32_t esp_spiffs_read(u32_t addr, u32_t size, u8_t *dst) { #ifdef CS_MMAP if (dst >= DUMMY_MMAP_BUFFER_START && dst < DUMMY_MMAP_BUFFER_END) { if ((addr - SPIFFS_PAGE_HEADER_SIZE) % LOG_PAGE_SIZE == 0) { fprintf(stderr, "mmap spiffs prep read: %x %u %p\n", addr, size, dst); cur_mmap_desc->blocks[cur_mmap_desc->pages++] = FLASH_BASE + addr; } return SPIFFS_OK; } #endif if (0 && addr % FLASH_UNIT_SIZE == 0 && size % FLASH_UNIT_SIZE == 0) { /* * For unknown reason spi_flash_read/write * hangs from time to time if size is small (< 8) * and address is not aligned to 0xFF * TODO(alashkin): understand why and remove `0 &&` from `if` */ return spi_flash_read(addr, (u32_t *) dst, size); } else { return esp_spiffs_readwrite(addr, size, dst, 0); } }
void ICACHE_FLASH_ATTR CFG_Save() { spi_flash_read((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, (uint32 *) &saveFlag, sizeof(SAVE_FLAG)); if (saveFlag.flag == 0) { spi_flash_erase_sector(CFG_LOCATION + 1); spi_flash_write((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32 *) &sysCfg, sizeof(SYSCFG)); saveFlag.flag = 1; spi_flash_erase_sector(CFG_LOCATION + 3); spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, (uint32 *) &saveFlag, sizeof(SAVE_FLAG)); } else { spi_flash_erase_sector(CFG_LOCATION + 0); spi_flash_write((CFG_LOCATION + 0) * SPI_FLASH_SEC_SIZE, (uint32 *) &sysCfg, sizeof(SYSCFG)); saveFlag.flag = 0; spi_flash_erase_sector(CFG_LOCATION + 3); spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, (uint32 *) &saveFlag, sizeof(SAVE_FLAG)); } }
bool platform_partition_add (const platform_partition_t *info) { partition_info_t *part_table = (partition_info_t *)malloc(SPI_FLASH_SEC_SIZE); if (!part_table) return false; esp_err_t err = spi_flash_read (PARTITION_ADD, (uint32_t *)part_table, SPI_FLASH_SEC_SIZE); if (err != ESP_OK) goto out; uint8_t idx = 0; for (; possible_idx (idx); ++idx) if (part_table[idx].magic != PARTITION_MAGIC) break; if (possible_idx (idx)) { partition_info_t *slot = &part_table[idx]; slot->magic = PARTITION_MAGIC; slot->type = info->type; slot->subtype = info->subtype; slot->pos.offset = info->offs; slot->pos.size = info->size; memcpy (slot->label, info->label, sizeof (slot->label)); //memset (slot->reserved, 0xff, sizeof (slot->reserved)); slot->flags = 0xffffffff; err = spi_flash_erase_sector (PARTITION_ADD / SPI_FLASH_SEC_SIZE); if (err == ESP_OK) err = spi_flash_write ( PARTITION_ADD, (uint32_t *)part_table, SPI_FLASH_SEC_SIZE); } out: free (part_table); return err == ESP_OK; }
static unsigned char* mbedtls_get_default_obj(uint32 *sec, uint32 type, uint32 *len) { const char* const begin = "-----BEGIN"; unsigned char *parame_data = NULL; pmbedtls_parame mbedtls_obj = NULL; if (type == ESPCONN_PK){ mbedtls_obj = def_private_key; } else{ mbedtls_obj = def_certificate; } if (mbedtls_obj->parame_sec != 0){ #define DATA_OFFSET 4 uint32 data_len = mbedtls_obj->parame_datalen; parame_data = (unsigned char *)os_zalloc(data_len + DATA_OFFSET); if (parame_data){ spi_flash_read(mbedtls_obj->parame_sec * FLASH_SECTOR_SIZE, (uint32*)parame_data, data_len); /* * Determine buffer content. Buffer contains either one DER certificate or * one or more PEM certificates. */ if ((char*)os_strstr(parame_data, begin) != NULL){ data_len ++; parame_data[data_len - 1] = '\0'; } } *len = data_len; } else{ parame_data = mbedtls_obj->parame_data; *len = mbedtls_obj->parame_datalen; } *sec = mbedtls_obj->parame_sec; return parame_data; }
void EEPROMClass::begin(size_t size) { if (size <= 0) return; if (size > SPI_FLASH_SEC_SIZE) size = SPI_FLASH_SEC_SIZE; size = (size + 3) & (~3); //In case begin() is called a 2nd+ time, don't reallocate if size is the same if(_data && size != _size) { delete[] _data; _data = new uint8_t[size]; } else if(!_data) { _data = new uint8_t[size]; } _size = size; noInterrupts(); spi_flash_read(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast<uint32_t*>(_data), _size); interrupts(); _dirty = false; //make sure dirty is cleared in case begin() is called 2nd+ time }
void ICACHE_FLASH_ATTR debug_DispFlashExceptInfo(flashDebugBuf* flashDbgBuf) { ESP_DBG("flash debug : version: %d \r\n",flashDbgBuf->DebugVersion); ESP_DBG("flash debug : InPos: %08x\r\n",flashDbgBuf->InPos); ESP_DBG("flash debug : OutPos: %08x\r\n",flashDbgBuf->OutPos); uint8* debug_str = NULL; int size = (flashDbgBuf->InPos-flashDbgBuf->OutPos); if(size>0){ debug_str = (uint8*)os_zalloc(size+1); spi_flash_read(flashDbgBuf->OutPos,(uint32*)debug_str,size); ESP_DBG("-----------------------\r\n"); ESP_DBG("FLASH DEBUG INFO: \r\n"); ESP_DBG("%s\r\n",debug_str); ESP_DBG("-----------------------\r\n"); } if(debug_str){ os_free(debug_str); debug_str = NULL; } }
/** * This will search for one or more bootloaders in the SPI NOR and boot * either the failsafe one or the last valid one found. * * @param cmdtp Command data structure * @param flag flags, not used * @param argc argument count, not used, passed on * @param argv arguments, not used, passed on * * @return -1 on error otherwise no return. */ int do_octbootstage3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct spi_flash *flash; struct bootloader_header *header; uint32_t addr; const int bus = 0; const int cs = 0; const int speed = CONFIG_SF_DEFAULT_SPEED; const int mode = CONFIG_SF_DEFAULT_MODE; void *buf; int len; int offset; int found_offset = -1; int found_size = 0; int rc; int failsafe; flash = spi_flash_probe(bus, cs, speed, mode); if (!flash) { printf("Failed to initialize SPI flash at %u:%u", bus, cs); return -1; } addr = getenv_ulong("octeon_stage3_load_addr", 16, CONFIG_OCTEON_STAGE3_LOAD_ADDR); header = CASTPTR(struct bootloader_header, addr); buf = (void *)header; #ifdef CONFIG_OCTEON_FAILSAFE_GPIO failsafe = gpio_direction_input(CONFIG_OCTEON_FAILSAFE_GPIO); #else failsafe = 0; #endif offset = CONFIG_OCTEON_SPI_BOOT_START; do { if (spi_flash_read(flash, offset, sizeof(*header), header)) { printf("Could not read SPI flash to find bootloader\n"); return -1; } if (!validate_bootloader_header(header) || (header->board_type != gd->arch.board_desc.board_type)) { offset += flash->erase_size; continue; } len = header->hlen + header->dlen - sizeof(*header); if (len < 0) { printf("Invalid length calculated, hlen: %d, dlen: %d\n", header->hlen, header->dlen); offset += flash->erase_size; continue; } /* Read rest of bootloader */ rc = spi_flash_read(flash, offset + sizeof(*header), len, &header[1]); if (rc) { printf("Could not read %d bytes from SPI flash\n", header->dlen + header->hlen); return -1; } if (calculate_image_crc(header) != header->dcrc) { printf("Found corrupted image at offset 0x%x, continuing search\n", offset); offset += flash->erase_size; continue; } found_offset = offset; found_size = header->hlen + header->dlen; printf("Found valid SPI bootloader at offset: 0x%x, size: %d bytes\n", found_offset, found_size); if (failsafe) break; /* Skip past the current image to the next one */ offset += (found_size + flash->erase_size - 1) & ~(flash->erase_size); } while (offset < CONFIG_OCTEON_SPI_BOOT_END); if (found_offset < 0) { printf("Could not find stage 3 bootloader\n"); return -1; } /* If we searched for multiple bootloaders and didn't stop at the first * one (i.e. failsafe) then re-read the last good one found into * memory. */ if (found_offset != offset) { rc = spi_flash_read(flash, found_offset, found_size, header); if (rc) { printf("Error reading bootloader from offset 0x%x, size: 0x%x\n", found_offset, found_size); return -1; } } do_go_exec(buf, argc - 1, argv + 1); return 0; }
ICACHE_FLASH_ATTR void eeGetData(int address, void* buffer, int size) { // address, size in BYTES !!!! spi_flash_read(EEPROM_START + address, (uint32 *)buffer, size); }
ICACHE_FLASH_ATTR uint32_t eeGet4Byte(uint32_t address) { // address = number of 4-byte parts from beginning address *= 4; uint32_t t = 0; spi_flash_read(EEPROM_START + address, (uint32 *)&t, 4); return t; }
/* * Write to flash on RTG4 */ static int write_program_to_flash(uint8_t *write_buf) { uint8_t write_buffer[FLASH_SEGMENT_SIZE]; uint8_t read_buffer[FLASH_SEGMENT_SIZE]; uint16_t status; int flash_address = 0; int count = 0; spi_flash_status_t result; struct device_Info DevInfo; spi_flash_init(); spi_flash_control_hw( SPI_FLASH_RESET, 0, &status ); result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); /*-------------------------------------------------------------------------- * First fetch status register. First byte in low 8 bits, second byte in * upper 8 bits. */ result = spi_flash_control_hw( SPI_FLASH_GET_STATUS, 0, &status ); result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); /*-------------------------------------------------------------------------- * Fetch protection register value for each of the 128 sectors. * After power up these should all read as 0xFF */ for( count = 0; count != 128; ++count ) { result = spi_flash_control_hw( SPI_FLASH_GET_PROTECT, count * FLASH_SECTOR_SIZE, &read_buffer[count] ); } //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); /*-------------------------------------------------------------------------- * Show sector protection in action by: * - unprotecting the first sector * - erasing the sector * - writing some data to the first 256 bytes * - protecting the first sector * - erasing the first sector * - reading back the first 256 bytes of the first sector * - unprotecting the first sector * - erasing the sector * - reading back the first 256 bytes of the first sector * * The first read should still show the written data in place as the erase * will fail. the second read should show all 0xFFs. Step through the code * in debug mode and examine the read buffer after the read operations to * see this. */ result = spi_flash_control_hw( SPI_FLASH_SECTOR_UNPROTECT, flash_address, NULL ); //device D works result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_4KBLOCK_ERASE, flash_address , NULL ); //device D-- now working result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); memset( write_buffer, count, FLASH_SEGMENT_SIZE ); strcpy( (char *)write_buffer, "Microsemi FLASH test" ); spi_flash_write( flash_address, write_buffer, FLASH_SEGMENT_SIZE ); //device D -- result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_SECTOR_PROTECT, flash_address, NULL ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_4KBLOCK_ERASE, flash_address , NULL ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_GET_STATUS, 0, &status ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); spi_flash_read ( flash_address, read_buffer, FLASH_SEGMENT_SIZE); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_SECTOR_UNPROTECT, flash_address, NULL ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_4KBLOCK_ERASE, flash_address , NULL ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_GET_STATUS, 0, &status ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_SECTOR_UNPROTECT, flash_address, NULL ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); result = spi_flash_control_hw( SPI_FLASH_4KBLOCK_ERASE, flash_address , NULL ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); spi_flash_read ( flash_address, read_buffer, FLASH_SEGMENT_SIZE ); //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); /*-------------------------------------------------------------------------- * Read the protection registers again so you can see that the first sector * is unprotected now. */ for( count = 0; count != 128; ++count ) { spi_flash_control_hw( SPI_FLASH_GET_PROTECT, count * FLASH_SECTOR_SIZE, &write_buffer[count] ); } //device D result = spi_flash_control_hw( SPI_FLASH_READ_DEVICE_ID, count * FLASH_SECTOR_SIZE, &DevInfo ); /*-------------------------------------------------------------------------- * Write something to all 32768 blocks of 256 bytes in the 8MB FLASH. */ for( count = 0; count != ((32*1024)/256) /*32768*/; ++count ) { /*---------------------------------------------------------------------- * Vary the fill for each chunk of 256 bytes */ memset( write_buffer, count, FLASH_SEGMENT_SIZE ); strcpy( (char *)write_buffer, "Microsemi FLASH test" ); /*---------------------------------------------------------------------- * at the start of each sector we need to make sure it is unprotected * so we can erase blocks within it. The spi_flash_write() function * unprotects the sector as well but we need to start erasing before the * first write takes place. */ if(0 == (flash_address % FLASH_SECTOR_SIZE)) { result = spi_flash_control_hw( SPI_FLASH_SECTOR_UNPROTECT, flash_address, NULL ); } /*---------------------------------------------------------------------- * At the start of each 4K block we issue an erase so that we are then * free to write anything we want to the block. If we don't do this the * write may fail as we can only effectively turn 1s to 0s when we * write. For example if we have an erased location with 0xFF in it and * we write 0xAA to it first and then later on write 0x55, the resulting * value is 0x00... */ if(0 == (flash_address % FLASH_BLOCK_SIZE)) { result = spi_flash_control_hw( SPI_FLASH_4KBLOCK_ERASE, flash_address , NULL ); } /*---------------------------------------------------------------------- * Write our values to the FLASH, read them back and compare. * Placing a breakpoint on the while statement below will allow * you break on any failures. */ spi_flash_write( flash_address, write_buf, FLASH_SEGMENT_SIZE ); spi_flash_read ( flash_address, read_buffer, FLASH_SEGMENT_SIZE ); if( memcmp( write_buf, read_buffer, FLASH_SEGMENT_SIZE ) ) { while(1) // Breakpoint here will trap write faults { } } write_buf += FLASH_SEGMENT_SIZE; flash_address += FLASH_SEGMENT_SIZE; /* Step to the next 256 byte chunk */ } /*-------------------------------------------------------------------------- * One last look at the protection registers which should all be 0 now */ for( count = 0; count != 128; ++count ) { spi_flash_control_hw( SPI_FLASH_GET_PROTECT, count * FLASH_SECTOR_SIZE, &write_buffer[count] ); } UART_polled_tx_string( &g_uart, " Flash write success\n\r" ); return(0); }
void test_spi_flash(void) { struct spi_slave spi; struct spi_flash flash; unsigned int addr, i; int ret; /* We use a 512 byte buf for verifications below because of limited RAM */ uint8_t buf[512]; ptest(); /* Enable PIO0.2 for CS */ LPC_GPIO0->DIR |= (1<<2); /* Configure SPI */ spi.master = &SPI0; spi.speed = 24000000; spi.mode = 0; spi.cs_pin = 2; spi.cs_active_high = false; debug_printf(STR_TAB "Press enter to start SPI flash test...\n"); uart_getc(); uart_putc('\n'); /* Probe for the flash */ debug_printf(STR_TAB "Probing for SPI flash chip...\n"); passert(spi_flash_probe(&flash, &spi) == 0); pokay("Found SPI flash!"); pokay(" JEDEC ID: 0x%08x", flash.params->jedec_id); pokay(" Name: %s", flash.params->name); pokay(" Sector Size: %d", flash.params->sector_size); pokay(" Capacity: %d", flash.params->capacity); pokay(" Flags: %04x", flash.params->flags); debug_printf(STR_TAB "Testing invalid argument checks of SPI flash functions\n"); /* Make sure not sector size mod address and length fail */ passert(spi_flash_erase(&flash, 0x5, 4096) == SPI_FLASH_ERROR_ARGS); passert(spi_flash_erase(&flash, 0, 4095) == SPI_FLASH_ERROR_ARGS); /* Make sure program out of bounds fails */ passert(spi_flash_write(&flash, 0x3, NULL, flash.params->capacity) == SPI_FLASH_ERROR_ARGS); /* Erase two sectors */ debug_printf(STR_TAB "Erasing lower two sectors...\n"); passert(spi_flash_erase(&flash, 0x0, 4096*2) == 0); /* Verify they are all 0xff */ debug_printf(STR_TAB "Verifying lower two sectors are blank...\n"); for (addr = 0; addr < 4096*2; addr += sizeof(buf)) { if ((ret = spi_flash_read(&flash, addr, buf, sizeof(buf))) != 0) { pfail("Error with spi_flash_read(): %d", ret); passert(false); } for (i = 0; i < sizeof(buf); i++) { if (buf[i] != 0xff) { pfail("Memory is not blank at address 0x%06x! got 0x%02x", addr+i, buf[i]); passert(false); } } } pokay("Lower two sectors are blank"); debug_printf(STR_TAB "Starting write/read/verify test vector tests...\n"); /* Write test vector 1 to 0x003 - 0x04e inclusive (75 bytes) */ passert(spi_flash_write(&flash, 0x03, test_sf_vector1, sizeof(test_sf_vector1)) == 0); pokay("Wrote test vector 1 to 0x003-0x04e"); /* Verify test vector 1 data from 0x000 - 0x0ff */ passert(spi_flash_read(&flash, 0x0, buf, sizeof(buf)) == 0); passert(memcmp(buf, test_sf_vector_blank, 3) == 0); passert(memcmp(buf+3, test_sf_vector1, sizeof(test_sf_vector1)) == 0); passert(memcmp(buf+3+sizeof(test_sf_vector1), test_sf_vector_blank, 0x100-3-sizeof(test_sf_vector1)) == 0); pokay("Read test vector 1 verified 0x000-0x0ff"); /* Write test vector 2 to 0x100 - 0x1ff inclusive (1 page == 256 bytes) */ passert(spi_flash_write(&flash, 0x100, test_sf_vector2, sizeof(test_sf_vector2)) == 0); pokay("Wrote test vector 2 to 0x100-0x1ff"); /* Verify test vector 1 again */ debug_printf(STR_TAB "Verifying test vector 1 again\n"); passert(spi_flash_read(&flash, 0x0, buf, sizeof(buf)) == 0); passert(memcmp(buf, test_sf_vector_blank, 3) == 0); passert(memcmp(buf+3, test_sf_vector1, sizeof(test_sf_vector1)) == 0); passert(memcmp(buf+3+sizeof(test_sf_vector1), test_sf_vector_blank, 0x100-3-sizeof(test_sf_vector1)) == 0); pokay("Read test vector 1 verified 0x000-0x0ff"); /* Verify test vector 2 */ passert(spi_flash_read(&flash, 0x100, buf, sizeof(buf)) == 0); passert(memcmp(buf, test_sf_vector2, sizeof(test_sf_vector2)) == 0); pokay("Read test vector 2 verified 0x100-0x1ff"); /* Write test vector 3 to 0x200 - 0x301 inclusive (1 page, 1 byte == 257 bytes) */ passert(spi_flash_write(&flash, 0x200, test_sf_vector3, sizeof(test_sf_vector3)) == 0); pokay("Wrote test vector 3 to 0x200-0x301"); /* Verify test vector 3 */ passert(spi_flash_read(&flash, 0x200, buf, sizeof(buf)) == 0); passert(memcmp(buf, test_sf_vector3, sizeof(test_sf_vector3)) == 0); passert(memcmp(buf+sizeof(test_sf_vector3), test_sf_vector_blank, 0x100-1) == 0); pokay("Read test vector 3 verified 0x200-0x3ff"); /* Write test vector 4 to 0x37f - 0x5ff inclusive (2.5 pages == 640 bytes) */ passert(spi_flash_write(&flash, 0x37f, test_sf_vector4, sizeof(test_sf_vector4)) == 0); pokay("Wrote test vector 4 to 0x37f-0x5ff"); /* Verify test vector 4 */ /* First 512 bytes */ passert(spi_flash_read(&flash, 0x37f, buf, sizeof(buf)) == 0); passert(memcmp(buf, test_sf_vector4, 512) == 0); /* Last 128 bytes (and 384 blank bytes) */ passert(spi_flash_read(&flash, 0x37f+512, buf, sizeof(buf)) == 0); passert(memcmp(buf, test_sf_vector4+512, 128) == 0); passert(memcmp(buf+128, test_sf_vector_blank, 384) == 0); pokay("Read test vector 4 verified 0x37f-0x5ff"); debug_printf(STR_TAB "Erasing entire chip... Press enter to continue."); uart_getc(); uart_putc('\n'); /* Erase chip */ passert(spi_flash_erase(&flash, 0x0, flash.params->capacity) == 0); /* Verify lower 256kB is blank */ debug_printf(STR_TAB "Verifying lower 256kB is blank...\n"); for (addr = 0; addr < 256*1024; addr += sizeof(buf)) { if ((ret = spi_flash_read(&flash, addr, buf, sizeof(buf))) != 0) { pfail("Error with spi_flash_read(): %d", ret); passert(false); } for (i = 0; i < sizeof(buf); i++) { if (buf[i] != 0xff) { pfail("Memory is not blank at address 0x%06x! got 0x%02x", addr+i, buf[i]); passert(false); } } } pokay("Lower 256kB is blank"); debug_printf(STR_TAB "Starting pseudorandom data test... Press enter to continue."); uart_getc(); uart_putc('\n'); /* Write 256kB pseudorandom data */ debug_printf(STR_TAB "Writing 256kB pseudorandom data\n"); srand(0xdeadbeef); for (addr = 0; addr < 256*1024; addr += sizeof(buf)) { for (i = 0; i < sizeof(buf); i++) buf[i] = rand(); if (spi_flash_write(&flash, addr, buf, sizeof(buf)) != 0) { pfail("Error with spi_flash_write(): %d", ret); passert(false); } } pokay("Wrote 256kB pseudorandom data"); /* Verify 256kB pseudorandom data */ debug_printf(STR_TAB "Verifying 256kB pseudorandom data\n"); srand(0xdeadbeef); for (addr = 0; addr < 256*1024; addr += sizeof(buf)) { if ((ret = spi_flash_read(&flash, addr, buf, sizeof(buf))) != 0) { pfail("Error with spi_flash_read(): %d", ret); passert(false); } for (i = 0; i < sizeof(buf); i++) { uint8_t x = rand(); if (buf[i] != x) { pfail("Pseudorandom data mismatch at address 0x%06x! expected 0x%02x, got 0x%02x", addr+i, x, buf[i]); passert(false); } } } pokay("Pseudorandom data matches!"); }
/** * Read one block of the image from the device. * * \param addr absolute offset * \param len number of bytes to read * \param data buffer for the image data * \return status code */ int hpm_nvram_read(size_t addr, uint8_t *data, size_t len) { /* Add offset for the selected NVRAM section. */ addr += oem_config.update_nvram * BIOS_NVRAM_SIZE; return spi_flash_read(&spi_flash, addr, len, data); }
int saveenv(void) { env_t env_new; ssize_t len; char *res, *saved_buffer = NULL, flag = OBSOLETE_FLAG; u32 saved_size, saved_offset, sector = 1; int ret; if (!env_flash) { env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); if (!env_flash) { set_default_env("!spi_flash_probe() failed"); return 1; } } res = (char *)&env_new.data; len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; } env_new.crc = crc32(0, env_new.data, ENV_SIZE); env_new.flags = ACTIVE_FLAG; if (gd->env_valid == 1) { env_new_offset = CONFIG_ENV_OFFSET_REDUND; env_offset = CONFIG_ENV_OFFSET; } else { env_new_offset = CONFIG_ENV_OFFSET; env_offset = CONFIG_ENV_OFFSET_REDUND; } /* Is the sector larger than the env (i.e. embedded) */ if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; saved_offset = env_new_offset + CONFIG_ENV_SIZE; saved_buffer = malloc(saved_size); if (!saved_buffer) { ret = 1; goto done; } ret = spi_flash_read(env_flash, saved_offset, saved_size, saved_buffer); if (ret) goto done; } if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) { sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE; if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE) sector++; } puts("Erasing SPI flash..."); ret = spi_flash_erase(env_flash, env_new_offset, sector * CONFIG_ENV_SECT_SIZE); if (ret) goto done; puts("Writing to SPI flash..."); ret = spi_flash_write(env_flash, env_new_offset, CONFIG_ENV_SIZE, &env_new); if (ret) goto done; if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { ret = spi_flash_write(env_flash, saved_offset, saved_size, saved_buffer); if (ret) goto done; } ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags), sizeof(env_new.flags), &flag); if (ret) goto done; puts("done\n"); gd->env_valid = gd->env_valid == 2 ? 1 : 2; printf("Valid environment: %d\n", (int)gd->env_valid); done: if (saved_buffer) free(saved_buffer); return ret; }
int saveenv(void) { u32 saved_size, saved_offset, sector = 1; char *res, *saved_buffer = NULL; int ret = 1; env_t env_new; ssize_t len; if (!env_flash) { env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); if (!env_flash) { set_default_env("!spi_flash_probe() failed"); return 1; } } /* Is the sector larger than the env (i.e. embedded) */ if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE; saved_buffer = malloc(saved_size); if (!saved_buffer) goto done; ret = spi_flash_read(env_flash, saved_offset, saved_size, saved_buffer); if (ret) goto done; } if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) { sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE; if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE) sector++; } res = (char *)&env_new.data; len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); goto done; } env_new.crc = crc32(0, env_new.data, ENV_SIZE); puts("Erasing SPI flash..."); ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, sector * CONFIG_ENV_SECT_SIZE); if (ret) goto done; puts("Writing to SPI flash..."); ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, &env_new); if (ret) goto done; if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { ret = spi_flash_write(env_flash, saved_offset, saved_size, saved_buffer); if (ret) goto done; } ret = 0; puts("done\n"); done: if (saved_buffer) free(saved_buffer); return ret; }
void env_relocate_spec(void) { int ret; int crc1_ok = 0, crc2_ok = 0; env_t *tmp_env1 = NULL; env_t *tmp_env2 = NULL; env_t *ep = NULL; tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE); tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE); if (!tmp_env1 || !tmp_env2) { set_default_env("!malloc() failed"); goto out; } env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); if (!env_flash) { set_default_env("!spi_flash_probe() failed"); goto out; } ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, tmp_env1); if (ret) { set_default_env("!spi_flash_read() failed"); goto err_read; } if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc) crc1_ok = 1; ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE, tmp_env2); if (!ret) { if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc) crc2_ok = 1; } if (!crc1_ok && !crc2_ok) { set_default_env("!bad CRC"); goto err_read; } else if (crc1_ok && !crc2_ok) { gd->env_valid = 1; } else if (!crc1_ok && crc2_ok) { gd->env_valid = 2; } else if (tmp_env1->flags == ACTIVE_FLAG && tmp_env2->flags == OBSOLETE_FLAG) { gd->env_valid = 1; } else if (tmp_env1->flags == OBSOLETE_FLAG && tmp_env2->flags == ACTIVE_FLAG) { gd->env_valid = 2; } else if (tmp_env1->flags == tmp_env2->flags) { gd->env_valid = 2; } else if (tmp_env1->flags == 0xFF) { gd->env_valid = 2; } else { /* * this differs from code in env_flash.c, but I think a sane * default path is desirable. */ gd->env_valid = 2; } if (gd->env_valid == 1) ep = tmp_env1; else ep = tmp_env2; ret = env_import((char *)ep, 0); if (!ret) { error("Cannot import environment: errno = %d\n", errno); set_default_env("env_import failed"); } err_read: spi_flash_free(env_flash); env_flash = NULL; out: free(tmp_env1); free(tmp_env2); }