From 3be5e78a09f7f6117cb07d480a137d88c7f377b7 Mon Sep 17 00:00:00 2001 From: Renze Nicolai Date: Fri, 13 May 2022 00:13:14 +0200 Subject: [PATCH 1/2] Restructuring of the init functions, display more detailed error messages on failed init --- .../mch2022-bsp/esp_efuse_custom_table.csv | 16 --- components/mch2022-bsp/hardware.c | 130 +++++++++++++----- components/mch2022-bsp/hardware.h | 9 +- main/main.c | 87 +++++++----- main/rp2040_updater.c | 4 +- 5 files changed, 157 insertions(+), 89 deletions(-) delete mode 100644 components/mch2022-bsp/esp_efuse_custom_table.csv diff --git a/components/mch2022-bsp/esp_efuse_custom_table.csv b/components/mch2022-bsp/esp_efuse_custom_table.csv deleted file mode 100644 index e9b0b1d..0000000 --- a/components/mch2022-bsp/esp_efuse_custom_table.csv +++ /dev/null @@ -1,16 +0,0 @@ -# After editing this file, run the command manually "make efuse_custom_table" or "idf.py efuse_custom_table" - -# WR_DIS_EFUSE_RD_DISABLE, EFUSE_BLK0, 0, 1, Write protection for RD_DIS, ADC_VREF -WR_DIS_WR_DIS, EFUSE_BLK0, 1, 1, Write protection for WR_DIS -# WR_DIS_FLASH_CRYPT_CNT, EFUSE_BLK0, 2, 1, Write protection for FLASH_CRYPT_CNT, UART_DOWNLOAD_DIS -WR_DIS_MAC_AND_CHIP_INFO, EFUSE_BLK0, 3, 1, Write protection for MAC, MAC_CRC, CIP_VER_REV1, CHIP_VERSION, CHIP_PACKAGE -WR_DIS_XPD, EFUSE_BLK0, 5, 1, Write protection for XPD_SDIO_FORCE, XPD_SDIO_REG, XPD_SDIO_TIEH -WR_DIS_SPI_PAD, EFUSE_BLK0, 6, 1, Write protection for CHIP_VER_REV2, SPI_PAD_CONFIG -# WR_DIS_BLK1, EFUSE_BLK0, 7, 1, Write protection for WR_DIS_BLK1 -# WR_DIS_BLK2, EFUSE_BLK0, 8, 1, Write protection for WR_DIS_BLK2 -# WR_DIS_BLK3, EFUSE_BLK0, 9, 1, Write protection for WR_DIS_BLK3, MAC_VERSION -WR_DIS_SCHEME_KEY_CRYPT, EFUSE_BLK0, 10, 1, Write protection for CODING_SCHEME, KEY_STATUS, FLASH_CRYPT_CONFIG, BLK3_PART_RESERVE -WR_DIS_ABS_DONE_0, EFUSE_BLK0, 12, 1, Write protection for ABS_DONE_0 -WR_DIS_ABS_DONE_1, EFUSE_BLK0, 13, 1, Write protection for ABS_DONE_1 -WR_DIS_JTAG_DISABLE, EFUSE_BLK0, 14, 1, Write protection for JTAG_DISABLE -WR_DIS_CONSOLE_DEBUG_AND_DISABLE_DL_CRYPT, EFUSE_BLK0, 15, 1, Write protection for CONSOLE_DEBUG_DISABLE, DISABLE_DL diff --git a/components/mch2022-bsp/hardware.c b/components/mch2022-bsp/hardware.c index b2d03d7..bf0b517 100644 --- a/components/mch2022-bsp/hardware.c +++ b/components/mch2022-bsp/hardware.c @@ -13,11 +13,18 @@ static ILI9341 dev_ili9341 = {0}; static ICE40 dev_ice40 = {0}; static RP2040 dev_rp2040 = {0}; +static uint8_t rp2040_fw_version = 0; + +static bool bsp_ready = false; +static bool rp2040_ready = false; +static bool ice40_ready = false; +static bool bno055_ready = false; + esp_err_t ice40_get_done_wrapper(bool* done) { - uint8_t buttons[2]; - esp_err_t res = rp2040_read_buttons(&dev_rp2040, buttons); + uint16_t buttons; + esp_err_t res = rp2040_read_buttons(&dev_rp2040, &buttons); if (res != ESP_OK) return res; - *done = !((buttons[0] >> 5) & 0x01); + *done = !((buttons >> 5) & 0x01); printf("FPGA done is %u\n", *done); return ESP_OK; } @@ -64,10 +71,16 @@ static esp_err_t _bus_init() { return ESP_OK; } -// Board init +/* BSP init + * + * This function initializes the interrupt handling service, the SPI and I2C busses and the LCD display. + * After running this function information can be displayed to the user via the display. + * + */ -esp_err_t board_init(bool* aLcdReady) { - if (aLcdReady != NULL) *aLcdReady = false; +esp_err_t bsp_init() { + if (bsp_ready) return ESP_OK; + esp_err_t res; // Interrupts @@ -104,7 +117,20 @@ esp_err_t board_init(bool* aLcdReady) { return res; } - if (aLcdReady != NULL) *aLcdReady = true; + bsp_ready = true; + return ESP_OK; +} + +/* RP2040 init + * + * This function initializes communication with the RP2040 co-processor. + * After running this function the buttons, backlight control and FPGA management functions will be available for use. + * + */ + +esp_err_t bsp_rp2040_init() { + if (!bsp_ready) return ESP_FAIL; + if (rp2040_ready) return ESP_OK; // RP2040 co-processor dev_rp2040.i2c_bus = I2C_BUS_SYS; @@ -112,60 +138,92 @@ esp_err_t board_init(bool* aLcdReady) { dev_rp2040.pin_interrupt = GPIO_INT_RP2040; dev_rp2040.queue = xQueueCreate(8, sizeof(rp2040_input_message_t)); - res = rp2040_init(&dev_rp2040); + esp_err_t res = rp2040_init(&dev_rp2040); if (res != ESP_OK) { ESP_LOGE(TAG, "Initializing RP2040 failed"); return res; } - - uint8_t rp2040_fw_version; + if (rp2040_get_firmware_version(&dev_rp2040, &rp2040_fw_version) != ESP_OK) { ESP_LOGE(TAG, "Initializing RP2040 failed to read firmware version"); return ESP_FAIL; } - - if (rp2040_fw_version != 0xFF) { // Only init FPGA when RP2040 is not in bootloader mode - // FPGA - dev_ice40.spi_bus = SPI_BUS; - dev_ice40.pin_cs = GPIO_SPI_CS_FPGA; - dev_ice40.pin_done = -1; - dev_ice40.pin_reset = -1; - dev_ice40.pin_int = GPIO_INT_FPGA; - dev_ice40.spi_speed_full_duplex = 26700000; - dev_ice40.spi_speed_half_duplex = 40000000; - dev_ice40.spi_max_transfer_size = SPI_MAX_TRANSFER_SIZE; - dev_ice40.get_done = ice40_get_done_wrapper; - dev_ice40.set_reset = ice40_set_reset_wrapper; - res = ice40_init(&dev_ice40); - if (res != ESP_OK) { - ESP_LOGE(TAG, "Initializing FPGA failed"); - return res; - } + rp2040_ready = true; + return ESP_OK; +} + +/* RP2040 init + * + * This function initializes the ICE40 FPGA + * After running this function the FPGA will be kept in reset state until a bitstream is loaded + * + */ + +esp_err_t bsp_ice40_init() { + if (!bsp_ready) return ESP_FAIL; + if (!rp2040_ready) return ESP_FAIL; + if (rp2040_fw_version == 0xFF) return ESP_FAIL; // The ICE40 FPGA can only be controlled when the RP2040 is not in bootloader mode + if (rp2040_ready) return ESP_OK; + + dev_ice40.spi_bus = SPI_BUS; + dev_ice40.pin_cs = GPIO_SPI_CS_FPGA; + dev_ice40.pin_done = -1; + dev_ice40.pin_reset = -1; + dev_ice40.pin_int = GPIO_INT_FPGA; + dev_ice40.spi_speed_full_duplex = 26700000; + dev_ice40.spi_speed_half_duplex = 40000000; + dev_ice40.spi_max_transfer_size = SPI_MAX_TRANSFER_SIZE; + dev_ice40.get_done = ice40_get_done_wrapper; + dev_ice40.set_reset = ice40_set_reset_wrapper; + + esp_err_t res = ice40_init(&dev_ice40); + if (res != ESP_OK) { + ESP_LOGE(TAG, "Initializing FPGA failed"); + return res; } - // BNO055 sensor on system I2C bus + ice40_ready = true; + return ESP_OK; +} - res = bno055_init(&dev_bno055, I2C_BUS_SYS, BNO055_ADDR, GPIO_INT_BNO055, true); +/* BNO055 init + * + * This function initializes the BNO055 position sensor + * After running this function the position sensor can be used + * + */ + +esp_err_t bsp_bno055_init() { + if (!bsp_ready) return ESP_FAIL; + if (bno055_ready) return ESP_OK; + + esp_err_t res = bno055_init(&dev_bno055, I2C_BUS_SYS, BNO055_ADDR, GPIO_INT_BNO055, true); if (res != ESP_OK) { ESP_LOGE(TAG, "Initializing BNO055 failed"); return res; } - return res; -} -BNO055* get_bno055() { - return &dev_bno055; + bno055_ready = true; + return ESP_OK; } ILI9341* get_ili9341() { + if (!bsp_ready) return NULL; return &dev_ili9341; } +RP2040* get_rp2040() { + if (!rp2040_ready) return NULL; + return &dev_rp2040; +} + ICE40* get_ice40() { + if (!ice40_ready) return NULL; return &dev_ice40; } -RP2040* get_rp2040() { - return &dev_rp2040; +BNO055* get_bno055() { + if (!bno055_ready) return NULL; + return &dev_bno055; } diff --git a/components/mch2022-bsp/hardware.h b/components/mch2022-bsp/hardware.h index 151cee1..e74706c 100644 --- a/components/mch2022-bsp/hardware.h +++ b/components/mch2022-bsp/hardware.h @@ -55,9 +55,12 @@ #define GPIO_SPI_CS_LCD 32 #define GPIO_SPI_DC_LCD 33 -esp_err_t board_init(bool* aLcdReady); +esp_err_t bsp_init(); +esp_err_t bsp_rp2040_init(); +esp_err_t bsp_ice40_init(); +esp_err_t bsp_bno055_init(); -BNO055* get_bno055(); ILI9341* get_ili9341(); -ICE40* get_ice40(); RP2040* get_rp2040(); +ICE40* get_ice40(); +BNO055* get_bno055(); diff --git a/main/main.c b/main/main.c index 88a663f..cdc0ed6 100644 --- a/main/main.c +++ b/main/main.c @@ -262,6 +262,23 @@ void menu_wifi_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341 menu_free(menu); } +void display_boot_screen(pax_buf_t* pax_buffer, ILI9341* ili9341) { + pax_noclip(pax_buffer); + pax_background(pax_buffer, 0x325aa8); + pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*0, "Starting launcher..."); + ili9341_write(ili9341, pax_buffer->buf); +} + +void display_fatal_error(pax_buf_t* pax_buffer, ILI9341* ili9341, const char* line0, const char* line1, const char* line2, const char* line3) { + pax_noclip(pax_buffer); + pax_background(pax_buffer, 0xa85a32); + if (line0 != NULL) pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 18, 0, 20*0, line0); + if (line1 != NULL) pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 12, 0, 20*1, line1); + if (line2 != NULL) pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 12, 0, 20*2, line2); + if (line3 != NULL) pax_draw_text(pax_buffer, 0xFFFFFFFF, NULL, 12, 0, 20*3, line3); + ili9341_write(ili9341, pax_buffer->buf); +} + void app_main(void) { esp_err_t res; @@ -269,14 +286,14 @@ void app_main(void) { uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT); if (framebuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate framebuffer"); - restart(); + esp_restart(); } memset(framebuffer, 0, ILI9341_BUFFER_SIZE); pax_buf_t* pax_buffer = malloc(sizeof(pax_buf_t)); if (framebuffer == NULL) { - ESP_LOGE(TAG, "Failed to allocate pax buffer"); - restart(); + ESP_LOGE(TAG, "Failed to allocate buffer for PAX graphics library"); + esp_restart(); } memset(pax_buffer, 0, sizeof(pax_buf_t)); @@ -285,60 +302,66 @@ void app_main(void) { /* Initialize hardware */ efuse_protect(); - - bool lcdReady = false; - res = board_init(&lcdReady); - if (res != ESP_OK) { - if (lcdReady) { - ILI9341* ili9341 = get_ili9341(); - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Hardware error!"); - } - printf("Failed to initialize hardware!\n"); - restart(); + if (bsp_init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize basic board support functions"); + esp_restart(); } ILI9341* ili9341 = get_ili9341(); - ICE40* ice40 = get_ice40(); - BNO055* bno055 = get_bno055(); + + display_boot_screen(pax_buffer, ili9341); + + if (bsp_rp2040_init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize the RP2040 co-processor"); + display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "RP2040 co-processor error", NULL, NULL); + esp_restart(); + } + RP2040* rp2040 = get_rp2040(); + rp2040_updater(rp2040, pax_buffer, ili9341, framebuffer); // Handle RP2040 firmware update & bootloader mode + + if (bsp_ice40_init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize the ICE40 FPGA"); + display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "ICE40 FPGA error", NULL, NULL); + esp_restart(); + } + + ICE40* ice40 = get_ice40(); + + if (bsp_bno055_init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize the BNO055 position sensor"); + display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "BNO055 sensor error", "Check I2C bus", "Remove SAO and try again"); + esp_restart(); + } + + BNO055* bno055 = get_bno055(); + /* Start AppFS */ - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init..."); res = appfs_init(); if (res != ESP_OK) { ESP_LOGE(TAG, "AppFS init failed: %d", res); - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init failed!"); - return; + display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "AppFS failed to initialize", "Flash may be corrupted", NULL); + esp_restart(); } - ESP_LOGI(TAG, "AppFS initialized"); /* Start NVS */ - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "NVS init..."); res = nvs_init(); if (res != ESP_OK) { ESP_LOGE(TAG, "NVS init failed: %d", res); - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "NVS init failed!"); - return; + display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "NVS failed to initialize", "Flash may be corrupted", NULL); + esp_restart(); } - ESP_LOGI(TAG, "NVS initialized"); /* Start SD card */ - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Mount SD card..."); res = mount_sd(SD_CMD, SD_CLK, SD_D0, SD_PWR, "/sd", false, 5); bool sdcard_ready = (res == ESP_OK); - - if (sdcard_ready) { - graphics_task(pax_buffer, ili9341, framebuffer, NULL, "SD card mounted"); - } - + /* Start LEDs */ ws2812_init(GPIO_LED_DATA); uint8_t ledBuffer[15] = {50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0}; ws2812_send_data(ledBuffer, sizeof(ledBuffer)); - - /* Start RP2040 firmware update check */ - rp2040_updater(rp2040, pax_buffer, ili9341, framebuffer); /* Launcher menu */ while (true) { diff --git a/main/rp2040_updater.c b/main/rp2040_updater.c index 48edef9..3f2d52e 100644 --- a/main/rp2040_updater.c +++ b/main/rp2040_updater.c @@ -33,13 +33,13 @@ void rp2040_updater(RP2040* rp2040, pax_buf_t* pax_buffer, ILI9341* ili9341, uin restart(); } - pax_noclip(pax_buffer); + /*pax_noclip(pax_buffer); pax_background(pax_buffer, 0xCCCCCC); memset(message, 0, sizeof(message)); snprintf(message, sizeof(message) - 1, "RP2040 firmware: 0x%02X", fw_version); pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 0, 20*0, message); ili9341_write(ili9341, framebuffer); - vTaskDelay(100 / portTICK_PERIOD_MS); + vTaskDelay(100 / portTICK_PERIOD_MS);*/ if (fw_version < 0x01) { // Update required pax_noclip(pax_buffer); From 90636e01c638ed7bada9d2f661d4d8660c7a6619 Mon Sep 17 00:00:00 2001 From: Renze Nicolai Date: Fri, 13 May 2022 13:22:03 +0200 Subject: [PATCH 2/2] Fix wrong exit condition in ice40_init, add extra checks to main --- components/mch2022-bsp/hardware.c | 2 +- main/main.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/components/mch2022-bsp/hardware.c b/components/mch2022-bsp/hardware.c index bf0b517..3bb672a 100644 --- a/components/mch2022-bsp/hardware.c +++ b/components/mch2022-bsp/hardware.c @@ -164,7 +164,7 @@ esp_err_t bsp_ice40_init() { if (!bsp_ready) return ESP_FAIL; if (!rp2040_ready) return ESP_FAIL; if (rp2040_fw_version == 0xFF) return ESP_FAIL; // The ICE40 FPGA can only be controlled when the RP2040 is not in bootloader mode - if (rp2040_ready) return ESP_OK; + if (ice40_ready) return ESP_OK; dev_ice40.spi_bus = SPI_BUS; dev_ice40.pin_cs = GPIO_SPI_CS_FPGA; diff --git a/main/main.c b/main/main.c index cdc0ed6..9d8b981 100644 --- a/main/main.c +++ b/main/main.c @@ -309,6 +309,11 @@ void app_main(void) { } ILI9341* ili9341 = get_ili9341(); + if (ili9341 == NULL) { + ESP_LOGE(TAG, "ili9341 is NULL"); + esp_restart(); + } + display_boot_screen(pax_buffer, ili9341); @@ -319,6 +324,10 @@ void app_main(void) { } RP2040* rp2040 = get_rp2040(); + if (rp2040 == NULL) { + ESP_LOGE(TAG, "rp2040 is NULL"); + esp_restart(); + } rp2040_updater(rp2040, pax_buffer, ili9341, framebuffer); // Handle RP2040 firmware update & bootloader mode @@ -329,6 +338,10 @@ void app_main(void) { } ICE40* ice40 = get_ice40(); + if (ice40 == NULL) { + ESP_LOGE(TAG, "ice40 is NULL"); + esp_restart(); + } if (bsp_bno055_init() != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize the BNO055 position sensor"); @@ -337,6 +350,10 @@ void app_main(void) { } BNO055* bno055 = get_bno055(); + if (bno055 == NULL) { + ESP_LOGE(TAG, "bno055 is NULL"); + esp_restart(); + } /* Start AppFS */ res = appfs_init();