366 lines
12 KiB
C
366 lines
12 KiB
C
// Copyright 2015-2025 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "sdkconfig.h"
|
|
#if defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE) || defined(CONFIG_ESP_WIFI_REMOTE_ENABLED)
|
|
|
|
#include "esp32-hal-hosted.h"
|
|
#include "esp32-hal-log.h"
|
|
#include "esp32-hal.h"
|
|
#include "pins_arduino.h"
|
|
|
|
#include "esp_hosted.h"
|
|
#include "esp_hosted_transport_config.h"
|
|
// extern esp_err_t esp_hosted_init();
|
|
// extern esp_err_t esp_hosted_deinit();
|
|
|
|
static bool hosted_initialized = false;
|
|
static bool hosted_ble_active = false;
|
|
static bool hosted_wifi_active = false;
|
|
|
|
static sdio_pin_config_t sdio_pin_config = {
|
|
#ifdef BOARD_HAS_SDIO_ESP_HOSTED
|
|
.pin_clk = BOARD_SDIO_ESP_HOSTED_CLK,
|
|
.pin_cmd = BOARD_SDIO_ESP_HOSTED_CMD,
|
|
.pin_d0 = BOARD_SDIO_ESP_HOSTED_D0,
|
|
.pin_d1 = BOARD_SDIO_ESP_HOSTED_D1,
|
|
.pin_d2 = BOARD_SDIO_ESP_HOSTED_D2,
|
|
.pin_d3 = BOARD_SDIO_ESP_HOSTED_D3,
|
|
.pin_reset = BOARD_SDIO_ESP_HOSTED_RESET
|
|
#else
|
|
.pin_clk = CONFIG_ESP_SDIO_PIN_CLK,
|
|
.pin_cmd = CONFIG_ESP_SDIO_PIN_CMD,
|
|
.pin_d0 = CONFIG_ESP_SDIO_PIN_D0,
|
|
.pin_d1 = CONFIG_ESP_SDIO_PIN_D1,
|
|
.pin_d2 = CONFIG_ESP_SDIO_PIN_D2,
|
|
.pin_d3 = CONFIG_ESP_SDIO_PIN_D3,
|
|
.pin_reset = CONFIG_ESP_SDIO_GPIO_RESET_SLAVE
|
|
#endif
|
|
};
|
|
|
|
static esp_hosted_coprocessor_fwver_t slave_version_struct = {.major1 = 0, .minor1 = 0, .patch1 = 0};
|
|
static esp_hosted_coprocessor_fwver_t host_version_struct = {
|
|
.major1 = ESP_HOSTED_VERSION_MAJOR_1, .minor1 = ESP_HOSTED_VERSION_MINOR_1, .patch1 = ESP_HOSTED_VERSION_PATCH_1
|
|
};
|
|
|
|
static bool hostedInit();
|
|
static bool hostedDeinit();
|
|
|
|
void hostedGetHostVersion(uint32_t *major, uint32_t *minor, uint32_t *patch) {
|
|
*major = host_version_struct.major1;
|
|
*minor = host_version_struct.minor1;
|
|
*patch = host_version_struct.patch1;
|
|
}
|
|
|
|
void hostedGetSlaveVersion(uint32_t *major, uint32_t *minor, uint32_t *patch) {
|
|
*major = slave_version_struct.major1;
|
|
*minor = slave_version_struct.minor1;
|
|
*patch = slave_version_struct.patch1;
|
|
}
|
|
|
|
bool hostedHasUpdate() {
|
|
if (!hosted_initialized) {
|
|
log_e("ESP-Hosted is not initialized");
|
|
return false;
|
|
}
|
|
|
|
uint32_t host_version = ESP_HOSTED_VERSION_VAL(host_version_struct.major1, host_version_struct.minor1, host_version_struct.patch1);
|
|
uint32_t slave_version = 0;
|
|
|
|
esp_err_t ret = esp_hosted_get_coprocessor_fwversion(&slave_version_struct);
|
|
if (ret != ESP_OK) {
|
|
log_e("Could not get slave firmware version: %s", esp_err_to_name(ret));
|
|
} else {
|
|
slave_version = ESP_HOSTED_VERSION_VAL(slave_version_struct.major1, slave_version_struct.minor1, slave_version_struct.patch1);
|
|
}
|
|
|
|
log_i("Host firmware version: %" PRIu32 ".%" PRIu32 ".%" PRIu32, host_version_struct.major1, host_version_struct.minor1, host_version_struct.patch1);
|
|
log_i("Slave firmware version: %" PRIu32 ".%" PRIu32 ".%" PRIu32, slave_version_struct.major1, slave_version_struct.minor1, slave_version_struct.patch1);
|
|
|
|
// compare major.minor only
|
|
// slave_version &= 0xFFFFFF00;
|
|
// host_version &= 0xFFFFFF00;
|
|
|
|
if (host_version == slave_version) {
|
|
log_i("Versions Match!");
|
|
} else if (host_version > slave_version) {
|
|
log_w("Version on Host is NEWER than version on co-processor");
|
|
log_w("Update URL: %s", hostedGetUpdateURL());
|
|
return true;
|
|
} else {
|
|
log_w("Version on Host is OLDER than version on co-processor");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
char *hostedGetUpdateURL() {
|
|
// https://espressif.github.io/arduino-esp32/hosted/esp32c6-v1.2.3.bin
|
|
static char url[92] = {0};
|
|
snprintf(
|
|
url, 92, "https://espressif.github.io/arduino-esp32/hosted/%s-v%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".bin", CONFIG_ESP_HOSTED_IDF_SLAVE_TARGET,
|
|
host_version_struct.major1, host_version_struct.minor1, host_version_struct.patch1
|
|
);
|
|
return url;
|
|
}
|
|
|
|
bool hostedBeginUpdate() {
|
|
if (!hosted_initialized) {
|
|
log_e("ESP-Hosted is not initialized");
|
|
return false;
|
|
}
|
|
|
|
esp_err_t err = esp_hosted_slave_ota_begin();
|
|
if (err != ESP_OK) {
|
|
log_e("Failed to begin Update: %s", esp_err_to_name(err));
|
|
}
|
|
return err == ESP_OK;
|
|
}
|
|
|
|
bool hostedWriteUpdate(uint8_t *buf, uint32_t len) {
|
|
if (!hosted_initialized) {
|
|
log_e("ESP-Hosted is not initialized");
|
|
return false;
|
|
}
|
|
|
|
esp_err_t err = esp_hosted_slave_ota_write(buf, len);
|
|
if (err != ESP_OK) {
|
|
log_e("Failed to write Update: %s", esp_err_to_name(err));
|
|
}
|
|
return err == ESP_OK;
|
|
}
|
|
|
|
bool hostedEndUpdate() {
|
|
if (!hosted_initialized) {
|
|
log_e("ESP-Hosted is not initialized");
|
|
return false;
|
|
}
|
|
|
|
esp_err_t err = esp_hosted_slave_ota_end();
|
|
if (err != ESP_OK) {
|
|
log_e("Failed to end Update: %s", esp_err_to_name(err));
|
|
}
|
|
return err == ESP_OK;
|
|
}
|
|
|
|
bool hostedActivateUpdate() {
|
|
if (!hosted_initialized) {
|
|
log_e("ESP-Hosted is not initialized");
|
|
return false;
|
|
}
|
|
|
|
// Activate can fail on older firmwares and that is not critical
|
|
uint32_t slave_version = ESP_HOSTED_VERSION_VAL(slave_version_struct.major1, slave_version_struct.minor1, slave_version_struct.patch1);
|
|
uint32_t min_version = ESP_HOSTED_VERSION_VAL(2, 6, 0);
|
|
|
|
if (slave_version < min_version) {
|
|
// Silence messages caused by earlier versions
|
|
esp_log_level_set("rpc_core", ESP_LOG_NONE);
|
|
}
|
|
|
|
esp_err_t err = esp_hosted_slave_ota_activate();
|
|
|
|
// Any further communication will result in logged errors
|
|
esp_log_level_set("sdmmc_io", ESP_LOG_NONE);
|
|
esp_log_level_set("H_SDIO_DRV", ESP_LOG_NONE);
|
|
|
|
if (err != ESP_OK && slave_version >= min_version) {
|
|
log_e("Failed to activate Update: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool hostedInit() {
|
|
if (!hosted_initialized) {
|
|
log_i("Initializing ESP-Hosted");
|
|
log_d(
|
|
"SDIO pins: clk=%d, cmd=%d, d0=%d, d1=%d, d2=%d, d3=%d, rst=%d", sdio_pin_config.pin_clk, sdio_pin_config.pin_cmd, sdio_pin_config.pin_d0,
|
|
sdio_pin_config.pin_d1, sdio_pin_config.pin_d2, sdio_pin_config.pin_d3, sdio_pin_config.pin_reset
|
|
);
|
|
hosted_initialized = true;
|
|
struct esp_hosted_sdio_config conf = INIT_DEFAULT_HOST_SDIO_CONFIG();
|
|
conf.pin_clk.pin = sdio_pin_config.pin_clk;
|
|
conf.pin_cmd.pin = sdio_pin_config.pin_cmd;
|
|
conf.pin_d0.pin = sdio_pin_config.pin_d0;
|
|
conf.pin_d1.pin = sdio_pin_config.pin_d1;
|
|
conf.pin_d2.pin = sdio_pin_config.pin_d2;
|
|
conf.pin_d3.pin = sdio_pin_config.pin_d3;
|
|
conf.pin_reset.pin = sdio_pin_config.pin_reset;
|
|
esp_err_t err = esp_hosted_sdio_set_config(&conf);
|
|
if (err != ESP_OK) { //&& err != ESP_ERR_NOT_ALLOWED) { // uncomment when second init is fixed
|
|
log_e("esp_hosted_sdio_set_config failed: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
err = esp_hosted_init();
|
|
if (err != ESP_OK) {
|
|
log_e("esp_hosted_init failed: %s", esp_err_to_name(err));
|
|
hosted_initialized = false;
|
|
return false;
|
|
}
|
|
log_i("ESP-Hosted initialized!");
|
|
err = esp_hosted_connect_to_slave();
|
|
if (err != ESP_OK) {
|
|
log_e("esp_hosted_connect_to_slave failed: %s", esp_err_to_name(err));
|
|
hosted_initialized = false;
|
|
return false;
|
|
}
|
|
hostedHasUpdate();
|
|
return true;
|
|
}
|
|
|
|
// Attach pins to PeriMan here
|
|
// Slave chip model is CONFIG_IDF_SLAVE_TARGET
|
|
// sdio_pin_config.pin_clk
|
|
// sdio_pin_config.pin_cmd
|
|
// sdio_pin_config.pin_d0
|
|
// sdio_pin_config.pin_d1
|
|
// sdio_pin_config.pin_d2
|
|
// sdio_pin_config.pin_d3
|
|
// sdio_pin_config.pin_reset
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool hostedDeinit() {
|
|
if (!hosted_initialized) {
|
|
log_e("ESP-Hosted is not initialized");
|
|
return false;
|
|
}
|
|
|
|
if (esp_hosted_deinit() != ESP_OK) {
|
|
log_e("esp_hosted_deinit failed!");
|
|
return false;
|
|
}
|
|
|
|
hosted_initialized = false;
|
|
return true;
|
|
}
|
|
|
|
bool hostedInitBLE() {
|
|
log_i("Initializing ESP-Hosted for BLE");
|
|
if (!hostedInit()) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t slave_version = ESP_HOSTED_VERSION_VAL(slave_version_struct.major1, slave_version_struct.minor1, slave_version_struct.patch1);
|
|
uint32_t min_version = ESP_HOSTED_VERSION_VAL(2, 6, 0);
|
|
if (slave_version >= min_version) {
|
|
esp_err_t err = esp_hosted_bt_controller_init();
|
|
if (err != ESP_OK) {
|
|
log_e("esp_hosted_bt_controller_init failed: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
err = esp_hosted_bt_controller_enable();
|
|
if (err != ESP_OK) {
|
|
log_e("esp_hosted_bt_controller_enable failed: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
}
|
|
hosted_ble_active = true;
|
|
return true;
|
|
}
|
|
|
|
bool hostedInitWiFi() {
|
|
log_i("Initializing ESP-Hosted for WiFi");
|
|
hosted_wifi_active = true;
|
|
return hostedInit();
|
|
}
|
|
|
|
bool hostedDeinitBLE() {
|
|
log_i("Deinitializing ESP-Hosted for BLE");
|
|
uint32_t slave_version = ESP_HOSTED_VERSION_VAL(slave_version_struct.major1, slave_version_struct.minor1, slave_version_struct.patch1);
|
|
uint32_t min_version = ESP_HOSTED_VERSION_VAL(2, 6, 0);
|
|
if (slave_version >= min_version) {
|
|
esp_err_t err = esp_hosted_bt_controller_disable();
|
|
if (err != ESP_OK) {
|
|
log_e("esp_hosted_bt_controller_disable failed: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
err = esp_hosted_bt_controller_deinit(false);
|
|
if (err != ESP_OK) {
|
|
log_e("esp_hosted_bt_controller_deinit failed: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
}
|
|
hosted_ble_active = false;
|
|
if (!hosted_wifi_active) {
|
|
return hostedDeinit();
|
|
} else {
|
|
log_i("ESP-Hosted is still being used by Wi-Fi. Skipping deinit.");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool hostedDeinitWiFi() {
|
|
log_i("Deinitializing ESP-Hosted for WiFi");
|
|
hosted_wifi_active = false;
|
|
if (!hosted_ble_active) {
|
|
return hostedDeinit();
|
|
} else {
|
|
log_i("ESP-Hosted is still being used by BLE. Skipping deinit.");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool hostedSetPins(int8_t clk, int8_t cmd, int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t rst) {
|
|
if (clk < 0 || cmd < 0 || d0 < 0 || d1 < 0 || d2 < 0 || d3 < 0 || rst < 0) {
|
|
log_e("All SDIO pins must be defined");
|
|
return false;
|
|
}
|
|
|
|
if (hosted_initialized) {
|
|
int8_t current_clk, current_cmd, current_d0, current_d1, current_d2, current_d3, current_rst;
|
|
hostedGetPins(¤t_clk, ¤t_cmd, ¤t_d0, ¤t_d1, ¤t_d2, ¤t_d3, ¤t_rst);
|
|
log_e("SDIO pins must be set before ESP-Hosted is initialized");
|
|
log_e(
|
|
"Current pins used: clk=%d, cmd=%d, d0=%d, d1=%d, d2=%d, d3=%d, rst=%d", current_clk, current_cmd, current_d0, current_d1, current_d2, current_d3,
|
|
current_rst
|
|
);
|
|
return false;
|
|
}
|
|
|
|
sdio_pin_config.pin_clk = clk;
|
|
sdio_pin_config.pin_cmd = cmd;
|
|
sdio_pin_config.pin_d0 = d0;
|
|
sdio_pin_config.pin_d1 = d1;
|
|
sdio_pin_config.pin_d2 = d2;
|
|
sdio_pin_config.pin_d3 = d3;
|
|
sdio_pin_config.pin_reset = rst;
|
|
return true;
|
|
}
|
|
|
|
void hostedGetPins(int8_t *clk, int8_t *cmd, int8_t *d0, int8_t *d1, int8_t *d2, int8_t *d3, int8_t *rst) {
|
|
*clk = sdio_pin_config.pin_clk;
|
|
*cmd = sdio_pin_config.pin_cmd;
|
|
*d0 = sdio_pin_config.pin_d0;
|
|
*d1 = sdio_pin_config.pin_d1;
|
|
*d2 = sdio_pin_config.pin_d2;
|
|
*d3 = sdio_pin_config.pin_d3;
|
|
*rst = sdio_pin_config.pin_reset;
|
|
}
|
|
|
|
bool hostedIsBLEActive() {
|
|
return hosted_ble_active;
|
|
}
|
|
|
|
bool hostedIsWiFiActive() {
|
|
return hosted_wifi_active;
|
|
}
|
|
|
|
bool hostedIsInitialized() {
|
|
return hosted_initialized;
|
|
}
|
|
|
|
#endif /* defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE) || defined(CONFIG_ESP_WIFI_REMOTE_ENABLED) */
|