From 9a544172c2e6a95bb9fd5e665041ec8b481b9a2b Mon Sep 17 00:00:00 2001 From: SSAnkur Date: Mon, 19 Oct 2026 16:23:55 +0600 Subject: [PATCH] Switched to Official SDK --- LYWSD03MMC-BTHome.bin | Bin 42596 -> 54212 bytes README.md | 67 +++++++++++++++++++----- makefile | 118 ++++++++++++++++++++++++------------------ src/app_config.h | 51 +++++++++++++----- src/battery.c | 19 ++++++- src/ble.c | 99 ++++++++++++++++++----------------- src/lcd.c | 1 - src/main.c | 47 ++++++++++++----- 8 files changed, 260 insertions(+), 142 deletions(-) diff --git a/LYWSD03MMC-BTHome.bin b/LYWSD03MMC-BTHome.bin index 762a078f1d63c59f7f63d18bbd22745609a5f53e..0a6dc9b5d3766bd47e551ea10e79ca435e312230 100644 GIT binary patch literal 54212 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 Cu%H6~ literal 42596 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 j;peAtZG= %s deep retention, RAM used %d B of 32768, image %d B\n", \ + r, t, (t < 16384 ? "16K" : "32K"), e, b }' -# Raw image + Telink CRC (required by the OTA bootloader) $(BIN): $(ELF) $(OBJCOPY) -O binary $< $@ - $(PYTHON) $(ATC_PATH)/utils/tl_check_fw.py $@ + $(CHECK_FW) clean: rm -rf $(OUT_PATH) $(BIN) diff --git a/src/app_config.h b/src/app_config.h index bbc9d8f..4f2dac1 100644 --- a/src/app_config.h +++ b/src/app_config.h @@ -11,16 +11,18 @@ * to measure VDD (= CR2032 voltage) * PD7 LCD SPI-CLK * PB7 LCD SPI-SDI + * + * Built against the official Telink tc_ble_single_sdk. The makefile + * force-includes this file into every translation unit (-include), SDK + * sources included, because the SDK's vendor/common/user_config.h only + * knows its own demo projects. That is how gpio_init() in the SDK sees the + * PB0 settings below. */ #pragma once +/* System clock. vendor/common/app_common.h derives SYS_CLK_TYPE and + * CLOCK_SYS_CLOCK_1S/1MS/1US from this; do not define them here. */ #define CLOCK_SYS_CLOCK_HZ 24000000 -#define SYS_CLK_TYPE SYS_CLK_24M_Crystal -enum { - CLOCK_SYS_CLOCK_1S = CLOCK_SYS_CLOCK_HZ, - CLOCK_SYS_CLOCK_1MS = (CLOCK_SYS_CLOCK_1S / 1000), - CLOCK_SYS_CLOCK_1US = (CLOCK_SYS_CLOCK_1S / 1000000), -}; /* Low-power busy wait: CPU stalled, woken by timer0 */ #define pm_wait_us(t) cpu_stall_wakeup_by_timer0((t) * CLOCK_SYS_CLOCK_1US) @@ -29,6 +31,19 @@ enum { /* Variables that must survive deep-sleep retention */ #define RAM _attribute_data_retention_ +/* ---- SDK feature switches ---- */ +#define BLE_APP_PM_ENABLE 1 +#define PM_DEEPSLEEP_RETENTION_ENABLE 1 /* also feeds the boot.link check */ +#define BLE_APP_SECURITY_ENABLE 0 /* no pairing: OTA service only */ +#define APP_FLASH_PROTECTION_ENABLE 0 /* see flash_clear_write_protection() */ +#define UART_PRINT_DEBUG_ENABLE 0 +#define MODULE_WATCHDOG_ENABLE 0 + +/* No Telink evaluation board: a value that matches none of the boards in + * vendor/common/boards, so default_config.h pulls in no board pin map */ +#define BOARD_LYWSD03MMC_B15 0xB150 +#define BOARD_SELECT BOARD_LYWSD03MMC_B15 + /* ---- Application settings (equivalents of the Zephyr build) ---- */ #define DEV_NAME "LYWSD03MMC" /* CONFIG_BT_DEVICE_NAME */ #define ADV_INTERVAL 16000 /* 10000 ms / 0.625 ms */ @@ -52,12 +67,22 @@ enum { #define OTA_WINDOW_S 120 #define OTA_WINDOW_ADV_INTERVAL 1600 /* 1 s while the window is open */ +/* Power-on marker. DEEP_ANA_REG1 keeps its value through deep sleep and + * software reboots and is cleared only by a power cycle. (DEEP_ANA_REG0, + * used by the pvvx build, is reserved by the official SDK: its bit 1 is + * the crystal start-up failure flag.) */ +#define POWER_ON_FLAG_REG DEEP_ANA_REG1 +#define POWER_ON_FLAG 0x55 + /* ---- Connection / OTA (values from pvvx ble.h / app.c) ---- */ #define CONN_INTERVAL 16 /* 16 * 1.25 ms = 20 ms */ #define CONN_LATENCY 49 /* (49 + 1) * 20 ms = 1 s between radio events */ #define CONN_TIMEOUT 400 /* x10 ms = 4 s */ -#define OTA_IDLE_TIMEOUT_US (16 * 1000000) /* abort OTA after 16 s without data */ - +/* Official OTA server timeouts. The packet timeout is an inactivity + * timeout (1..20 s); the process timeout limits the whole upload + * (5..1000 s, SDK default only 30 s). */ +#define OTA_PACKET_TIMEOUT_S 16 /* abort OTA after 16 s without data */ +#define OTA_PROCESS_TIMEOUT_S 1000 /* ---- I2C ---- */ #define I2C_GROUP I2C_GPIO_GROUP_C2C3 @@ -69,7 +94,10 @@ enum { /* ---- Battery ADC ---- */ #define GPIO_VBAT GPIO_PB0 #define ADC_VBAT_CHN B0P -#define ADC_VREF_MV 1175 /* typical internal 1.2 V ref, mV */ +/* 0: use the chip's ADC reference calibration, loaded by the SDK from the + * calibration sector or eFuse (typical 1175 mV if there is none). + * Non-zero: fixed reference in mV, to trim against a meter. */ +#define ADC_VREF_MV 0 /* PB0 (not bonded) is driven high permanently, as in pvvx: no toggling * around each ADC read, and the pad never floats. Applied by gpio_init() * on every wake-up, including from deep-sleep retention. */ @@ -89,9 +117,4 @@ enum { #define GPIO_KEY GPIO_PA5 #define PULL_KEY PM_PIN_PULLUP_1M -#define MODULE_WATCHDOG_ENABLE 0 - -/* Stock Xiaomi flash layout: factory MAC address lives here */ -#define CFG_ADR_MAC 0x76000 - #include "vendor/common/default_config.h" diff --git a/src/battery.c b/src/battery.c index 840f28a..4750dbf 100644 --- a/src/battery.c +++ b/src/battery.c @@ -3,7 +3,9 @@ * kept driven high (= VDD) permanently by gpio_init() (see app_config.h, * same as pvvx) and sampled through the 1/8 prescaler against the * 1.2 V reference. 8 samples are taken, sorted, and the middle 4 averaged. - * ADC sequence follows pvvx/ATC_MiThermometer battery.c. + * ADC sequence follows pvvx/ATC_MiThermometer battery.c; the conversion + * uses the per-chip reference calibration of the official SDK (as its + * adc_sample_and_get_result() does) unless ADC_VREF_MV fixes it. */ #include "tl_common.h" #include "drivers.h" @@ -12,6 +14,11 @@ #define ADC_SAMPLES 8 +/* Set by user_calib_adc_vref() from blc_app_loadCustomizedParameters_normal() + * (drivers/B85/adc.c, retention RAM, default 1175 mV / 0 mV) */ +extern unsigned short adc_gpio_calib_vref; +extern signed char adc_gpio_calib_vref_offset; + /* ADC analog config is not kept across deep-sleep retention: set it up each time */ static void vbat_adc_setup(void) { @@ -61,8 +68,16 @@ u16 battery_read_mv(void) dfifo_disable_dfifo2(); adc_power_on_sar_adc(0); - /* mV = avg/8192 * Vref * 8 = sum4 * Vref / 4096 */ + /* mV = avg/8192 * Vref * 8 + offset = sum4 * Vref / 4096 + offset */ u32 sum = s[2] + s[3] + s[4] + s[5]; + if (!sum) { + return 0; + } +#if ADC_VREF_MV return (u16)((sum * ADC_VREF_MV + 2048) >> 12); +#else + return (u16)((s32)((sum * adc_gpio_calib_vref + 2048) >> 12) + + adc_gpio_calib_vref_offset); +#endif } diff --git a/src/ble.c b/src/ble.c index f69986f..f0374d6 100644 --- a/src/ble.c +++ b/src/ble.c @@ -7,23 +7,23 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. * * OTA itself (packet handling, CRC, flash writes, swapping the boot bank - * and rebooting) is done by the Telink BLE library: otaWrite()/otaRead(). - * The new image is written to the bank that is not running (0x00000 or - * 0x20000, 128 KiB each), so a failed transfer leaves the old firmware - * bootable. + * and rebooting) is done by the OTA server of the official Telink BLE + * library (stack/ble/service/ota/ota_server.h, otaWrite()). It speaks the + * legacy Telink OTA protocol (CMD_OTA_START / data / CMD_OTA_END) used by + * TelinkOTA.html, plus the extended one. The new image is written to the + * bank that is not running (0x00000 or 0x20000, 128 KiB each; at most + * 124 KiB of firmware, the SDK default), so a failed transfer leaves the old + * firmware bootable. */ #include "tl_common.h" #include "drivers.h" #include "stack/ble/ble.h" -#include "stack/ble/service/ble_ll_ota.h" -#include "vendor/common/blt_common.h" #include "app_config.h" #include "ble.h" #include "lcd.h" -void bls_set_advertise_prepare(void *p); /* in the library, no header */ - -/* Peripheral Preferred Connection Parameters (not in this SDK's headers) */ +/* Peripheral Preferred Connection Parameters (not in the SDK headers; + * the SDK's ble_sample defines it locally too) */ typedef struct { u16 intervalMin; u16 intervalMax; @@ -46,9 +46,6 @@ RAM static u32 window_start; static void close_window(void); RAM static u8 conn_param_accepted; -RAM static u8 mac_public[6]; -static u8 mac_random_static[6]; - /* Scan response: complete local name DEV_NAME */ #define NAME_LEN (sizeof(DEV_NAME) - 1) RAM static u8 scan_rsp[2 + NAME_LEN]; @@ -74,6 +71,7 @@ enum { OTA_PS_H, /* Telink OTA */ OTA_CD_H, OTA_DP_H, + OTA_CCC_H, OTA_DESC_H, ATT_END_H, @@ -120,27 +118,21 @@ static const u8 service_change_cd[5] = { U16_LO(GATT_UUID_SERVICE_CHANGE), U16_HI(GATT_UUID_SERVICE_CHANGE) }; -/* Telink OTA */ -static const u8 ota_service_uuid[16] = TELINK_OTA_UUID_SERVICE; -static const u8 ota_data_uuid[16] = TELINK_SPP_DATA_OTA; -static u8 ota_data; +/* Telink OTA, laid out as in the SDK's ble_sample: the official OTA + * server answers on the data characteristic itself (result and version + * responses of the extended protocol), hence NOTIFY and the CCC. */ +static const u8 ota_service_uuid[16] = WRAPPING_BRACES(TELINK_OTA_UUID_SERVICE); +static const u8 ota_data_uuid[16] = WRAPPING_BRACES(TELINK_SPP_DATA_OTA); +RAM static u8 ota_data; +RAM static u8 ota_ccc[2]; static const u8 ota_name[] = { 'O', 'T', 'A' }; static const u8 ota_cd[19] = { - CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RSP, + CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RSP | CHAR_PROP_NOTIFY | + CHAR_PROP_WRITE, U16_LO(OTA_DP_H), U16_HI(OTA_DP_H), - 0x12, 0x2B, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 + TELINK_SPP_DATA_OTA }; - -/* Make the library's OTA timeout an inactivity timeout (pvvx otaWritePre): - * every OTA packet restarts it. */ -static int ota_write_pre(void *p) -{ - blt_ota_start_tick = clock_time() | 1; - return otaWrite(p); -} - /* In RAM, as pvvx: the stack walks this table from interrupt context, * which must not depend on flash reads while OTA is erasing/writing it. */ RAM static attribute_t attributes[] = { @@ -159,9 +151,10 @@ RAM static attribute_t attributes[] = { { 0, ATT_PERMISSIONS_READ, 2, sizeof(service_change_val), (u8 *)&service_change_uuid, (u8 *)&service_change_val, 0, 0 }, { 0, ATT_PERMISSIONS_RDWR, 2, sizeof(service_change_ccc), (u8 *)&ccc_uuid, (u8 *)&service_change_ccc, 0, 0 }, - { 4, ATT_PERMISSIONS_READ, 2, 16, (u8 *)&primary_service_uuid, (u8 *)ota_service_uuid, 0, 0 }, + { 5, ATT_PERMISSIONS_READ, 2, 16, (u8 *)&primary_service_uuid, (u8 *)ota_service_uuid, 0, 0 }, { 0, ATT_PERMISSIONS_READ, 2, sizeof(ota_cd), (u8 *)&character_uuid, (u8 *)ota_cd, 0, 0 }, - { 0, ATT_PERMISSIONS_RDWR, 16, sizeof(ota_data), (u8 *)ota_data_uuid, &ota_data, &ota_write_pre, &otaRead }, + { 0, ATT_PERMISSIONS_RDWR, 16, sizeof(ota_data), (u8 *)ota_data_uuid, &ota_data, &otaWrite, 0 }, + { 0, ATT_PERMISSIONS_RDWR, 2, sizeof(ota_ccc), (u8 *)&ccc_uuid, ota_ccc, 0, 0 }, { 0, ATT_PERMISSIONS_READ, 2, sizeof(ota_name), (u8 *)&user_desc_uuid, (u8 *)ota_name, 0, 0 }, }; @@ -174,7 +167,6 @@ static void ota_start_cb(void) ota_active = 1; conn_param_accepted = 0; bls_pm_setManualLatency(0); - bls_ota_setTimeout(OTA_IDLE_TIMEOUT_US); } /* After a successful OTA the library reboots into the new image itself; @@ -233,12 +225,17 @@ static void suspend_exit_cb(u8 e, u8 *p, int n) void ble_init(const u8 *adv, int adv_len, int (*adv_prepare)(void *), int open_window) { - /* Factory public address (A4:C1:38:...) from the stock flash layout */ - blc_initMacAddress(CFG_ADR_MAC, mac_public, mac_random_static); + u8 mac_public[6]; + u8 mac_random_static[6]; + + /* Factory public address (A4:C1:38:...) from the stock flash layout: + * flash_sector_mac_address = 0x76000 on the 512 KiB flash */ + blc_initMacAddress(flash_sector_mac_address, mac_public, + mac_random_static); memcpy(&scan_rsp[2], DEV_NAME, NAME_LEN); scan_rsp[0] = NAME_LEN + 1; - scan_rsp[1] = GAP_ADTYPE_LOCAL_NAME_COMPLETE; + scan_rsp[1] = DT_COMPLETE_LOCAL_NAME; /* Controller */ blc_ll_initStandby_module(mac_public); @@ -246,23 +243,26 @@ void ble_init(const u8 *adv, int adv_len, int (*adv_prepare)(void *), blc_ll_initConnection_module(); blc_ll_initSlaveRole_module(); - /* Host */ + /* Host (GAP first, as the SDK requires) */ blc_gap_peripheral_init(); - bls_att_setAttributeTable((u8 *)attributes); blc_l2cap_register_handler(blc_l2cap_packet_receive); + bls_att_setAttributeTable((u8 *)attributes); blc_smp_setSecurityLevel(No_Security); + /* OTA server. Its init also erases the inactive bank if it still + * holds an old image. */ + blc_ota_initOtaServer_module(); + blc_ota_setOtaProcessTimeout(OTA_PROCESS_TIMEOUT_S); + blc_ota_setOtaDataPacketTimeout(OTA_PACKET_TIMEOUT_S); + blc_ota_registerOtaStartCmdCb(ota_start_cb); + blc_ota_registerOtaResultIndicationCb(ota_result_cb); + rf_set_power_level_index(RF_TX_POWER); bls_app_registerEventCallback(BLT_EV_FLAG_CONNECT, &connect_cb); bls_app_registerEventCallback(BLT_EV_FLAG_TERMINATE, &disconnect_cb); bls_app_registerEventCallback(BLT_EV_FLAG_SUSPEND_EXIT, &suspend_exit_cb); blc_l2cap_registerConnUpdateRspCb(conn_param_rsp_cb); - /* OTA: erase the inactive bank if it still holds an old image */ - bls_ota_clearNewFwDataArea(); - bls_ota_registerStartCmdCb(ota_start_cb); - bls_ota_registerResultIndicateCb(ota_result_cb); - /* Advertising */ bls_ll_setAdvData((u8 *)adv, adv_len); bls_ll_setScanRspData(scan_rsp, sizeof(scan_rsp)); @@ -281,19 +281,18 @@ void ble_init(const u8 *adv, int adv_len, int (*adv_prepare)(void *), close_window(); } - /* Power management (pvvx init_ble) */ + /* Power management. Thresholds as pvvx init_ble; early wake-up and + * retention size as the SDK's ble_sample: 16 KiB retention when code + * + retained data fit, else 32 KiB. */ blc_ll_initPowerManagement_module(); + blc_app_setDeepsleepRetentionSramSize(); blc_pm_setDeepsleepRetentionThreshold(40, 18); - blc_pm_setDeepsleepRetentionEarlyWakeupTiming(240); - blc_pm_setDeepsleepRetentionType(DEEPSLEEP_MODE_RET_SRAM_LOW32K); + blc_pm_setDeepsleepRetentionEarlyWakeupTiming(270); bls_pm_setSuspendMask(SUSPEND_ADV | DEEPSLEEP_RETENTION_ADV | SUSPEND_CONN | DEEPSLEEP_RETENTION_CONN); bls_pm_setManualLatency(0); } -/* Called every main-loop pass. During OTA: answer every connection event - * (no slave latency) and never use deep-sleep retention, which would drop - * the transfer state. Otherwise allow the deepest sleep everywhere. */ /* Window over: non-connectable advertising at the normal interval. In * this mode the radio does not listen after each packet. */ static void close_window(void) @@ -306,6 +305,9 @@ static void close_window(void) lcd_show_ble(0); } +/* Called every main-loop pass. During OTA: answer every connection event + * (no slave latency) and never use deep-sleep retention, which would drop + * the transfer state. Otherwise allow the deepest sleep everywhere. */ _attribute_ram_code_ int ble_task(void) { @@ -336,5 +338,6 @@ void ble_init_deep_retention(void) { rf_set_power_level_index(RF_TX_POWER); blc_ll_recoverDeepRetention(); - bls_ota_registerStartCmdCb(ota_start_cb); /* as pvvx */ + /* OTA server state and callbacks live in retention RAM in the + * official library: nothing to re-register */ } diff --git a/src/lcd.c b/src/lcd.c index 43ac035..0f80952 100644 --- a/src/lcd.c +++ b/src/lcd.c @@ -25,7 +25,6 @@ */ #include "tl_common.h" #include "drivers.h" -#include "drivers/8258/gpio_8258.h" #include "app_config.h" #include "lcd.h" diff --git a/src/main.c b/src/main.c index 88b0c5a..4a72544 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,7 @@ /* * BTHome v2 temperature / humidity beacon with LCD and OTA - Xiaomi - * LYWSD03MMC B1.5 (Telink TLSR8251, Telink BLE SDK, no RTOS) + * LYWSD03MMC B1.5 (Telink TLSR8251, official Telink tc_ble_single_sdk, + * no RTOS) * * Every 60 s: measure T/RH (SHTV3) and VDD, update the segment LCD and the * BTHome v2 advertisement sent every 10 s. For OTA_WINDOW_S after the @@ -21,7 +22,6 @@ #include "tl_common.h" #include "drivers.h" #include "stack/ble/ble.h" -#include "vendor/common/blt_common.h" #include "app_config.h" #include "sensor.h" #include "battery.h" @@ -92,6 +92,22 @@ static void low_battery(u16 mv) deep_sleep_s(LOW_VBAT_SLEEP_S); } +/* The OTA server writes flash: clear block protection left by other + * firmware, once per power-on, as pvvx does. Same operation as the pvvx + * SDK's flash_unlock() (status register := 0), done with the official + * driver, but only when a protection bit is actually set. Works on any + * SPI flash, unlike the per-chip flash_prot.c, which only knows the + * flash types listed in the SDK. */ +#define FLASH_SR_PROTECT_BITS 0xFC /* BP0..BP4, SRP0 */ + +static void flash_clear_write_protection(void) +{ + if (flash_read_status(FLASH_READ_STATUS_CMD_LOWBYTE) & + FLASH_SR_PROTECT_BITS) { + flash_write_status(FLASH_TYPE_8BIT_STATUS, 0); + } +} + _attribute_ram_code_ static void store_result(s32 mc, s32 mrh) { @@ -173,6 +189,16 @@ static int adv_prepare_cb(void *p) static void user_init_normal(void) { + /* Must come before any BLE stack initialisation (official order) */ + random_generator_init(); + + /* Flash size -> sector map (MAC 0x76000, calibration 0x77000 on the + * 512 KiB part), then the factory calibration from that sector: + * crystal trim, flash supply and ADC reference. Read-only, so it is + * safe before the battery check, which needs the ADC calibration. */ + blc_readFlashSize_autoConfigCustomFlashSector(); + blc_app_loadCustomizedParameters_normal(); + blc_ll_initBasicMCU(); adc_power_on_sar_adc(0); lpc_power_down(); @@ -194,10 +220,7 @@ static void user_init_normal(void) low_battery(vbat_mv); } - /* The library writes flash for OTA: clear write protection left by - * other firmware (as pvvx, once per power-on) */ - flash_unlock(); - random_generator_init(); + flash_clear_write_protection(); #if ADV_NAME_IN_ADV memcpy(&adv[18], DEV_NAME, NAME_LEN); @@ -217,11 +240,10 @@ static void user_init_normal(void) } publish(); - /* DEEP_ANA_REG0 survives deep sleep and software reboots and is - * cleared only by a power cycle (pvvx uses it the same way) */ - int power_on = analog_read(DEEP_ANA_REG0) != 0x55; + /* Cleared only by a power cycle, see app_config.h */ + int power_on = analog_read(POWER_ON_FLAG_REG) != POWER_ON_FLAG; - analog_write(DEEP_ANA_REG0, 0x55); + analog_write(POWER_ON_FLAG_REG, POWER_ON_FLAG); bls_pm_registerAppWakeupLowPowerCb(measure_done_cb); ble_init(adv, sizeof(adv), adv_prepare_cb, power_on); @@ -231,6 +253,7 @@ static void user_init_normal(void) _attribute_ram_code_ static void user_init_deepRetn(void) { + blc_app_loadCustomizedParameters_deepRetn(); /* crystal trim, VDD_F */ blc_ll_initBasicMCU(); ble_init_deep_retention(); } @@ -280,11 +303,11 @@ int main(void) int deep_ret = pm_is_MCU_deepRetentionWakeup(); + /* Same order as the SDK's ble_sample */ + rf_drv_ble_init(); gpio_init(!deep_ret); clock_init(SYS_CLK_TYPE); - rf_drv_init(RF_MODE_BLE_1M); reg_clk_en0 = FLD_CLK0_SWIRE_EN; /* gate unused peripheral clocks */ - blc_app_loadCustomizedParameters(); /* factory crystal trim */ if (deep_ret) { user_init_deepRetn();