#include "platform.h" #include #include "driver/gpio.h" #include "esp_heap_caps.h" #include "esp_log.h" #include "mbedtls/platform.h" #include "nvs_flash.h" #include "sdkconfig.h" static bool s_initialized; static bool s_board_gpio_initialized; static const char *TAG = "platform_bootstrap"; #ifndef CONFIG_TQ_KEY_PRINT_BOOST_ENABLE_ON_BOOT #define CONFIG_TQ_KEY_PRINT_BOOST_ENABLE_ON_BOOT 1 #endif #ifndef CONFIG_TQ_KEY_PRINT_BOOST_ACTIVE_HIGH #define CONFIG_TQ_KEY_PRINT_BOOST_ACTIVE_HIGH 1 #endif #ifndef CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH #define CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH 1 #endif #if CONFIG_TQ_KEY_PRINT_BOOST_ENABLE_ON_BOOT #if CONFIG_TQ_KEY_PRINT_BOOST_ACTIVE_HIGH #define KEY_PRINT_BOOST_LEVEL 1 #else #define KEY_PRINT_BOOST_LEVEL 0 #endif #endif #if CONFIG_TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH #define BOOT_SCREEN_BACKLIGHT_ON_LEVEL 1 #else #define BOOT_SCREEN_BACKLIGHT_ON_LEVEL 0 #endif static void *tls_calloc_prefer_psram(size_t n, size_t size) { void *ptr = heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (ptr == NULL) { ptr = heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } return ptr; } static void tls_free(void *ptr) { heap_caps_free(ptr); } static esp_err_t board_gpio_config_output(int gpio_num, int level, const char *name) { if (gpio_num < 0) { return ESP_OK; } gpio_config_t cfg = { .pin_bit_mask = 1ULL << gpio_num, .mode = GPIO_MODE_OUTPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE, }; esp_err_t err = gpio_config(&cfg); if (err != ESP_OK) { ESP_LOGE(TAG, "gpio_config output failed: %s pin=%d err=%s", name, gpio_num, esp_err_to_name(err)); return err; } err = gpio_set_level(gpio_num, level); if (err != ESP_OK) { ESP_LOGE(TAG, "gpio_set_level failed: %s pin=%d level=%d err=%s", name, gpio_num, level, esp_err_to_name(err)); return err; } return ESP_OK; } static esp_err_t board_gpio_config_input(int gpio_num, bool pull_up, const char *name) { if (gpio_num < 0) { return ESP_OK; } gpio_config_t cfg = { .pin_bit_mask = 1ULL << gpio_num, .mode = GPIO_MODE_INPUT, .pull_up_en = pull_up ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE, }; esp_err_t err = gpio_config(&cfg); if (err != ESP_OK) { ESP_LOGE(TAG, "gpio_config input failed: %s pin=%d err=%s", name, gpio_num, esp_err_to_name(err)); return err; } return ESP_OK; } static esp_err_t platform_board_gpio_init(void) { if (s_board_gpio_initialized) { return ESP_OK; } // Must be asserted early to keep the board powered. esp_err_t err = board_gpio_config_output(CONFIG_TQ_POWER_HOLD_PIN, 1, "power_hold"); if (err != ESP_OK) { return err; } // Default UI GPIO states. err = board_gpio_config_output(CONFIG_TQ_LED_R_PIN, 0, "led_r"); if (err != ESP_OK) { return err; } err = board_gpio_config_output(CONFIG_TQ_LED_G_PIN, 0, "led_g"); if (err != ESP_OK) { return err; } err = board_gpio_config_output(CONFIG_TQ_SCREEN_CS_PIN, 1, "screen_cs"); if (err != ESP_OK) { return err; } err = board_gpio_config_output(CONFIG_TQ_SCREEN_DC_PIN, 0, "screen_dc"); if (err != ESP_OK) { return err; } err = board_gpio_config_output(CONFIG_TQ_SCREEN_BACKLIGHT_PIN, BOOT_SCREEN_BACKLIGHT_ON_LEVEL, "screen_backlight"); if (err != ESP_OK) { return err; } // Key/power/sensor GPIO input defaults. err = board_gpio_config_input(CONFIG_TQ_POWER_KEY_PIN, true, "power_key"); if (err != ESP_OK) { return err; } #if CONFIG_TQ_KEY_PRINT_BOOST_ENABLE_ON_BOOT err = board_gpio_config_output(CONFIG_TQ_KEY_PRINT_PIN, KEY_PRINT_BOOST_LEVEL, "key_print_boost"); if (err != ESP_OK) { return err; } #else err = board_gpio_config_input(CONFIG_TQ_KEY_PRINT_PIN, true, "key_print"); if (err != ESP_OK) { return err; } #endif err = board_gpio_config_input(CONFIG_TQ_MIC_KEY_PIN, true, "mic_key"); if (err != ESP_OK) { return err; } err = board_gpio_config_input(CONFIG_TQ_PRINT_PAPER_PIN, true, "print_paper"); if (err != ESP_OK) { return err; } err = board_gpio_config_input(CONFIG_TQ_BATTERY_ADC_PIN, false, "battery_adc"); if (err != ESP_OK) { return err; } err = board_gpio_config_input(CONFIG_TQ_NTC_ADC_PIN, false, "ntc_adc"); if (err != ESP_OK) { return err; } ESP_LOGI(TAG, "board gpio mapped: hold=%d pwr_key=%d key_print=%d boost_mode=%d led_r=%d led_g=%d spi(mosi=%d,miso=%d,clk=%d) screen(dc=%d,cs=%d,bk=%d) i2c(sda=%d,scl=%d) i2s(mclk=%d,bclk=%d,ws=%d,di=%d,do=%d) pa=%d", CONFIG_TQ_POWER_HOLD_PIN, CONFIG_TQ_POWER_KEY_PIN, CONFIG_TQ_KEY_PRINT_PIN, #if CONFIG_TQ_KEY_PRINT_BOOST_ENABLE_ON_BOOT 1, #else 0, #endif CONFIG_TQ_LED_R_PIN, CONFIG_TQ_LED_G_PIN, CONFIG_TQ_SPI_SHARED_MOSI_PIN, CONFIG_TQ_PRINTER_MISO_PIN, CONFIG_TQ_SPI_SHARED_CLK_PIN, CONFIG_TQ_SCREEN_DC_PIN, CONFIG_TQ_SCREEN_CS_PIN, CONFIG_TQ_SCREEN_BACKLIGHT_PIN, CONFIG_TQ_VOICE_I2C_SDA_PIN, CONFIG_TQ_VOICE_I2C_SCL_PIN, CONFIG_TQ_VOICE_I2S_MCLK_PIN, CONFIG_TQ_VOICE_I2S_BCLK_PIN, CONFIG_TQ_VOICE_I2S_WS_PIN, CONFIG_TQ_VOICE_I2S_DIN_PIN, CONFIG_TQ_VOICE_I2S_DOUT_PIN, CONFIG_TQ_VOICE_CODEC_PA_PIN); s_board_gpio_initialized = true; return ESP_OK; } esp_err_t platform_bootstrap_init(void) { if (s_initialized) { return ESP_OK; } ESP_ERROR_CHECK(platform_board_gpio_init()); esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); #if CONFIG_SPIRAM_USE_MALLOC // Keep very small allocations on internal RAM, push larger generic mallocs to PSRAM. heap_caps_malloc_extmem_enable(4096); ESP_LOGI(TAG, "extmem malloc threshold set to 4096 bytes"); #endif #if defined(MBEDTLS_PLATFORM_MEMORY) int tls_rc = mbedtls_platform_set_calloc_free(tls_calloc_prefer_psram, tls_free); if (tls_rc == 0) { ESP_LOGI(TAG, "mbedtls calloc/free redirected to PSRAM-preferred allocator"); } else { ESP_LOGW(TAG, "mbedtls calloc/free redirect failed: rc=%d", tls_rc); } #endif #if CONFIG_TQ_SCREEN_ENABLE err = platform_display_init(); if (err != ESP_OK) { ESP_LOGW(TAG, "st7789 init failed: %s", esp_err_to_name(err)); } #if CONFIG_TQ_SCREEN_TEST_PATTERN_ON_BOOT else { err = platform_display_show_test_pattern(); if (err != ESP_OK) { ESP_LOGW(TAG, "st7789 test pattern failed: %s", esp_err_to_name(err)); } } #endif #endif s_initialized = true; return ESP_OK; }