/****************************************************************************** * FunctionName : Cache_Read_Enable_New * Returns : none *******************************************************************************/ void Cache_Read_Enable_New(void) { #ifdef USE_OVERLAP_MODE if(dual_flash_flag) #ifdef USE_MAX_IRAM Cache_Read_Enable(1,0,0); #else Cache_Read_Enable(1,0,1); #endif else
void rtctime_early_startup (void) { Cache_Read_Enable (0, 0, 1); rtc_time_register_bootup (); rtc_time_switch_clocks (); Cache_Read_Disable (); }
/****************************************************************************** * FunctionName : Cache_Read_Enable_New * Returns : none *******************************************************************************/ void Cache_Read_Enable_New(void) { #ifdef USE_DUAL_FLASH if(dual_flash_flag) Cache_Read_Enable(1,0,1); else #endif Cache_Read_Enable_def(); }
//extern char _text_end; //============================================================================= // IRAM code //============================================================================= // call_user_start() - вызов из заголовка, загрузчиком // ENTRY(call_user_start) in eagle.app.v6.ld //----------------------------------------------------------------------------- void __attribute__ ((noreturn)) call_user_start(void) { // Cache_Read_Disable(); IO_RTC_4 = 0; // Отключить блок WiFi (уменьшение потребления на время загрузки) GPIO0_MUX_alt = VAL_MUX_GPIO0_SDK_DEF; // Отключить вывод CLK на GPIO0 SPI0_USER |= SPI_CS_SETUP; // +1 такт перед CS = 0x80000064 #if FQSPI == 80 // xSPI на 80 MHz GPIO_MUX_CFG_alt |= BIT(MUX_SPI0_CLK_BIT); // QSPI = 80 MHz SPI0_CTRL = (SPI0_CTRL & SPI_CTRL_F_MASK) | SPI_CTRL_F80MHZ; #else // xSPI на 40 MHz GPIO_MUX_CFG_alt &= ~(1<< MUX_SPI0_CLK_BIT); SPI0_CTRL = (SPI0_CTRL & SPI_CTRL_F_MASK) | SPI_CTRL_F40MHZ; #endif // OTA #if DEBUGSOO > 1 p_printf("\nStart OTA loader.\n"); #endif uint32_t buffer[SPI_FLASH_SEC_SIZE/4]; SPIRead(esp_init_data_default_addr + MAX_SYS_CONST_BLOCK, buffer, (sizeof(OTA_flash_struct)+3)&~3); OTA_flash_struct *OTA = (OTA_flash_struct *)buffer; if(OTA->id == OTA_flash_struct_id) { uint32 image_start = OTA->image_addr; uint32 sectors = OTA->image_sectors; SPIRead(image_start, buffer, 4); if(*(uint8 *)buffer == firmware_start_magic) { #if DEBUGSOO > 0 p_printf("Update firmware from 0x%x, %u sectors: ", image_start, sectors); #endif ets_delay_us(1000000); // 1 sec uint32 write_to = 0; for(uint32 i = 0; i < sectors; i++) { SPIRead(image_start + i * SPI_FLASH_SEC_SIZE, buffer, SPI_FLASH_SEC_SIZE); SPIEraseSector(i); SPIWrite(write_to, buffer, SPI_FLASH_SEC_SIZE); write_to += SPI_FLASH_SEC_SIZE; #if DEBUGSOO > 0 p_printf("x"); #endif } #if DEBUGSOO > 0 p_printf("\nOk."); #endif if(image_start >= write_to) SPIEraseSector(image_start / SPI_FLASH_SEC_SIZE); _ResetVector(); } } #if DEBUGSOO > 1 p_printf("\nGoto next loader.\n"); #endif // Всё, включаем кеширование, далее можно вызывать процедуры из flash Cache_Read_Enable(0, 0, 0); // Переход в область кеширования flash, // Запускаем загрузку SDK с указателем на заголовок SPIFlashHeader (находится за данным загручиком по адресу с align 16) // ((loader_call)((uint32)(&loader_flash_boot) + FLASH_BASE - IRAM_BASE + 0x10))((struct SPIFlashHeader *)(((uint32)(&_text_end) + FLASH_BASE - IRAM_BASE + 0x17) & (~15))); ((loader_call)(loader_flash_boot_addr))((struct SPIFlashHeader *)(next_flash_header_addr)); }
/* Prelude ensures exceptions/NMI off and flash is mapped, allowing calls to non-IRAM functions. */ static void IRAM fatal_handler_prelude(void) { if (!sdk_NMIIrqIsOn) { vPortEnterCritical(); do { DPORT.DPORT0 &= 0xffffffe0; } while (DPORT.DPORT0 & 0x00000001); } Cache_Read_Disable(); Cache_Read_Enable(0, 0, 1); }
SpiFlashOpResult IRAM spi_flash_erase_sector(uint16_t sec) { CHECK_PARAM_RET (sec < flashchip->chip_size / flashchip->sector_size, SPI_FLASH_RESULT_ERR); critical_enter (); Cache_Read_Disable(); SpiFlashOpResult ret = SPIEraseSector (sec); Cache_Read_Enable(0, 0, 1); critical_exit (); return ret; }
static void set_cache_and_start_app( uint32_t drom_addr, uint32_t drom_load_addr, uint32_t drom_size, uint32_t irom_addr, uint32_t irom_load_addr, uint32_t irom_size, uint32_t entry_addr) { ESP_LOGD(TAG, "configure drom and irom and start"); Cache_Read_Disable( 0 ); Cache_Flush( 0 ); /* Clear the MMU entries that are already set up, so the new app only has the mappings it creates. */ for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) { DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL; } uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count ); int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count ); ESP_LOGV(TAG, "rc=%d", rc ); rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count ); ESP_LOGV(TAG, "rc=%d", rc ); uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count ); rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count ); ESP_LOGV(TAG, "rc=%d", rc ); rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count ); ESP_LOGV(TAG, "rc=%d", rc ); DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 ); DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 ); Cache_Read_Enable( 0 ); // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) ESP_LOGD(TAG, "start: 0x%08x", entry_addr); typedef void (*entry_t)(void) __attribute__((noreturn)); entry_t entry = ((entry_t) entry_addr); // TODO: we have used quite a bit of stack at this point. // use "movsp" instruction to reset stack back to where ROM stack starts. (*entry)(); }
IRAM NOINSTR void Cache_Read_Enable_New(void) { static uint8_t m1 = 0xff, m2 = 0xff; if (m1 == 0xff) { uint32_t addr; rboot_config conf; Cache_Read_Disable(); SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, &conf, sizeof(conf)); addr = conf.roms[conf.current_rom]; addr /= 0x100000; m1 = addr % 2; m2 = addr / 2; } Cache_Read_Enable(m1, m2, 1); }
SpiFlashOpResult IRAM spi_flash_write (uint32_t faddr, uint32_t *src, size_t size) { /* * For simplicity, we use the ROM function. Since we need to disable the * IROM cache function for that purpose, we have to be in IRAM. * Please note, faddr, src and size have to be aligned to 4 byte */ SpiFlashOpResult ret; CHECK_PARAM_RET (src != NULL, SPI_FLASH_RESULT_ERR); CHECK_PARAM_RET (faddr + size <= flashchip->chip_size, SPI_FLASH_RESULT_ERR); critical_enter (); Cache_Read_Disable (); ret = SPIWrite (faddr, src, size); Cache_Read_Enable(0, 0, 1); critical_exit (); return ret; }