Skip to content
This repository was archived by the owner on Dec 14, 2025. It is now read-only.

Commit a18a2ed

Browse files
committed
[SYSTEM] Add support for OTA FW update
1 parent 53b51f0 commit a18a2ed

3 files changed

Lines changed: 135 additions & 25 deletions

File tree

main/bluetooth/att.c

Lines changed: 111 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55

66
#include <stdio.h>
7+
#include <esp_ota_ops.h>
8+
#include <esp_system.h>
9+
#include <esp_timer.h>
710
#include "host.h"
811
#include "att.h"
912
#include "zephyr/uuid.h"
@@ -13,6 +16,9 @@
1316

1417
#define ATT_MAX_LEN 512
1518
#define BR_API_VER 1
19+
#define OTA_START 0xA5
20+
#define OTA_ABORT 0xDE
21+
#define OTA_END 0x5A
1622

1723
enum {
1824
GATT_GRP_HDL = 0x0001,
@@ -43,17 +49,28 @@ enum {
4349
BR_IN_CFG_DATA_CHRC_HDL,
4450
BR_API_VER_ATT_HDL,
4551
BR_API_VER_CHRC_HDL,
52+
BR_OTA_FW_CTRL_ATT_HDL,
53+
BR_OTA_FW_CTRL_CHRC_HDL,
54+
BR_OTA_FW_DATA_ATT_HDL,
55+
BR_OTA_FW_DATA_CHRC_HDL,
56+
LAST_HDL = BR_OTA_FW_DATA_CHRC_HDL,
4657
MAX_HDL,
4758
};
4859

4960
static uint8_t br_grp_base_uuid[] = {0x00, 0x9a, 0x79, 0x76, 0xa1, 0x2f, 0x4b, 0x31, 0xb0, 0xfa, 0x80, 0x51, 0x56, 0x0f, 0x83, 0x56};
5061

62+
static esp_ota_handle_t ota_hdl = 0;
63+
static const esp_partition_t *update_partition = NULL;
5164
static uint16_t max_mtu = 23;
5265
static uint16_t mtu = 23;
5366
static uint8_t power = 0;
54-
static uint16_t out_ctrl_cfg_id = 0;
55-
static uint16_t ctrl_offset = 0;
56-
static uint16_t ctrl_cfg_id = 0;
67+
static uint16_t out_cfg_id = 0;
68+
static uint16_t in_cfg_offset = 0;
69+
static uint16_t in_cfg_id = 0;
70+
71+
static void bt_att_restart(void *arg) {
72+
esp_restart();
73+
}
5774

5875
static void bt_att_cmd(uint16_t handle, uint8_t code, uint16_t len) {
5976
uint16_t packet_len = (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE
@@ -206,8 +223,20 @@ static void bt_att_cmd_blueretro_char_read_type_rsp(uint16_t handle, uint16_t st
206223
else {
207224
rd_type_rsp->data->handle = start;
208225
}
209-
*data = BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE;
210-
data++;
226+
227+
switch (rd_type_rsp->data->handle + 1) {
228+
case BR_API_VER_CHRC_HDL:
229+
*data++ = BT_GATT_CHRC_READ;
230+
break;
231+
case BR_OTA_FW_CTRL_CHRC_HDL:
232+
case BR_OTA_FW_DATA_CHRC_HDL:
233+
*data++ = BT_GATT_CHRC_WRITE;
234+
break;
235+
default:
236+
*data++ = BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE;
237+
break;
238+
}
239+
211240
*(uint16_t *)data = rd_type_rsp->data->handle + 1;
212241
data += 2;
213242
memcpy(data, br_grp_base_uuid, sizeof(br_grp_base_uuid));
@@ -270,12 +299,12 @@ static void bt_att_cmd_config_rd_rsp(uint16_t handle, uint8_t config_id, uint16_
270299
len = mtu - 1;
271300
}
272301

273-
memcpy(bt_hci_pkt_tmp.att_data, (void *)&config.out_cfg[out_ctrl_cfg_id] + offset, len);
302+
memcpy(bt_hci_pkt_tmp.att_data, (void *)&config.out_cfg[out_cfg_id] + offset, len);
274303
}
275304
}
276305
else if (config_id == 4) {
277-
uint32_t cfg_len = (sizeof(config.in_cfg[0]) - (ADAPTER_MAPPING_MAX * sizeof(config.in_cfg[0].map_cfg[0]) - config.in_cfg[ctrl_cfg_id].map_size * sizeof(config.in_cfg[0].map_cfg[0])));
278-
uint32_t sum_offset = ctrl_offset + offset;
306+
uint32_t cfg_len = (sizeof(config.in_cfg[0]) - (ADAPTER_MAPPING_MAX * sizeof(config.in_cfg[0].map_cfg[0]) - config.in_cfg[in_cfg_id].map_size * sizeof(config.in_cfg[0].map_cfg[0])));
307+
uint32_t sum_offset = in_cfg_offset + offset;
279308
printf("# Input config %d\n", cfg_len);
280309
if (sum_offset > cfg_len || offset > ATT_MAX_LEN) {
281310
len = 0;
@@ -291,7 +320,7 @@ static void bt_att_cmd_config_rd_rsp(uint16_t handle, uint8_t config_id, uint16_
291320
len = ATT_MAX_LEN - offset;
292321
}
293322

294-
memcpy(bt_hci_pkt_tmp.att_data, (void *)&config.in_cfg[ctrl_cfg_id] + sum_offset, len);
323+
memcpy(bt_hci_pkt_tmp.att_data, (void *)&config.in_cfg[in_cfg_id] + sum_offset, len);
295324
}
296325
}
297326
else {
@@ -347,9 +376,9 @@ static void bt_att_cmd_read_group_rsp(uint16_t handle, uint16_t start, uint16_t
347376
else {
348377
rd_grp_rsp->len = 20;
349378

350-
if (start <= BR_GRP_HDL && end >= BR_API_VER_CHRC_HDL) {
379+
if (start <= BR_GRP_HDL && end >= LAST_HDL) {
351380
gatt_data->start_handle = BR_GRP_HDL;
352-
gatt_data->end_handle = BR_API_VER_CHRC_HDL;
381+
gatt_data->end_handle = LAST_HDL;
353382
memcpy(gatt_data->value, br_grp_base_uuid, sizeof(br_grp_base_uuid));
354383
len += rd_grp_rsp->len;
355384
}
@@ -380,6 +409,7 @@ static void bt_att_cmd_exec_wr_rsp(uint16_t handle) {
380409

381410
void bt_att_set_le_max_mtu(uint16_t le_max_mtu) {
382411
max_mtu = le_max_mtu;
412+
printf("# %s %d\n", __FUNCTION__, max_mtu);
383413
}
384414

385415
void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len) {
@@ -394,6 +424,7 @@ void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint3
394424
else {
395425
mtu = max_mtu;
396426
}
427+
printf("# Set mtu %d\n", mtu);
397428
bt_att_cmd_mtu_rsp(device->acl_handle, mtu);
398429
break;
399430
}
@@ -437,7 +468,7 @@ void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint3
437468
bt_att_cmd_batt_char_read_type_rsp(device->acl_handle);
438469
}
439470
/* BLUERETRO */
440-
else if (start >= BATT_CHRC_HDL && start < BR_API_VER_CHRC_HDL && end >= BR_API_VER_CHRC_HDL) {
471+
else if (start >= BATT_CHRC_HDL && start < LAST_HDL && end >= LAST_HDL) {
441472
bt_att_cmd_blueretro_char_read_type_rsp(device->acl_handle, start);
442473
}
443474
else {
@@ -521,8 +552,9 @@ void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint3
521552
{
522553
struct bt_att_write_req *wr_req = (struct bt_att_write_req *)bt_hci_acl_pkt->att_data;
523554
uint16_t *data = (uint16_t *)wr_req->value;
524-
uint32_t data_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_att_hdr));
525-
printf("# BT_ATT_OP_WRITE_REQ\n");
555+
uint32_t att_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_att_hdr));
556+
uint32_t data_len = att_len - sizeof(wr_req->handle);
557+
printf("# BT_ATT_OP_WRITE_REQ len: %d\n", data_len);
526558
switch (wr_req->handle) {
527559
case BR_GLBL_CFG_CHRC_HDL:
528560
printf("# BR_GLBL_CFG_CHRC_HDL %04X\n", wr_req->handle);
@@ -531,23 +563,72 @@ void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint3
531563
bt_att_cmd_wr_rsp(device->acl_handle);
532564
break;
533565
case BR_OUT_CFG_DATA_CHRC_HDL:
534-
memcpy((void *)&config.out_cfg[out_ctrl_cfg_id], wr_req->value, sizeof(config.out_cfg[0]));
566+
memcpy((void *)&config.out_cfg[out_cfg_id], wr_req->value, sizeof(config.out_cfg[0]));
535567
config_update();
536568
bt_att_cmd_wr_rsp(device->acl_handle);
537569
break;
538570
case BR_IN_CFG_DATA_CHRC_HDL:
539-
memcpy((void *)&config.in_cfg[ctrl_cfg_id], wr_req->value, data_len);
571+
memcpy((void *)&config.in_cfg[in_cfg_id] + in_cfg_offset, wr_req->value, data_len);
540572
config_update();
541573
bt_att_cmd_wr_rsp(device->acl_handle);
542574
break;
543575
case BR_OUT_CFG_CTRL_CHRC_HDL:
544-
out_ctrl_cfg_id = *data;
576+
out_cfg_id = *data;
545577
bt_att_cmd_wr_rsp(device->acl_handle);
546578
break;
547579
case BR_IN_CFG_CTRL_CHRC_HDL:
548-
ctrl_cfg_id = *data;
549-
data++;
550-
ctrl_offset = *data;
580+
in_cfg_id = *data++;
581+
in_cfg_offset = *data;
582+
bt_att_cmd_wr_rsp(device->acl_handle);
583+
break;
584+
case BR_OTA_FW_CTRL_CHRC_HDL:
585+
switch (wr_req->value[0]) {
586+
case OTA_START:
587+
update_partition = esp_ota_get_next_update_partition(NULL);
588+
if (esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &ota_hdl) == 0) {
589+
printf("# OTA FW Update started...\n");
590+
}
591+
else {
592+
esp_ota_abort(ota_hdl);
593+
ota_hdl = 0;
594+
printf("# OTA FW Update start fail\n");
595+
}
596+
break;
597+
case OTA_END:
598+
if (esp_ota_end(ota_hdl) == 0) {
599+
if (esp_ota_set_boot_partition(update_partition) == 0) {
600+
ota_hdl = 0;
601+
const esp_timer_create_args_t ota_restart_args = {
602+
.callback = &bt_att_restart,
603+
.arg = (void *)device,
604+
.name = "ota_restart"
605+
};
606+
esp_timer_handle_t timer_hdl;
607+
608+
esp_timer_create(&ota_restart_args, &timer_hdl);
609+
esp_timer_start_once(timer_hdl, 1000000);
610+
printf("# OTA FW Update sucessfull! Restarting...\n");
611+
}
612+
else {
613+
printf("# OTA FW Update set partition fail\n");
614+
}
615+
}
616+
else {
617+
printf("# OTA FW Update end fail\n");
618+
}
619+
break;
620+
default:
621+
if (ota_hdl) {
622+
esp_ota_abort(ota_hdl);
623+
ota_hdl = 0;
624+
printf("# OTA FW Update abort from WebUI\n");
625+
}
626+
break;
627+
}
628+
bt_att_cmd_wr_rsp(device->acl_handle);
629+
break;
630+
case BR_OTA_FW_DATA_CHRC_HDL:
631+
esp_ota_write(ota_hdl, wr_req->value, data_len);
551632
bt_att_cmd_wr_rsp(device->acl_handle);
552633
break;
553634
default:
@@ -559,12 +640,17 @@ void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint3
559640
case BT_ATT_OP_PREPARE_WRITE_REQ:
560641
{
561642
struct bt_att_prepare_write_req *prep_wr_req = (struct bt_att_prepare_write_req *)bt_hci_acl_pkt->att_data;
562-
uint32_t data_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_att_hdr));
563-
printf("# BT_ATT_OP_PREPARE_WRITE_REQ %d %d\n", len, data_len);
643+
uint32_t att_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_att_hdr));
644+
uint32_t data_len = att_len - (sizeof(prep_wr_req->handle) + sizeof(prep_wr_req->offset));
645+
printf("# BT_ATT_OP_PREPARE_WRITE_REQ len: %d offset: %d\n", data_len, prep_wr_req->offset);
564646
switch (prep_wr_req->handle) {
565647
case BR_IN_CFG_DATA_CHRC_HDL:
566-
memcpy((void *)&config.in_cfg[ctrl_cfg_id] + ctrl_offset + prep_wr_req->offset, prep_wr_req->value, data_len);
567-
bt_att_cmd_prep_wr_rsp(device->acl_handle, bt_hci_acl_pkt->att_data, data_len);
648+
memcpy((void *)&config.in_cfg[in_cfg_id] + in_cfg_offset + prep_wr_req->offset, prep_wr_req->value, data_len);
649+
bt_att_cmd_prep_wr_rsp(device->acl_handle, bt_hci_acl_pkt->att_data, att_len);
650+
break;
651+
case BR_OTA_FW_DATA_CHRC_HDL:
652+
esp_ota_write(ota_hdl, prep_wr_req->value, data_len);
653+
bt_att_cmd_prep_wr_rsp(device->acl_handle, bt_hci_acl_pkt->att_data, att_len);
568654
break;
569655
default:
570656
bt_att_cmd_error_rsp(device->acl_handle, BT_ATT_OP_PREPARE_WRITE_REQ, prep_wr_req->handle, BT_ATT_ERR_INVALID_HANDLE);
@@ -576,7 +662,7 @@ void bt_att_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint3
576662
{
577663
struct bt_att_exec_write_req *exec_wr_req = (struct bt_att_exec_write_req *)bt_hci_acl_pkt->att_data;
578664
printf("# BT_ATT_OP_EXEC_WRITE_REQ\n");
579-
if (exec_wr_req->flags == BT_ATT_FLAG_EXEC) {
665+
if (!ota_hdl && exec_wr_req->flags == BT_ATT_FLAG_EXEC) {
580666
config_update();
581667
}
582668
bt_att_cmd_exec_wr_rsp(device->acl_handle);

main/main.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string.h>
77
#include <freertos/FreeRTOS.h>
88
#include <freertos/task.h>
9+
#include <esp_ota_ops.h>
910
#include "system/bare_metal_app_cpu.h"
1011
#include "system/core0_stall.h"
1112
#include "system/delay.h"
@@ -194,12 +195,17 @@ static void wired_init_task(void) {
194195
}
195196

196197
static void wl_init_task(void *arg) {
198+
uint32_t err = 0;
199+
const esp_partition_t *running = esp_ota_get_running_partition();
200+
esp_ota_img_states_t ota_state;
201+
esp_ota_get_state_partition(running, &ota_state);
197202
err_led_init();
198203

199204
core0_stall_init();
200205

201206
if (fs_init()) {
202207
err_led_set();
208+
err = 1;
203209
printf("FATFS init fail!\n");
204210
}
205211

@@ -208,10 +214,21 @@ static void wl_init_task(void *arg) {
208214
#ifndef CONFIG_BLUERETRO_BT_DISABLE
209215
if (bt_host_init()) {
210216
err_led_set();
217+
err = 1;
211218
printf("Bluetooth init fail!\n");
212219
}
213220
#endif
214221

222+
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
223+
if (err) {
224+
printf("Boot error on pending img, rollback to the previous version.");
225+
esp_ota_mark_app_invalid_rollback_and_reboot();
226+
}
227+
else {
228+
printf("Pending img valid!");
229+
esp_ota_mark_app_valid_cancel_rollback();
230+
}
231+
}
215232
vTaskDelete(NULL);
216233
}
217234

main/system/btn.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <stdio.h>
77
#include <freertos/FreeRTOS.h>
88
#include <freertos/task.h>
9+
#include <esp_partition.h>
910
#include "zephyr/atomic.h"
1011
#include "driver/gpio.h"
1112
#include "system/fs.h"
@@ -53,6 +54,12 @@ static void boot_btn_task(void *param) {
5354

5455
while (!gpio_get_level(BOOT_BTN_PIN)) {
5556
if (hold_cnt++ > RESET_EVT_THRESHOLD) {
57+
const esp_partition_t* partition = esp_partition_find_first(
58+
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, "otadata");
59+
if (partition) {
60+
esp_partition_erase_range(partition, 0, partition->size);
61+
}
62+
5663
fs_reset();
5764
printf("BlueRetro factory reset\n");
5865
vTaskDelay(1000 / portTICK_PERIOD_MS);

0 commit comments

Comments
 (0)