Restructuring of the init functions, display more detailed error messages on failed init

This commit is contained in:
Renze Nicolai 2022-05-13 00:13:14 +02:00
parent ee2def0843
commit 3be5e78a09
5 changed files with 157 additions and 89 deletions

View file

@ -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
Can't render this file because it contains an unexpected character in line 1 and column 53.

View file

@ -13,11 +13,18 @@ static ILI9341 dev_ili9341 = {0};
static ICE40 dev_ice40 = {0}; static ICE40 dev_ice40 = {0};
static RP2040 dev_rp2040 = {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) { esp_err_t ice40_get_done_wrapper(bool* done) {
uint8_t buttons[2]; uint16_t buttons;
esp_err_t res = rp2040_read_buttons(&dev_rp2040, buttons); esp_err_t res = rp2040_read_buttons(&dev_rp2040, &buttons);
if (res != ESP_OK) return res; if (res != ESP_OK) return res;
*done = !((buttons[0] >> 5) & 0x01); *done = !((buttons >> 5) & 0x01);
printf("FPGA done is %u\n", *done); printf("FPGA done is %u\n", *done);
return ESP_OK; return ESP_OK;
} }
@ -64,10 +71,16 @@ static esp_err_t _bus_init() {
return ESP_OK; 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 bsp_init() {
if (bsp_ready) return ESP_OK;
esp_err_t board_init(bool* aLcdReady) {
if (aLcdReady != NULL) *aLcdReady = false;
esp_err_t res; esp_err_t res;
// Interrupts // Interrupts
@ -104,7 +117,20 @@ esp_err_t board_init(bool* aLcdReady) {
return res; 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 // RP2040 co-processor
dev_rp2040.i2c_bus = I2C_BUS_SYS; 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.pin_interrupt = GPIO_INT_RP2040;
dev_rp2040.queue = xQueueCreate(8, sizeof(rp2040_input_message_t)); 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) { if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing RP2040 failed"); ESP_LOGE(TAG, "Initializing RP2040 failed");
return res; return res;
} }
uint8_t rp2040_fw_version;
if (rp2040_get_firmware_version(&dev_rp2040, &rp2040_fw_version) != ESP_OK) { if (rp2040_get_firmware_version(&dev_rp2040, &rp2040_fw_version) != ESP_OK) {
ESP_LOGE(TAG, "Initializing RP2040 failed to read firmware version"); ESP_LOGE(TAG, "Initializing RP2040 failed to read firmware version");
return ESP_FAIL; return ESP_FAIL;
} }
if (rp2040_fw_version != 0xFF) { // Only init FPGA when RP2040 is not in bootloader mode rp2040_ready = true;
// FPGA 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;
res = ice40_init(&dev_ice40); /* RP2040 init
if (res != ESP_OK) { *
ESP_LOGE(TAG, "Initializing FPGA failed"); * This function initializes the ICE40 FPGA
return res; * 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) { if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing BNO055 failed"); ESP_LOGE(TAG, "Initializing BNO055 failed");
return res; return res;
} }
return res;
}
BNO055* get_bno055() { bno055_ready = true;
return &dev_bno055; return ESP_OK;
} }
ILI9341* get_ili9341() { ILI9341* get_ili9341() {
if (!bsp_ready) return NULL;
return &dev_ili9341; return &dev_ili9341;
} }
RP2040* get_rp2040() {
if (!rp2040_ready) return NULL;
return &dev_rp2040;
}
ICE40* get_ice40() { ICE40* get_ice40() {
if (!ice40_ready) return NULL;
return &dev_ice40; return &dev_ice40;
} }
RP2040* get_rp2040() { BNO055* get_bno055() {
return &dev_rp2040; if (!bno055_ready) return NULL;
return &dev_bno055;
} }

View file

@ -55,9 +55,12 @@
#define GPIO_SPI_CS_LCD 32 #define GPIO_SPI_CS_LCD 32
#define GPIO_SPI_DC_LCD 33 #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(); ILI9341* get_ili9341();
ICE40* get_ice40();
RP2040* get_rp2040(); RP2040* get_rp2040();
ICE40* get_ice40();
BNO055* get_bno055();

View file

@ -262,6 +262,23 @@ void menu_wifi_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341
menu_free(menu); 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) { void app_main(void) {
esp_err_t res; esp_err_t res;
@ -269,14 +286,14 @@ void app_main(void) {
uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT); uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT);
if (framebuffer == NULL) { if (framebuffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate framebuffer"); ESP_LOGE(TAG, "Failed to allocate framebuffer");
restart(); esp_restart();
} }
memset(framebuffer, 0, ILI9341_BUFFER_SIZE); memset(framebuffer, 0, ILI9341_BUFFER_SIZE);
pax_buf_t* pax_buffer = malloc(sizeof(pax_buf_t)); pax_buf_t* pax_buffer = malloc(sizeof(pax_buf_t));
if (framebuffer == NULL) { if (framebuffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate pax buffer"); ESP_LOGE(TAG, "Failed to allocate buffer for PAX graphics library");
restart(); esp_restart();
} }
memset(pax_buffer, 0, sizeof(pax_buf_t)); memset(pax_buffer, 0, sizeof(pax_buf_t));
@ -286,60 +303,66 @@ void app_main(void) {
efuse_protect(); efuse_protect();
bool lcdReady = false; if (bsp_init() != ESP_OK) {
res = board_init(&lcdReady); ESP_LOGE(TAG, "Failed to initialize basic board support functions");
esp_restart();
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();
} }
ILI9341* ili9341 = get_ili9341(); 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* 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 */ /* Start AppFS */
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init...");
res = appfs_init(); res = appfs_init();
if (res != ESP_OK) { if (res != ESP_OK) {
ESP_LOGE(TAG, "AppFS init failed: %d", res); ESP_LOGE(TAG, "AppFS init failed: %d", res);
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init failed!"); display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "AppFS failed to initialize", "Flash may be corrupted", NULL);
return; esp_restart();
} }
ESP_LOGI(TAG, "AppFS initialized");
/* Start NVS */ /* Start NVS */
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "NVS init...");
res = nvs_init(); res = nvs_init();
if (res != ESP_OK) { if (res != ESP_OK) {
ESP_LOGE(TAG, "NVS init failed: %d", res); ESP_LOGE(TAG, "NVS init failed: %d", res);
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "NVS init failed!"); display_fatal_error(pax_buffer, ili9341, "Failed to initialize", "NVS failed to initialize", "Flash may be corrupted", NULL);
return; esp_restart();
} }
ESP_LOGI(TAG, "NVS initialized");
/* Start SD card */ /* 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); res = mount_sd(SD_CMD, SD_CLK, SD_D0, SD_PWR, "/sd", false, 5);
bool sdcard_ready = (res == ESP_OK); bool sdcard_ready = (res == ESP_OK);
if (sdcard_ready) {
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "SD card mounted");
}
/* Start LEDs */ /* Start LEDs */
ws2812_init(GPIO_LED_DATA); ws2812_init(GPIO_LED_DATA);
uint8_t ledBuffer[15] = {50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0, 50, 0, 0}; 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)); ws2812_send_data(ledBuffer, sizeof(ledBuffer));
/* Start RP2040 firmware update check */
rp2040_updater(rp2040, pax_buffer, ili9341, framebuffer);
/* Launcher menu */ /* Launcher menu */
while (true) { while (true) {
menu_action_t menu_action; menu_action_t menu_action;

View file

@ -33,13 +33,13 @@ void rp2040_updater(RP2040* rp2040, pax_buf_t* pax_buffer, ILI9341* ili9341, uin
restart(); restart();
} }
pax_noclip(pax_buffer); /*pax_noclip(pax_buffer);
pax_background(pax_buffer, 0xCCCCCC); pax_background(pax_buffer, 0xCCCCCC);
memset(message, 0, sizeof(message)); memset(message, 0, sizeof(message));
snprintf(message, sizeof(message) - 1, "RP2040 firmware: 0x%02X", fw_version); snprintf(message, sizeof(message) - 1, "RP2040 firmware: 0x%02X", fw_version);
pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 0, 20*0, message); pax_draw_text(pax_buffer, 0xFF000000, NULL, 18, 0, 20*0, message);
ili9341_write(ili9341, framebuffer); ili9341_write(ili9341, framebuffer);
vTaskDelay(100 / portTICK_PERIOD_MS); vTaskDelay(100 / portTICK_PERIOD_MS);*/
if (fw_version < 0x01) { // Update required if (fw_version < 0x01) { // Update required
pax_noclip(pax_buffer); pax_noclip(pax_buffer);