migrate OTA to be connection manager based
This commit is contained in:
parent
d840e52609
commit
093ce60a9f
4 changed files with 319 additions and 251 deletions
|
|
@ -1,5 +1,14 @@
|
||||||
set(REQUIRES bt)
|
set(REQUIRES
|
||||||
set(SRCS src/baros_ble.c)
|
app_update
|
||||||
|
bootloader_support
|
||||||
|
bt
|
||||||
|
esp_ringbuf
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SRCS
|
||||||
|
src/baros_ble.c
|
||||||
|
src/baros_ble_ota.c
|
||||||
|
)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SRCS}
|
SRCS ${SRCS}
|
||||||
|
|
|
||||||
7
include/baros_ble_ota.h
Normal file
7
include/baros_ble_ota.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef __BAROS_BLE_OTA_H__
|
||||||
|
#define __BAROS_BLE_OTA_H__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t baros_ble_ota_init();
|
||||||
263
src/baros_ble.c
263
src/baros_ble.c
|
|
@ -1,266 +1,31 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "esp_system.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_nimble_hci.h"
|
|
||||||
#include "nimble/nimble_port.h"
|
#include "esp_bt.h"
|
||||||
#include "nimble/nimble_port_freertos.h"
|
#include "esp_log.h"
|
||||||
#include "host/ble_hs.h"
|
|
||||||
#include "host/util/util.h"
|
|
||||||
#include "services/gap/ble_svc_gap.h"
|
|
||||||
#include "services/bas/ble_svc_bas.h"
|
|
||||||
#include "esp_event_base.h"
|
#include "esp_event_base.h"
|
||||||
#include "esp_event.h"
|
|
||||||
|
|
||||||
#include "baros.h"
|
#include "baros.h"
|
||||||
|
#include "baros_ble_ota.h"
|
||||||
|
|
||||||
#define TAG "BOS_BLE"
|
#define TAG "BOS_BLE"
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(EVENT_BAROS_BLE);
|
ESP_EVENT_DEFINE_BASE(EVENT_BAROS_BLE);
|
||||||
|
|
||||||
static uint8_t blehr_addr_type;
|
|
||||||
static uint16_t conn_handle;
|
|
||||||
static const char *device_name;
|
|
||||||
|
|
||||||
static const struct ble_gatt_svc_def service_defs[] = {
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ble_advertise(void);
|
|
||||||
|
|
||||||
static int ble_gap_event(struct ble_gap_event *event, void *arg) {
|
|
||||||
switch (event->type) {
|
|
||||||
case BLE_GAP_EVENT_DISC: {
|
|
||||||
struct ble_hs_adv_fields fields;
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data));
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "DISCOVERY: %d", event->disc.length_data);
|
|
||||||
|
|
||||||
uint8_t addr[6];
|
|
||||||
memcpy(&addr, (uint8_t*)&event->disc.addr + 1, 6);
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "addr: %02X:%02X:%02X:%02X:%02X:%02X", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_event_post(EVENT_BAROS_BLE, BAROS_BLE_DISC, (void*)&event->disc, sizeof(struct ble_gap_disc_desc), 1000));
|
|
||||||
|
|
||||||
/*
|
|
||||||
uint8_t *buf = (uint8_t*)malloc(event->disc.length_data);
|
|
||||||
memcpy(buf, event->disc.data, event->disc.length_data);
|
|
||||||
|
|
||||||
printf("\ndata: ");
|
|
||||||
for(uint8_t i = 0; i < event->disc.length_data; i++) {
|
|
||||||
printf("0x%02X ", buf[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(fields.name != NULL) {
|
|
||||||
char *name = (char*)malloc(fields.name_len);
|
|
||||||
memcpy(name, (uint8_t*)fields.name, fields.name_len);
|
|
||||||
name[fields.name_len] = '\0';
|
|
||||||
ESP_LOGV(TAG, "Name: %s", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "uuids: %d", fields.num_uuids16);
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < fields.num_uuids16; i++) {
|
|
||||||
ESP_LOGV(TAG, "uuid: 0x%04X", fields.uuids16[i].value);
|
|
||||||
|
|
||||||
if (ble_uuid_u16(&fields.uuids16[i].u) == BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME) {
|
|
||||||
ESP_LOGV(TAG, "device has name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case BLE_GAP_EVENT_CONNECT:
|
|
||||||
/* A new connection was established or a connection attempt failed */
|
|
||||||
conn_handle = event->connect.conn_handle;
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "connection %s; conn_handle: %d status=%d\n",
|
|
||||||
event->connect.status == 0 ? "established" : "failed",
|
|
||||||
conn_handle,
|
|
||||||
event->connect.status
|
|
||||||
);
|
|
||||||
|
|
||||||
// always keep advertising
|
|
||||||
ble_advertise();
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_DISCONNECT:
|
|
||||||
ESP_LOGI(TAG, "disconnect; reason=%d\n", event->disconnect.reason);
|
|
||||||
|
|
||||||
/* Connection terminated; resume advertising */
|
|
||||||
ble_advertise();
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
|
||||||
ESP_LOGI(TAG, "adv complete\n");
|
|
||||||
|
|
||||||
ble_advertise();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_SUBSCRIBE:
|
|
||||||
ESP_LOGI(TAG, "subscribe event; cur_notify=%d\n value handle; "
|
|
||||||
"val_handle=%d\n",
|
|
||||||
event->subscribe.cur_notify, event->subscribe.attr_handle);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_CONN_UPDATE:
|
|
||||||
ESP_LOGI(TAG, "BLE_GAP_EVENT_CONN_UPDATE, conn_handle: %d status: %d",
|
|
||||||
event->mtu.conn_handle,
|
|
||||||
event->enc_change.status
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_ENC_CHANGE:
|
|
||||||
ESP_LOGI(TAG, "BLE_GAP_EVENT_ENC_CHANGE");
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_MTU:
|
|
||||||
ESP_LOGI(TAG, "mtu update event; conn_handle=%d mtu=%d\n",
|
|
||||||
event->mtu.conn_handle,
|
|
||||||
event->mtu.value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_NOTIFY_RX:
|
|
||||||
ESP_LOGI(TAG, "BLE_GAP_EVENT_NOTIFY_RX; conn_handle=%d mtu=%d attr_handle=%d\n",
|
|
||||||
event->mtu.conn_handle,
|
|
||||||
event->mtu.value,
|
|
||||||
event->notify_rx.attr_handle);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_NOTIFY_TX:
|
|
||||||
ESP_LOGI(TAG, "BLE_GAP_EVENT_NOTIFY_TX; conn_handle=%d mtu=%d\n",
|
|
||||||
event->mtu.conn_handle,
|
|
||||||
event->mtu.value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ESP_LOGW(TAG, "unhandled ble_gap_event; conn_handle=%d type=%d\n",
|
|
||||||
event->mtu.conn_handle,
|
|
||||||
event->type
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ble_advertise(void) {
|
|
||||||
// check if already adverting
|
|
||||||
if(ble_gap_adv_active()) return;
|
|
||||||
|
|
||||||
struct ble_gap_adv_params adv_params;
|
|
||||||
struct ble_hs_adv_fields fields;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
memset(&fields, 0, sizeof(fields));
|
|
||||||
|
|
||||||
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
|
|
||||||
|
|
||||||
fields.tx_pwr_lvl_is_present = 1;
|
|
||||||
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
|
||||||
|
|
||||||
fields.name = (uint8_t *)device_name;
|
|
||||||
fields.name_len = strlen(device_name);
|
|
||||||
fields.name_is_complete = 1;
|
|
||||||
|
|
||||||
rc = ble_gap_adv_set_fields(&fields);
|
|
||||||
if (rc != 0) {
|
|
||||||
ESP_LOGE(TAG, "error setting advertisement data; rc=%d\n", rc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Begin advertising */
|
|
||||||
memset(&adv_params, 0, sizeof(adv_params));
|
|
||||||
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
|
||||||
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
|
||||||
rc = ble_gap_adv_start(blehr_addr_type, NULL, BLE_HS_FOREVER,
|
|
||||||
&adv_params, ble_gap_event, NULL);
|
|
||||||
if (rc != 0) {
|
|
||||||
ESP_LOGE(TAG, "error enabling advertisement; rc=%d\n", rc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int baros_ble_scan_start() {
|
|
||||||
uint8_t addr_type;
|
|
||||||
struct ble_gap_disc_params disc_params = {
|
|
||||||
.filter_duplicates = 1,
|
|
||||||
.passive = 1,
|
|
||||||
.itvl = 0,
|
|
||||||
.window = 0,
|
|
||||||
.filter_policy = 0,
|
|
||||||
.limited = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(ble_hs_id_infer_auto(0, &addr_type));
|
|
||||||
ble_gap_disc_cancel();
|
|
||||||
ESP_ERROR_CHECK(ble_gap_disc(addr_type, 3000, &disc_params, ble_gap_event, &addr_type));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int baros_ble_scan_stop() {
|
|
||||||
return ble_gap_disc_cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void nimble_host_task(void *param) {
|
|
||||||
nimble_port_run();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_sync() {
|
|
||||||
ESP_LOGI(TAG, "on_sync");
|
|
||||||
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = ble_hs_id_infer_auto(0, &blehr_addr_type);
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
|
|
||||||
uint8_t addr_val[6] = {0};
|
|
||||||
err = ble_hs_id_copy_addr(blehr_addr_type, addr_val, NULL);
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
|
|
||||||
ble_advertise();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_reset(int reason) {
|
|
||||||
ESP_LOGE(TAG, "on_reset, reason: %d", reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t baros_ble_init(baros_ble_cfg_t *cfg) {
|
uint8_t baros_ble_init(baros_ble_cfg_t *cfg) {
|
||||||
esp_err_t err;
|
ESP_LOGV(TAG, "init");
|
||||||
|
|
||||||
device_name = cfg->name;
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||||
|
|
||||||
//ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
|
esp_err_t ret = esp_bt_controller_init(&bt_cfg);
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
nimble_port_init();
|
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
ble_hs_cfg.sync_cb = on_sync;
|
baros_ble_ota_init();
|
||||||
ble_hs_cfg.reset_cb = on_reset;
|
|
||||||
|
|
||||||
// initialize services
|
|
||||||
err = ble_gatts_count_cfg(service_defs);
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
|
|
||||||
err = ble_gatts_add_svcs(service_defs);
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Setting device name: %s", device_name);
|
|
||||||
|
|
||||||
err = ble_svc_gap_device_name_set(device_name);
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
|
||||||
|
|
||||||
nimble_port_freertos_init(nimble_host_task);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
287
src/baros_ble_ota.c
Normal file
287
src/baros_ble_ota.c
Normal file
|
|
@ -0,0 +1,287 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/ringbuf.h"
|
||||||
|
|
||||||
|
#include "esp_app_format.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "ble_ota.h"
|
||||||
|
#include "esp_delta_ota.h"
|
||||||
|
#include "esp_partition.h"
|
||||||
|
#include "esp_app_format.h"
|
||||||
|
|
||||||
|
#include "baros.h"
|
||||||
|
#include "baros_ble_ota.h"
|
||||||
|
|
||||||
|
#define TAG "BOS_BLE_OTA"
|
||||||
|
|
||||||
|
#define DIGEST_SIZE 32
|
||||||
|
#define IMG_HEADER_LEN sizeof(esp_image_header_t)
|
||||||
|
#define OTA_RINGBUF_SIZE 8192
|
||||||
|
#define OTA_TASK_SIZE 8192
|
||||||
|
#define PATCH_HEADER_SIZE 64
|
||||||
|
|
||||||
|
const esp_partition_t *current_partition;
|
||||||
|
static RingbufHandle_t s_ringbuf = NULL;
|
||||||
|
static esp_ota_handle_t out_handle;
|
||||||
|
SemaphoreHandle_t notify_sem;
|
||||||
|
|
||||||
|
static bool verify_patch_header(void *img_hdr_data)
|
||||||
|
{
|
||||||
|
if (!img_hdr_data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_delta_ota_magic = 0xfccdde10;
|
||||||
|
uint32_t recv_magic = *(uint32_t *)img_hdr_data;
|
||||||
|
uint8_t *digest = (uint8_t *)(img_hdr_data + 4);
|
||||||
|
uint8_t sha_256[DIGEST_SIZE] = { 0 };
|
||||||
|
|
||||||
|
if (recv_magic != esp_delta_ota_magic) {
|
||||||
|
ESP_LOGE(TAG, "Invalid magic word in patch");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256);
|
||||||
|
if (memcmp(sha_256, digest, DIGEST_SIZE) != 0) {
|
||||||
|
ESP_LOGE(TAG, "SHA256 of current firmware differs from than in patch header. Invalid patch for current firmware");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool verify_chip_id(void *bin_header_data)
|
||||||
|
{
|
||||||
|
esp_image_header_t *header = (esp_image_header_t *)bin_header_data;
|
||||||
|
|
||||||
|
if (header->chip_id != CONFIG_IDF_FIRMWARE_CHIP_ID) {
|
||||||
|
ESP_LOGE(TAG, "Mismatch chip id, expected %d, found %d", CONFIG_IDF_FIRMWARE_CHIP_ID, header->chip_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0))
|
||||||
|
static esp_err_t write_cb(const uint8_t *buf_p, size_t size, void *user_data)
|
||||||
|
#else
|
||||||
|
static esp_err_t write_cb(const uint8_t *buf_p, size_t size)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (size <= 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char header_data[IMG_HEADER_LEN];
|
||||||
|
static bool chip_id_verified = false;
|
||||||
|
static int header_data_read = 0;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
if (!chip_id_verified) {
|
||||||
|
if (header_data_read + size <= IMG_HEADER_LEN) {
|
||||||
|
memcpy(header_data + header_data_read, buf_p, size);
|
||||||
|
header_data_read += size;
|
||||||
|
return ESP_OK;
|
||||||
|
} else {
|
||||||
|
index = IMG_HEADER_LEN - header_data_read;
|
||||||
|
memcpy(header_data + header_data_read, buf_p, index);
|
||||||
|
if (!verify_chip_id(header_data)) {
|
||||||
|
return ESP_ERR_INVALID_VERSION;
|
||||||
|
}
|
||||||
|
chip_id_verified = true;
|
||||||
|
|
||||||
|
// Write data in header_data buffer.
|
||||||
|
esp_err_t err = esp_ota_write(out_handle, header_data, IMG_HEADER_LEN);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return esp_ota_write(out_handle, buf_p + index, size - index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t read_cb(uint8_t *buf_p, size_t size, int src_offset)
|
||||||
|
{
|
||||||
|
esp_err_t temp;
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = esp_partition_read(current_partition, src_offset, buf_p, size);
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
bool ble_ota_ringbuf_init(uint32_t ringbuf_size) {
|
||||||
|
s_ringbuf = xRingbufferCreate(ringbuf_size, RINGBUF_TYPE_BYTEBUF);
|
||||||
|
if (s_ringbuf == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write_to_ringbuf(const uint8_t *data, size_t size) {
|
||||||
|
BaseType_t done = xRingbufferSend(s_ringbuf, (void *)data, size, (TickType_t)portMAX_DELAY);
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ota_recv_fw_cb(uint8_t *buf, uint32_t length) {
|
||||||
|
write_to_ringbuf(buf, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ota_task(void *arg) {
|
||||||
|
esp_partition_t *partition_ptr = NULL;
|
||||||
|
esp_partition_t partition;
|
||||||
|
const esp_partition_t *next_partition = NULL;
|
||||||
|
|
||||||
|
uint32_t recv_len = 0;
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
size_t item_size = 0;
|
||||||
|
ESP_LOGI(TAG, "ota_task start");
|
||||||
|
|
||||||
|
notify_sem = xSemaphoreCreateCounting(100, 0);
|
||||||
|
xSemaphoreGive(notify_sem);
|
||||||
|
|
||||||
|
esp_err_t err;
|
||||||
|
esp_delta_ota_cfg_t cfg = {
|
||||||
|
.read_cb = &read_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0))
|
||||||
|
char *user_data = "ble_delta_ota";
|
||||||
|
cfg.write_cb_with_user_data = &write_cb;
|
||||||
|
cfg.user_data = user_data;
|
||||||
|
#else
|
||||||
|
cfg.write_cb = &write_cb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const esp_partition_t *destination_partition;
|
||||||
|
|
||||||
|
esp_delta_ota_handle_t handle = esp_delta_ota_init(&cfg);
|
||||||
|
if (handle == NULL) {
|
||||||
|
ESP_LOGE(TAG, "delta_ota_set_cfg failed!");
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
/* search ota partition */
|
||||||
|
current_partition = esp_ota_get_running_partition();
|
||||||
|
destination_partition = esp_ota_get_next_update_partition(NULL);
|
||||||
|
|
||||||
|
if (current_partition == NULL || destination_partition == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Error getting partition information");
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
if (current_partition->subtype >= ESP_PARTITION_SUBTYPE_APP_OTA_MAX ||
|
||||||
|
destination_partition->subtype >= ESP_PARTITION_SUBTYPE_APP_OTA_MAX) {
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
err = esp_ota_begin(destination_partition, OTA_SIZE_UNKNOWN, &(out_handle));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_ota_begin failed: %s", esp_err_to_name(err));
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "wait for data from ringbuf! fw_len = %u", esp_ble_ota_get_fw_length());
|
||||||
|
/*deal with all receive packet*/
|
||||||
|
for (;;) {
|
||||||
|
data = (uint8_t *)xRingbufferReceive(s_ringbuf, &item_size, (TickType_t)portMAX_DELAY);
|
||||||
|
|
||||||
|
xSemaphoreTake(notify_sem, portMAX_DELAY);
|
||||||
|
|
||||||
|
static int flag = 0;
|
||||||
|
static char ota_write_data[65] = { 0 };
|
||||||
|
|
||||||
|
/*deal with receive patch header*/
|
||||||
|
if (flag == 0) {
|
||||||
|
|
||||||
|
flag = 1;
|
||||||
|
|
||||||
|
/* Read size equal to patch header to verify the header*/
|
||||||
|
memcpy(ota_write_data, data, PATCH_HEADER_SIZE);
|
||||||
|
if (!verify_patch_header(ota_write_data)) {
|
||||||
|
ESP_LOGE(TAG, "Patch Header verification failed!");
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += 64;
|
||||||
|
item_size -= 64;
|
||||||
|
recv_len += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "recv: %u, recv_total:%"PRIu32"\n", item_size, recv_len + item_size);
|
||||||
|
|
||||||
|
if (item_size != 0) {
|
||||||
|
|
||||||
|
if (esp_delta_ota_feed_patch(handle, (const uint8_t *)data, item_size) < 0) {
|
||||||
|
ESP_LOGE(TAG, "Error while applying patch");
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_len += item_size;
|
||||||
|
vRingbufferReturnItem(s_ringbuf, (void *)data);
|
||||||
|
|
||||||
|
if (recv_len >= esp_ble_ota_get_fw_length()) {
|
||||||
|
xSemaphoreGive(notify_sem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(notify_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = esp_delta_ota_finalize(handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_delta_ota_finalize() failed : %s", esp_err_to_name(err));
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = esp_delta_ota_deinit(handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_delta_ota_deinit() failed : %s", esp_err_to_name(err));
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esp_ota_end(out_handle) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_ota_end failed!\r\n");
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esp_ota_set_boot_partition(destination_partition) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed!\r\n");
|
||||||
|
goto OTA_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
vSemaphoreDelete(notify_sem);
|
||||||
|
esp_restart();
|
||||||
|
|
||||||
|
OTA_ERROR:
|
||||||
|
ESP_LOGE(TAG, "OTA failed");
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ota_task_init(void) {
|
||||||
|
xTaskCreate(&ota_task, "ota_task", OTA_TASK_SIZE, NULL, 5, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t baros_ble_ota_init() {
|
||||||
|
if (!ble_ota_ringbuf_init(OTA_RINGBUF_SIZE)) {
|
||||||
|
ESP_LOGE(TAG, "%s init ring buffer failed", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t ret = esp_ble_ota_host_init();
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
esp_ble_ota_recv_fw_data_callback(ota_recv_fw_cb);
|
||||||
|
|
||||||
|
ota_task_init();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue