static void dumpll(lldesc_t *ll) { ets_printf("****LL DUMP****\n"); ets_printf("Size %d\n", ll->size); ets_printf("Len: %d\n", ll->length); ets_printf("Owner: %s\n", ll->owner ? "dma" : "cpu"); }
uint8_t init_i2c(void) { ets_printf("I2C stack init ... "); brzo_i2c_setup(100); ets_printf("success\r\n"); return 0; }
/** Sets up the UART so we can get debugging output from the bootloader */ void NOINLINE setupSerial(void) { // Update the clock rate here since it's the first function we call //uart_div_modify(0, CPU_CLK_FREQ/115200); // Debugging delay //ets_delay_us(2000000); ets_printf("Welcome to dboot\r\n"); ets_printf("Version commit %x\r\nBuild by %s on %s\r\n", VERSION_COMMIT, USER, BUILD_DATE); }
void toggle_pca9685_leds(uint8_t addr, bool desired_state) { uint8_t rc; bool will_be_on; uint8_t bytes[8]; // Turn all LEDs on or off // To turn specific LEDs on or off set byte 0 (register) to 0x06 for LED 0, // 0x0A for LED 1, 0x0E for LED2, ... bytes[0] = 0xfa; // All LEDs // bytes[0] = 0x06; // LED 0 only ets_printf("Turn LED(s) "); if (!desired_state) { // Turn off ets_printf("off ... "); bytes[1] = 0; bytes[2] = 0; bytes[3] = 0; bytes[4] = 0b00010000; will_be_on = FALSE; } else { // Turn on ets_printf("on ... "); bytes[1] = 0; bytes[2] = 0b00010000; bytes[3] = 0; bytes[4] = 0; will_be_on = TRUE; } brzo_i2c_start_transaction(addr, 100); brzo_i2c_write(bytes, 5, FALSE); rc = brzo_i2c_end_transaction(); if (rc) { ets_printf("failed: %d\r\n", rc); goto EXIT_LABEL; } if (!rc) { ets_printf("success\r\n"); } pca9685_on = will_be_on; EXIT_LABEL: return; }
/** Command SPI flash to make certain sectors read only until next power cycle * @note Must be NOINLINE and not static to call from ASM without generating a stack which will be left in memory */ void NOINLINE writeProtect(void) { uint32 factoryDoneFlag = 0xFFFFffff; uint8 protectSectors = 1; // Always protecting outselves SPIRead(FACTORY_SECTOR * SECTOR_SIZE + SECTOR_SIZE - 4, &factoryDoneFlag, 4); // Read the last word from the factory sector if (factoryDoneFlag != 0xFFFFffff) { ets_printf("Factory done flag %08x, write protecting factory sector\r\n", factoryDoneFlag); protectSectors++; // If there's data there, write protect the factory sector } // XXX Exectute the flash protect command! ets_printf("WARNING: Flash write protection not yet implemented\r\n"); }
void IRAM NORETURN panic_arch(void) { #if defined(DEVELHELP) struct mallinfo minfo = mallinfo(); ets_printf("heap: %lu (free %lu) byte\n", &_eheap - &_sheap, get_free_heap_size()); ets_printf("sysmem: %d (used %d, free %d)\n", minfo.arena, minfo.uordblks, minfo.fordblks); ets_printf(" \n"); ets_printf(" \n"); #endif /* hard reset */ __asm__ volatile (" call0 0x40000080 "); UNREACHABLE(); }
static void dumpregs(spi_dev_t *hw) { ets_printf("***REG DUMP ***\n"); ets_printf("mosi_dlen : %08X\n", hw->mosi_dlen.val); ets_printf("miso_dlen : %08X\n", hw->miso_dlen.val); ets_printf("slv_wrbuf_dlen : %08X\n", hw->slv_wrbuf_dlen.val); ets_printf("slv_rdbuf_dlen : %08X\n", hw->slv_rdbuf_dlen.val); ets_printf("slave : %08X\n", hw->slave.val); ets_printf("slv_rdata_bit : %x\n", hw->slv_rd_bit.slv_rdata_bit); ets_printf("dma_rx_status : %08X\n", hw->dma_rx_status); ets_printf("dma_tx_status : %08X\n", hw->dma_tx_status); }
static void task1(void *arg) { testtype_t oldtest; char buf[100]; int i = 0; int x, r; while (1) { oldtest = testtype; if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) { for (x = 0; x < 10; x++) { sprintf(buf, "This is test %d item %d.", (int)testtype, i++); ets_printf("TSK w"); xRingbufferPrintInfo(rb); r = xRingbufferSend(rb, buf, strlen(buf) + 1, 2000 / portTICK_PERIOD_MS); if (!r) { printf("Test %d: Timeout on send!\n", (int)testtype); } if (testtype == TST_MOSTLYEMPTY) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } //Send NULL event to stop other side. r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS); } while (oldtest == testtype) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } }
void firmware_start(void) { // For SDK 1.5.2, either address has shifted and not mirrored in // eagle.rom.addr.v6.ld, or extra initial member was added. SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); char buf[128]; SPIRead(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); /*for (int i = 0; i < sizeof(buf); i++) { static char hexf[] = "%x "; ets_printf(hexf, buf[i]); }*/ bool inited = false; for (int i = 0; i < sizeof(buf); i++) { if (buf[i] != 0xff) { inited = true; break; } } if (!inited) { static char msg[] = "Writing init data\n"; ets_printf(msg); SPIRead((uint32_t)&default_init_data - 0x40200000, buf, sizeof(buf)); SPIWrite(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); } asm("j call_user_start"); }
/** * Verbose debug output */ void debug_message(const char *module, const char *format, ...) { #define BUFFER_SIZE 150 char buf[BUFFER_SIZE]; ets_printf("%08d [%-6s] ", millis(), module); // snprintf(buf, BUFFER_SIZE, "%6.3f [%-6s] ", millis()/1000.0, module); va_list args; va_start(args, format); vsnprintf(buf, BUFFER_SIZE, format, args); ets_printf(buf); va_end(args); if (ESP.getFreeHeap() < g_minFreeHeap) { g_minFreeHeap = ESP.getFreeHeap(); } }
static void task2(void *arg) { testtype_t oldtest; char *buf; size_t len; while (1) { oldtest = testtype; if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) { while (1) { ets_printf("TSK r"); xRingbufferPrintInfo(rb); buf = xRingbufferReceive(rb, &len, 2000 / portTICK_PERIOD_MS); if (buf == NULL) { printf("Test %d: Timeout on recv!\n", (int)testtype); } else if (len == 0) { printf("End packet received.\n"); vRingbufferReturnItem(rb, buf); break; } else { printf("Received: %s (%d bytes, %p)\n", buf, len, buf); vRingbufferReturnItem(rb, buf); } if (testtype == TST_MOSTLYFILLED) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } } while (oldtest == testtype) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } }
void call_user_start(void) { uint8 loop; for(loop = 0; loop < 50; loop++) { ets_printf("testload 1\r\n"); ets_delay_us(20000); } }
void vPortFree(void *pv, const char * file, unsigned line) #endif { uint8_t *puc = ( uint8_t * ) pv; BlockLink_t *pxLink; if( pv != NULL ) { /* The memory being freed will have an BlockLink_t structure immediately before it. */ puc -= uxHeapStructSize; /* This casting is to keep the compiler from issuing warnings. */ pxLink = ( void * ) puc; /* Check the block is actually allocated. */ configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); configASSERT( pxLink->pxNextFreeBlock == NULL ); if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) { #ifndef MEMLEAK_DEBUG if( pxLink->pxNextFreeBlock == NULL ) #endif { /* The block is being returned to the heap - it is no longer allocated. */ pxLink->xBlockSize &= ~xBlockAllocatedBit; //vTaskSuspendAll(); ETS_INTR_LOCK(); #ifdef MEMLEAK_DEBUG if(prvRemoveBlockFromUsedList(pxLink) < 0){ ets_printf("%x already freed\n", pv); } else #endif { /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; traceFREE( pv, pxLink->xBlockSize ); prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); } // ( void ) xTaskResumeAll(); ETS_INTR_UNLOCK(); } #ifndef MEMLEAK_DEBUG else { mtCOVERAGE_TEST_MARKER(); } #endif } else { mtCOVERAGE_TEST_MARKER(); } } }
void es8388_read_all() { for (int i = 0; i < 50; i++) { uint8_t reg = 0; es_read_reg(i, ®); ets_printf("%x: %x\n", i, reg); } }
static void loop_task(os_event_t *events) { g_micros_at_task_start = system_get_time(); cont_run(&g_cont, &loop_wrapper); if(cont_check(&g_cont) != 0) { ets_printf("\r\nsketch stack overflow detected\r\n"); abort(); } }
void loop_task(os_event_t *events) { g_micros_at_task_start = system_get_time(); cont_run(&g_cont, &loop_wrapper); if(cont_check(&g_cont) != 0) { ets_printf("\r\nheap collided with sketch stack\r\n"); abort(); } }
static void touch_press_2s_cb(void *arg) { CTouchPad *tp = (CTouchPad*) arg; touch_pad_t tp_num = tp->tp_num(); oled_evt_t evt; evt.type = OLED_EVT_SLEEP; xQueueSend(oled_queue, &evt, portMAX_DELAY); ets_printf("press_2s_cb tap callback of touch pad num %d\n", tp_num); }
uint8_t init_pca9685(uint8_t addr) { uint8_t rc; uint8_t bytes[2]; ets_printf("PCA9685 init ... "); // Write MODE1 register (key bits are to set auto-increment and turn off sleep mode bytes[0] = 0x00; // MODE1 register bytes[1] = 0b00100001; // reset = 1, AI = 1, sleep = 0, allcall = 1 brzo_i2c_start_transaction(addr, 100); brzo_i2c_write(bytes, 2, FALSE); rc = brzo_i2c_end_transaction(); if (rc) { ets_printf("failed write: %d\r\n", rc); goto EXIT_LABEL; } // Now read back the register to check it took brzo_i2c_start_transaction(addr, 100); brzo_i2c_write(bytes, 1, FALSE); brzo_i2c_read(bytes, 1, FALSE); rc = brzo_i2c_end_transaction(); if (!rc) { if (bytes[0] == bytes[1]) { ets_printf("success\r\n"); goto EXIT_LABEL; } else { ets_printf("failed read mismatch: 0x%02x\r\n", bytes[0]); } } else { ets_printf("failed read: %d\r\n", rc); } EXIT_LABEL: return rc; }
static void esp_apptrace_test_timer_isr_crash(void *arg) { esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg; if (tim_arg->group == 0) { if (tim_arg->id == 0) { TIMERG0.int_clr_timers.t0 = 1; TIMERG0.hw_timer[0].update = 1; TIMERG0.hw_timer[0].config.alarm_en = 1; } else { TIMERG0.int_clr_timers.t1 = 1; TIMERG0.hw_timer[1].update = 1; TIMERG0.hw_timer[1].config.alarm_en = 1; } } if (tim_arg->group == 1) { if (tim_arg->id == 0) { TIMERG1.int_clr_timers.t0 = 1; TIMERG1.hw_timer[0].update = 1; TIMERG1.hw_timer[0].config.alarm_en = 1; } else { TIMERG1.int_clr_timers.t1 = 1; TIMERG1.hw_timer[1].update = 1; TIMERG1.hw_timer[1].config.alarm_en = 1; } } if (tim_arg->data.wr_cnt < ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH) { uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t)); *ts = (uint32_t)esp_apptrace_test_ts_get();//xthal_get_ccount();//xTaskGetTickCount(); memset(tim_arg->data.buf + 2 * sizeof(uint32_t), tim_arg->data.wr_cnt & tim_arg->data.mask, tim_arg->data.buf_sz - 2 * sizeof(uint32_t)); int res = ESP_APPTRACE_TEST_WRITE_FROM_ISR(tim_arg->data.buf, tim_arg->data.buf_sz); if (res != ESP_OK) { ets_printf("tim-%d-%d: Failed to write trace %d %x!\n", tim_arg->group, tim_arg->id, res, tim_arg->data.wr_cnt & tim_arg->data.mask); } else { ets_printf("tim-%d-%d: Written chunk%d %d bytes, %x\n", tim_arg->group, tim_arg->id, tim_arg->data.wr_cnt, tim_arg->data.buf_sz, tim_arg->data.wr_cnt & tim_arg->data.mask); tim_arg->data.wr_cnt++; } } else { uint32_t *ptr = 0; *ptr = 1000; } }
static void touch_press_1s_cb(void *arg) { CTouchPad *tp = (CTouchPad*) arg; touch_pad_t tp_num = tp->tp_num(); if (tp_num == 9) { oled_next_page(); } else if (tp_num == 8) { oled_prev_page(); } ets_printf("press_1s_cb tap callback of touch pad num %d\n", tp_num); }
//============================================================================= // get_seg_size //----------------------------------------------------------------------------- uint32 get_seg_size(uint32_t faddr) { struct SPIFlashHeader sffh; SPIRead(faddr, &sffh, sizeof(sffh)); if(sffh.head.id == 0xe9) return 0; if(sffh.head.id != 0xea || sffh.head.number_segs != 4) { // Number of segments ets_printf("get flash_addr error!\n"); return 0xffffffff; } return sffh.seg.segment_size; }
void IRAM NORETURN exception_handler (void *arg) { (void)arg; uint32_t excsave1; uint32_t excvaddr; uint32_t exccause; RSR(excsave1, excsave1); RSR(excvaddr, excvaddr); RSR(exccause, exccause); (void)exception_names; ets_printf("EXCEPTION!! exccause=%d (%s) @%08lx excvaddr=%08lx\n", exccause, exception_names[exccause], excsave1, excvaddr); #if defined(DEVELHELP) #if defined(MODULE_PS) ps(); #endif struct mallinfo minfo = mallinfo(); ets_printf("heap: %lu (free %lu) byte\n", &_eheap - &_sheap, get_free_heap_size()); ets_printf("sysmem: %d (used %d, free %d)\n", minfo.arena, minfo.uordblks, minfo.fordblks); #endif /* flushing the buffer */ ets_printf(" \n"); ets_printf(" \n"); ets_printf(" \n"); /* hard reset */ __asm__ volatile (" call0 0x40000080 "); UNREACHABLE(); }
/****************************************************************************** * FunctionName : spi_flash_read * Description : чтение массива байт из flash * читает из flash по QSPI блоками по SPI_FBLK байт * в ROM-BIOS SPI_FBLK = 32 байта, 64 - предел SPI буфера * Parameters : flash Addr, pointer, кол-во * Returns : SpiFlashOpResult 0 - ok * Опции gcc: -mno-serialize-volatile ! *******************************************************************************/ SpiFlashOpResult __attribute__((optimize("O2"))) spi_flash_read(uint32 faddr, void *des, uint32 size) { #if DEBUGSOO > 5 ets_printf("fread:%p<-%p[%u]\n", des, faddr, size); #endif if(des == NULL) return SPI_FLASH_RESULT_ERR; if(size != 0) { faddr <<= 8; faddr >>= 8; Cache_Read_Disable(); Wait_SPI_Idle(flashchip); uint32 blksize = (uint32)des & 3; if(blksize) { blksize = 4 - blksize; if(size < blksize) blksize = size; SPI0_ADDR = faddr | (blksize << 24); SPI0_CMD = SPI_READ; size -= blksize; faddr += blksize; while(SPI0_CMD); register uint32 data_buf = SPI0_W0; do { *(uint8 *)des = data_buf; des = (uint8 *)des + 1; data_buf >>= 8; } while(--blksize); } while(size) { if(size < SPI_FBLK) blksize = size; else blksize = SPI_FBLK; SPI0_ADDR = faddr | (blksize << 24); SPI0_CMD = SPI_READ; size -= blksize; faddr += blksize; while(SPI0_CMD); uint32 *srcdw = (uint32 *)(&SPI0_W0); while(blksize >> 2) { *((uint32 *)des) = *srcdw++; des = ((uint32 *)des) + 1; blksize -= 4; } if(blksize) { uint32 data_buf = *srcdw; do { *(uint8 *)des = data_buf; des = (uint8 *)des + 1; data_buf >>= 8; } while(--blksize); break; } } Cache_Read_Enable_def(); }
static void task_wdt_isr(void *arg) { wdt_task_t *wdttask; const char *cpu; //Feed the watchdog so we do not reset TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; //Ack interrupt TIMERG0.int_clr_timers.wdt=1; //We are taking a spinlock while doing I/O (ets_printf) here. Normally, that is a pretty //bad thing, possibly (temporarily) hanging up the 2nd core and stopping FreeRTOS. In this case, //something bad already happened and reporting this is considered more important //than the badness caused by a spinlock here. portENTER_CRITICAL(&taskwdt_spinlock); if (!wdt_task_list) { //No task on list. Maybe none registered yet. portEXIT_CRITICAL(&taskwdt_spinlock); return; } //Watchdog got triggered because at least one task did not report in. ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n"); for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) { if (!wdttask->fed_watchdog) { cpu=xTaskGetAffinity(wdttask->task_handle)==0?DRAM_STR("CPU 0"):DRAM_STR("CPU 1"); if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu=DRAM_STR("CPU 0/1"); ets_printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu); } } ets_printf(DRAM_STR("Tasks currently running:\n")); for (int x=0; x<portNUM_PROCESSORS; x++) { ets_printf("CPU %d: %s\n", x, pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(x))); } #if CONFIG_TASK_WDT_PANIC ets_printf("Aborting.\n"); abort(); #endif portEXIT_CRITICAL(&taskwdt_spinlock); }
static void read_write_task(void* param) { read_write_test_arg_t* args = (read_write_test_arg_t*) param; FILE* f = fopen(args->filename, args->write ? "wb" : "rb"); if (f == NULL) { args->result = ESP_ERR_NOT_FOUND; goto done; } srand(args->seed); for (size_t i = 0; i < args->word_count; ++i) { uint32_t val = rand(); if (args->write) { int cnt = fwrite(&val, sizeof(val), 1, f); if (cnt != 1) { ets_printf("E(w): i=%d, cnt=%d val=%d\n\n", i, cnt, val); args->result = ESP_FAIL; goto close; } } else { uint32_t rval; int cnt = fread(&rval, sizeof(rval), 1, f); if (cnt != 1) { ets_printf("E(r): i=%d, cnt=%d rval=%d\n\n", i, cnt, rval); args->result = ESP_FAIL; goto close; } } } args->result = ESP_OK; close: fclose(f); done: xSemaphoreGive(args->done); vTaskDelay(1); vTaskDelete(NULL); }
uint8_t reset_i2c(void) { uint8_t rc; uint8_t bytes[2]; ets_printf("I2C Software Reset Call ... "); bytes[0] = 0; // general call address bytes[1] = 0b00000110; // SWRST data brzo_i2c_start_transaction(PCA9685_ADDR, 100); brzo_i2c_write(bytes, 2, FALSE); rc = brzo_i2c_end_transaction(); if (!rc) { ets_printf("success\r\n"); } else { ets_printf("failed\r\n"); } return rc; }
/* * For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked. */ void vPortCPUInitializeMutex(portMUX_TYPE *mux) { #if defined(CONFIG_SPIRAM_SUPPORT) // Check if mux belongs to internal memory (DRAM), prerequisite for atomic operations configASSERT(esp_ptr_internal((const void *) mux)); #endif #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG ets_printf("Initializing mux %p\n", mux); mux->lastLockedFn="(never locked)"; mux->lastLockedLine=-1; #endif mux->owner=portMUX_FREE_VAL; mux->count=0; }
int IRAM os_printf_plus (const char* format, ...) { va_list arglist; va_start(arglist, format); int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, format, arglist); if (ret > 0) { ets_printf (_printf_buf); } va_end(arglist); return ret; }
static void esp_apptrace_test_timer_isr(void *arg) { esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg; uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t)); *ts = (uint32_t)esp_apptrace_test_ts_get(); memset(tim_arg->data.buf + 2 * sizeof(uint32_t), tim_arg->data.wr_cnt & tim_arg->data.mask, tim_arg->data.buf_sz - 2 * sizeof(uint32_t)); int res = ESP_APPTRACE_TEST_WRITE_FROM_ISR(tim_arg->data.buf, tim_arg->data.buf_sz); if (res != ESP_OK) { } else { if (0) { ets_printf("tim-%d-%d: Written chunk%d %d bytes, %x\n", tim_arg->group, tim_arg->id, tim_arg->data.wr_cnt, tim_arg->data.buf_sz, tim_arg->data.wr_cnt & tim_arg->data.mask); } tim_arg->data.wr_err = 0; } tim_arg->data.wr_cnt++; if (tim_arg->group == 0) { if (tim_arg->id == 0) { TIMERG0.int_clr_timers.t0 = 1; TIMERG0.hw_timer[0].update = 1; TIMERG0.hw_timer[0].config.alarm_en = 1; } else { TIMERG0.int_clr_timers.t1 = 1; TIMERG0.hw_timer[1].update = 1; TIMERG0.hw_timer[1].config.alarm_en = 1; } } if (tim_arg->group == 1) { if (tim_arg->id == 0) { TIMERG1.int_clr_timers.t0 = 1; TIMERG1.hw_timer[0].update = 1; TIMERG1.hw_timer[0].config.alarm_en = 1; } else { TIMERG1.int_clr_timers.t1 = 1; TIMERG1.hw_timer[1].update = 1; TIMERG1.hw_timer[1].config.alarm_en = 1; } } }
/** Reads ROM headers and returns relivant information. * This is a separate functions from find_image so it can live in low IRAM and keep high IRAM minimized * @param[in/out] buffer A pointer to memory to use for a read buffer * @param[out] Gets set to the section count from the header * @param[in/out] readpos Used as starting position and gets set to the SPI read position to continue from * @return 0 on failure or firmware entry point on success */ static NOINLINE usercode* check_image(uint32* buffer, uint8* sectcount, uint32* readpos) { rom_header_new *header = (rom_header_new*)buffer; ets_printf("Checking image at %x\r\n", *readpos); // read rom header if (SPIRead(*readpos, header, sizeof(rom_header_new)) != 0) { ets_printf("SPIRead firmware new header failed!\r\n"); return 0; } // check header type if (header->magic == ROM_MAGIC_NEW1 && header->count == ROM_MAGIC_NEW2) { ets_printf("New style ROM header detected\r\n"); // skip the extra header and irom section *readpos = *readpos + header->len + sizeof(rom_header_new); // read the normal header that follows if (SPIRead(*readpos, header, sizeof(rom_header)) != 0) { ets_printf("SPIRead firmware rom header failed!\r\n"); return 0; } if (SPIRead(*readpos, header, sizeof(rom_header)) != 0) { ets_printf("SPIRead secondary header failed\r\n"); return 0; } } if (header->magic == ROM_MAGIC) { // old type, no extra header or irom section to skip over ets_printf("ROM header detected, count = %d, entry = %x\r\n", header->count, header->entry); *readpos += sizeof(rom_header); *sectcount = header->count; return header->entry; } else { ets_printf("No ROM header detected, read %02X from address %x\r\n", header->magic, *readpos); return 0; } }