diff --git a/firmware_p4/components/Applications/LoRa/meshtastic/meshtastic_app.c b/firmware_p4/components/Applications/LoRa/meshtastic/meshtastic_app.c index 32dbc5c7..c2b2bc19 100644 --- a/firmware_p4/components/Applications/LoRa/meshtastic/meshtastic_app.c +++ b/firmware_p4/components/Applications/LoRa/meshtastic/meshtastic_app.c @@ -66,6 +66,8 @@ esp_err_t meshtastic_app_start(void) { mt_region_t region = mt_region_current(); uint32_t freq_hz = mt_region_freq_for_channel(region, MT_PRIMARY_CHANNEL, p_info->bw_hz); + sx1262_deinit(); + sx1262_config_t cfg = {0}; ret = sx1262_hal_create(&cfg.hal); if (ret != ESP_OK) { diff --git a/firmware_p4/components/Drivers/sx1262/include/sx1262.h b/firmware_p4/components/Drivers/sx1262/include/sx1262.h index ff535832..d8324659 100644 --- a/firmware_p4/components/Drivers/sx1262/include/sx1262.h +++ b/firmware_p4/components/Drivers/sx1262/include/sx1262.h @@ -35,6 +35,19 @@ extern "C" { */ esp_err_t sx1262_init(const sx1262_config_t *config); +/** + * @brief Tear down the SX1262 driver so the next sx1262_init() starts clean. + * + * Stops the IRQ task (if running), destroys the HAL (removes the SPI device + * and mutex; SPI3 bus is preserved for shared peripherals), and clears + * driver state. + * + * Safe to call when nothing is initialized — no-op. + * + * @return ESP_OK on success. + */ +esp_err_t sx1262_deinit(void); + /** * @brief Start the IRQ processing task. * diff --git a/firmware_p4/components/Drivers/sx1262/include/sx1262_hal.h b/firmware_p4/components/Drivers/sx1262/include/sx1262_hal.h index d76d8c5c..2887d325 100644 --- a/firmware_p4/components/Drivers/sx1262/include/sx1262_hal.h +++ b/firmware_p4/components/Drivers/sx1262/include/sx1262_hal.h @@ -132,6 +132,19 @@ typedef struct sx1262_hal { */ esp_err_t sx1262_hal_create(sx1262_hal_t *out_hal); +/** + * @brief Tear down the HAL so the next sx1262_hal_create() rebuilds it. + * + * Removes the SX1262 SPI device, deletes the SPI mutex, and clears the + * internal initialized flag. The SPI3 bus itself is left initialized + * because it is shared with the ST7789 display. + * + * Safe to call when the HAL is not initialized — returns ESP_OK as a no-op. + * + * @return ESP_OK. + */ +esp_err_t sx1262_hal_destroy(void); + #ifdef __cplusplus } #endif diff --git a/firmware_p4/components/Drivers/sx1262/sx1262.c b/firmware_p4/components/Drivers/sx1262/sx1262.c index 32789b6a..9e8db25b 100644 --- a/firmware_p4/components/Drivers/sx1262/sx1262.c +++ b/firmware_p4/components/Drivers/sx1262/sx1262.c @@ -402,6 +402,13 @@ void sx1262_stop(void) { ESP_LOGI(TAG, "Stopped"); } +esp_err_t sx1262_deinit(void) { + sx1262_stop(); + esp_err_t ret = sx1262_hal_destroy(); + s_is_initialized = false; + return ret; +} + esp_err_t sx1262_set_callbacks(const sx1262_callbacks_t *cbs) { if (cbs == NULL) { return ESP_ERR_INVALID_ARG; diff --git a/firmware_p4/components/Drivers/sx1262/sx1262_hal.c b/firmware_p4/components/Drivers/sx1262/sx1262_hal.c index afd73ef9..d541a43e 100644 --- a/firmware_p4/components/Drivers/sx1262/sx1262_hal.c +++ b/firmware_p4/components/Drivers/sx1262/sx1262_hal.c @@ -202,6 +202,10 @@ esp_err_t sx1262_hal_create(sx1262_hal_t *out_hal) { }; ret = spi_bus_initialize(SPI_HOST_ID, &bus_cfg, SPI_DMA_CH_AUTO); + if (ret == ESP_ERR_INVALID_STATE) { + /* Bus already initialized by another driver (e.g. ST7789 via kernel spi_init). */ + ret = ESP_OK; + } if (ret != ESP_OK) { ESP_LOGE(TAG, "SPI bus init failed: %s", esp_err_to_name(ret)); return ret; @@ -217,7 +221,6 @@ esp_err_t sx1262_hal_create(sx1262_hal_t *out_hal) { ret = spi_bus_add_device(SPI_HOST_ID, &dev_cfg, &s_ctx.spi); if (ret != ESP_OK) { ESP_LOGE(TAG, "SPI add device failed: %s", esp_err_to_name(ret)); - spi_bus_free(SPI_HOST_ID); return ret; } @@ -226,7 +229,7 @@ esp_err_t sx1262_hal_create(sx1262_hal_t *out_hal) { if (s_ctx.spi_mutex == NULL) { ESP_LOGE(TAG, "Failed to create SPI mutex"); spi_bus_remove_device(s_ctx.spi); - spi_bus_free(SPI_HOST_ID); + s_ctx.spi = NULL; return ESP_ERR_NO_MEM; } @@ -254,3 +257,24 @@ esp_err_t sx1262_hal_create(sx1262_hal_t *out_hal) { return ESP_OK; } + +esp_err_t sx1262_hal_destroy(void) { + if (!s_ctx.is_initialized) { + return ESP_OK; + } + + if (s_ctx.spi != NULL) { + spi_bus_remove_device(s_ctx.spi); + s_ctx.spi = NULL; + } + if (s_ctx.spi_mutex != NULL) { + vSemaphoreDelete(s_ctx.spi_mutex); + s_ctx.spi_mutex = NULL; + } + + /* SPI3 bus is shared with ST7789 display; do not free it here. */ + + s_ctx.is_initialized = false; + ESP_LOGI(TAG, "HAL destroyed (SPI3 bus left intact for shared peripherals)"); + return ESP_OK; +}