diff --git a/component/xc6xx_drivers/Drivers/CMSIS/Device/xc6xxx.h b/component/xc6xx_drivers/Drivers/CMSIS/Device/xc6xxx.h
index 6e78491..00dd243 100644
--- a/component/xc6xx_drivers/Drivers/CMSIS/Device/xc6xxx.h
+++ b/component/xc6xx_drivers/Drivers/CMSIS/Device/xc6xxx.h
@@ -247,8 +247,8 @@ do { \
(__HANDLE__)->Lock = HAL_UNLOCKED; \
} while (0U)
-#if ((__ARMCC_VERSION % 1000) != 960)
- #error "Compiler build number mismatch. Required: build 960."
+#if ((__ARMCC_VERSION % 1000) != 750)
+ #error "Compiler build number mismatch. Required: build 750."
#endif
/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive
diff --git a/make_release_bin.bat b/make_release_bin.bat
new file mode 100644
index 0000000..35a3822
--- /dev/null
+++ b/make_release_bin.bat
@@ -0,0 +1,5 @@
+@echo off
+setlocal
+cd /d "%~dp0"
+powershell -ExecutionPolicy Bypass -File "%~dp0tools\make_release_bin.ps1" %*
+exit /b %errorlevel%
diff --git a/project/example/ble/ble_peripheral/app/src/app_task.c b/project/example/ble/ble_peripheral/app/src/app_task.c
index ac90d9d..7e148a9 100644
--- a/project/example/ble/ble_peripheral/app/src/app_task.c
+++ b/project/example/ble/ble_peripheral/app/src/app_task.c
@@ -538,6 +538,7 @@ static uint8_t gapc_callback(ke_msg_id_t const msgid, void const *param,
if (p_param->role == GAPM_ROLE_SLAVE) {
app_env.slave_conidx = conidx;
app_env.slave_connected = true;
+ ble_state_on_connect();
}
// Check if the received connection index is valid
if (conidx != GAP_INVALID_CONIDX) {
@@ -563,6 +564,7 @@ static uint8_t gapc_callback(ke_msg_id_t const msgid, void const *param,
if (conidx == app_env.slave_conidx) {
app_env.slave_conidx = INVALID_DATA;
app_env.slave_connected = false;
+ ble_state_on_disconnect();
app_start_advertising();
}
custom_svc_tx_char_notify = DISABLE;
diff --git a/project/example/ble/ble_peripheral/app/src/rf433.c b/project/example/ble/ble_peripheral/app/src/rf433.c
index 0546062..3dd87f7 100644
--- a/project/example/ble/ble_peripheral/app/src/rf433.c
+++ b/project/example/ble/ble_peripheral/app/src/rf433.c
@@ -8,6 +8,7 @@
#include "timeslice.h"
#include "dbg.h"
#include "rf433_decoder.h"
+#include "usr_server.h"
////用bit表示通道
//#define CH_GPIO2 0x01
//#define CH_GPIO5 0x10
@@ -215,11 +216,13 @@ void _433_fun(void)
if(match_ch & MATCH_CH2){
xc_gpio_toggle_pin(GPIO_2);
flash_ch2_state=xc_gpio_read_pin(GPIO_2);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT | BLE_STATE_DIRTY_RF433);
}
if(match_ch & MATCH_CH1){
xc_gpio_toggle_pin(GPIO_5);
flash_ch1_state=xc_gpio_read_pin(GPIO_5);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT | BLE_STATE_DIRTY_RF433);
}
@@ -231,11 +234,13 @@ void _433_fun(void)
{
xc_gpio_write_pin(GPIO_2,GPIO_PIN_RESET);
flash_ch2_state=xc_gpio_read_pin(GPIO_2);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT | BLE_STATE_DIRTY_RF433);
}
if(match_ch & MATCH_CH1)
{
xc_gpio_write_pin(GPIO_5,GPIO_PIN_RESET);
flash_ch1_state=xc_gpio_read_pin(GPIO_5);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT | BLE_STATE_DIRTY_RF433);
}
@@ -246,12 +251,14 @@ void _433_fun(void)
{
xc_gpio_write_pin(GPIO_2,GPIO_PIN_SET);
flash_ch2_state=xc_gpio_read_pin(GPIO_2);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT | BLE_STATE_DIRTY_RF433);
}
if(match_ch & MATCH_CH1)
{
xc_gpio_write_pin(GPIO_5,GPIO_PIN_SET);
flash_ch1_state=xc_gpio_read_pin(GPIO_5);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT | BLE_STATE_DIRTY_RF433);
}
diff --git a/project/example/ble/ble_peripheral/app/src/timeslice.c b/project/example/ble/ble_peripheral/app/src/timeslice.c
index c62c728..3407b55 100644
--- a/project/example/ble/ble_peripheral/app/src/timeslice.c
+++ b/project/example/ble/ble_peripheral/app/src/timeslice.c
@@ -6,6 +6,7 @@
#include "ota_flash_interface.h"
#include "ota_protocol.h"
#include "rf433_decoder.h"
+#include "usr_server.h"
TASK_COMPONENTS TaskComps[] =
{
{0, 50, 50, ble_message_process}, //蓝牙处理任务
@@ -17,6 +18,7 @@ TASK_COMPONENTS TaskComps[] =
{0, 10, 10,trigger_check_process},
{0, 300, 300, app_op_flash}, //用户数据持久化 fmc_spi_read9
{0, 300, 300, xc_ota_schedule}, //保存flash数据任务
+ {0, 1, 2, ble_state_sync_poll},
};
diff --git a/project/example/ble/ble_peripheral/app/src/uart_1.c b/project/example/ble/ble_peripheral/app/src/uart_1.c
index 93ff42d..70b7dee 100644
--- a/project/example/ble/ble_peripheral/app/src/uart_1.c
+++ b/project/example/ble/ble_peripheral/app/src/uart_1.c
@@ -1,6 +1,7 @@
#include "uart_1.h"
#include "xc_drv_gpio.h"
#include "rf433.h"
+#include "usr_server.h"
//#include "dbg.h"
ble_data_msg user_ble_data_msg;
ble_data_msg *p_ble_data_msg = NULL;
@@ -96,6 +97,7 @@ void ble_message_process(void)
scan_uart(temp);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_LIGHT | BLE_STATE_DIRTY_OUTPUT);
p_ble_data_msg = NULL;
diff --git a/project/example/ble/ble_peripheral/app/src/usr_server.c b/project/example/ble/ble_peripheral/app/src/usr_server.c
index 28b2c24..8105ad6 100644
--- a/project/example/ble/ble_peripheral/app/src/usr_server.c
+++ b/project/example/ble/ble_peripheral/app/src/usr_server.c
@@ -13,8 +13,12 @@
*/
#include "usr_server.h"
#include "uart_1.h"
+#include "xc_drv_gpio.h"
#if (BLE_APP_PRESENT)
+extern uint8_t adress_ch1_index;
+extern uint8_t adress_ch2_index;
+
uint8_t srv_user_lid = GATT_INVALID_USER_LID;
uint16_t custom_svc_start_hdl = GATT_INVALID_HDL;
uint8_t custom_svc_tx_char_notify = DISABLE;
@@ -67,6 +71,122 @@ uint16_t srv_get_hdl_from_att_idx(uint8_t idx)
return custom_svc_start_hdl + idx;
}
+static uint8_t ble_state_dirty = 0;
+static uint8_t ble_state_connect_delay = 0;
+static uint8_t ble_state_last_valid = 0;
+static uint8_t ble_state_last_output = 0;
+static uint8_t ble_state_last_ch1_count = 0;
+static uint8_t ble_state_last_ch2_count = 0;
+
+static uint8_t ble_state_output_mask(void)
+{
+ uint8_t mask = 0;
+
+ if (xc_gpio_read_pin(GPIO_5)) {
+ mask |= 0x01;
+ }
+ if (xc_gpio_read_pin(GPIO_2)) {
+ mask |= 0x02;
+ }
+ return mask;
+}
+
+void ble_state_mark_dirty(uint8_t dirty)
+{
+ ble_state_dirty |= dirty;
+}
+
+static uint8_t ble_state_fill_packet(uint8_t *data)
+{
+ data[0] = 0xA5;
+ data[1] = 0x5A;
+ data[2] = ble_state_dirty;
+ data[3] = ble_state_output_mask();
+ data[4] = 0;
+ data[5] = 0;
+ data[6] = 0;
+ data[7] = FIRMWARE_VERSION_MAJOR;
+ data[8] = FIRMWARE_VERSION_MINOR;
+ data[9] = FIRMWARE_VERSION_PATCH;
+ data[10] = adress_ch1_index;
+ data[11] = adress_ch2_index;
+ data[12] = 0;
+ data[13] = 0;
+ return 14;
+}
+
+static void ble_state_detect_changes(void)
+{
+ uint8_t output = ble_state_output_mask();
+ uint8_t ch1_count = adress_ch1_index;
+ uint8_t ch2_count = adress_ch2_index;
+
+ if (!ble_state_last_valid) {
+ ble_state_last_output = output;
+ ble_state_last_ch1_count = ch1_count;
+ ble_state_last_ch2_count = ch2_count;
+ ble_state_last_valid = 1;
+ return;
+ }
+
+ if (ble_state_last_output != output) {
+ ble_state_last_output = output;
+ ble_state_mark_dirty(BLE_STATE_DIRTY_OUTPUT);
+ }
+
+ if ((ble_state_last_ch1_count != ch1_count) ||
+ (ble_state_last_ch2_count != ch2_count)) {
+ ble_state_last_ch1_count = ch1_count;
+ ble_state_last_ch2_count = ch2_count;
+ ble_state_mark_dirty(BLE_STATE_DIRTY_RF433);
+ }
+}
+
+void ble_state_sync_poll(void)
+{
+ uint8_t data[14];
+ uint8_t len;
+ struct app_env_tag *app_env = get_app_env();
+
+ if (!app_env->slave_connected) {
+ ble_state_connect_delay = 0;
+ ble_state_last_valid = 0;
+ return;
+ }
+
+ if (ble_state_connect_delay > 0) {
+ ble_state_connect_delay--;
+ if (ble_state_connect_delay == 0) {
+ ble_state_mark_dirty(BLE_STATE_DIRTY_FULL);
+ }
+ }
+
+ ble_state_detect_changes();
+
+ if (ble_state_dirty == 0) {
+ return;
+ }
+
+ len = ble_state_fill_packet(data);
+ if (slave_send_data(data, len, CUSTOM_SVC_TX_CHAR_VAL) != INVALID_DATA) {
+ ble_state_dirty = 0;
+ }
+}
+
+void ble_state_on_connect(void)
+{
+ custom_svc_tx_char_notify = ENABLE;
+ ble_state_connect_delay = 20;
+ ble_state_mark_dirty(BLE_STATE_DIRTY_FULL);
+}
+
+void ble_state_on_disconnect(void)
+{
+ custom_svc_tx_char_notify = DISABLE;
+ ble_state_connect_delay = 0;
+ ble_state_last_valid = 0;
+}
+
// This function is called when GATT server user has initiated event send to
// peer device or if an error occurs.
__STATIC void custom_svc_cb_event_sent(uint8_t conidx, uint8_t user_lid,
@@ -126,8 +246,7 @@ __STATIC void custom_svc_cb_att_val_set(uint8_t conidx, uint8_t user_lid,
} else {
LOGI("notify ENABLE\r\n");
custom_svc_tx_char_notify = ENABLE;
- uint8_t data[] = {0x12, 0x13, 0x14};
- slave_send_data(data, sizeof(data), CUSTOM_SVC_TX_CHAR_VAL);
+ ble_state_mark_dirty(BLE_STATE_DIRTY_FULL);
}
}
}
diff --git a/project/example/ble/ble_peripheral/app/src/usr_server.h b/project/example/ble/ble_peripheral/app/src/usr_server.h
index 19567ec..353e955 100644
--- a/project/example/ble/ble_peripheral/app/src/usr_server.h
+++ b/project/example/ble/ble_peripheral/app/src/usr_server.h
@@ -35,6 +35,20 @@ enum cust_svc
CUSTOM_SVC_TX_CHAR_VAL,
CUSTOM_SVC_TX_CHAR_CFG,
};
+
+#define FIRMWARE_VERSION_MAJOR 1
+#define FIRMWARE_VERSION_MINOR 3
+#define FIRMWARE_VERSION_PATCH 0
+
+#define BLE_STATE_DIRTY_FULL 0x01
+#define BLE_STATE_DIRTY_OUTPUT 0x02
+#define BLE_STATE_DIRTY_RF433 0x04
+#define BLE_STATE_DIRTY_LIGHT 0x08
+
uint8_t custom_svc_add(void);
uint8_t slave_send_data(uint8_t *data, uint8_t len, uint8_t att_idx);
+void ble_state_mark_dirty(uint8_t dirty);
+void ble_state_sync_poll(void);
+void ble_state_on_connect(void);
+void ble_state_on_disconnect(void);
#endif // _USR_SERVER_H_
diff --git a/project/example/ble/ble_peripheral/mdk/app.bin b/project/example/ble/ble_peripheral/mdk/app.bin
index b3912ff..354e6ae 100644
Binary files a/project/example/ble/ble_peripheral/mdk/app.bin and b/project/example/ble/ble_peripheral/mdk/app.bin differ
diff --git a/project/example/ble/ble_peripheral/mdk/ble_peripheral.bin b/project/example/ble/ble_peripheral/mdk/ble_peripheral.bin
index 1499bfb..14ca2d3 100644
Binary files a/project/example/ble/ble_peripheral/mdk/ble_peripheral.bin and b/project/example/ble/ble_peripheral/mdk/ble_peripheral.bin differ
diff --git a/project/example/ble/ble_peripheral/mdk/ble_peripheral.uvprojx b/project/example/ble/ble_peripheral/mdk/ble_peripheral.uvprojx
index 7fd1e25..42076a6 100644
--- a/project/example/ble/ble_peripheral/mdk/ble_peripheral.uvprojx
+++ b/project/example/ble/ble_peripheral/mdk/ble_peripheral.uvprojx
@@ -10,7 +10,7 @@
ble-sdk-xip
0x4
ARM-ADS
- 5060960::V5.06 update 7 (build 960)::.\ARMCC
+ 5060750::V5.06 update 6 (build 750)::.\ARMCC
0
diff --git a/project/example/ble/ble_peripheral/mdk/output_bin/ble_peripheral.bin b/project/example/ble/ble_peripheral/mdk/output_bin/ble_peripheral.bin
index 1499bfb..14ca2d3 100644
Binary files a/project/example/ble/ble_peripheral/mdk/output_bin/ble_peripheral.bin and b/project/example/ble/ble_peripheral/mdk/output_bin/ble_peripheral.bin differ
diff --git a/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_aes.bin b/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_aes.bin
index 555f857..d4b98c2 100644
Binary files a/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_aes.bin and b/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_aes.bin differ
diff --git a/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_double.bin b/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_double.bin
index 54c62e0..90e9de7 100644
Binary files a/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_double.bin and b/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_double.bin differ
diff --git a/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_single.bin b/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_single.bin
index 6daf898..487bdf2 100644
Binary files a/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_single.bin and b/project/example/ble/ble_peripheral/mdk/output_bin/ota_data_single.bin differ
diff --git a/project/example/ble/ble_peripheral/mdk/output_tool/Double_ota/ge_ota.bat b/project/example/ble/ble_peripheral/mdk/output_tool/Double_ota/ge_ota.bat
index c9b9fbc..63637b7 100644
--- a/project/example/ble/ble_peripheral/mdk/output_tool/Double_ota/ge_ota.bat
+++ b/project/example/ble/ble_peripheral/mdk/output_tool/Double_ota/ge_ota.bat
@@ -68,5 +68,7 @@ set Ota_use_bin=.\output_bin\ota_data_double.bin
copy %Download_bin% .\
+call "%~dp0..\..\..\..\..\..\..\make_release_bin.bat"
+if errorlevel 1 exit /b 1
diff --git a/project_info.ini b/project_info.ini
new file mode 100644
index 0000000..8461e30
--- /dev/null
+++ b/project_info.ini
@@ -0,0 +1,7 @@
+PRODUCT=HPW422
+VERSION=V1.3
+CHIP=XC6517
+
+# Used only for checksum generation by tools/offline_burn/Xinc_mac_tool.exe.
+OFFLINE_MAC=40-ab-00-cd-01-01
+OFFLINE_COUNT=1000000
diff --git a/release/online/HPW422_V1.3_XC6517_7E2FEEA0.bin b/release/online/HPW422_V1.3_XC6517_7E2FEEA0.bin
new file mode 100644
index 0000000..14ca2d3
Binary files /dev/null and b/release/online/HPW422_V1.3_XC6517_7E2FEEA0.bin differ
diff --git a/release/ota/HPW422_V1.3_XC6517_7E2FEEA0_OTA.bin b/release/ota/HPW422_V1.3_XC6517_7E2FEEA0_OTA.bin
new file mode 100644
index 0000000..d4b98c2
Binary files /dev/null and b/release/ota/HPW422_V1.3_XC6517_7E2FEEA0_OTA.bin differ
diff --git a/tools/make_release_bin.ps1 b/tools/make_release_bin.ps1
new file mode 100644
index 0000000..8e47f85
--- /dev/null
+++ b/tools/make_release_bin.ps1
@@ -0,0 +1,148 @@
+param(
+ [string]$ConfigPath,
+ [string]$Mac,
+ [string]$Count,
+ [string]$OnlineBinPath,
+ [string]$OtaBinPath,
+ [switch]$NoOta
+)
+
+Set-StrictMode -Version 2.0
+$ErrorActionPreference = "Stop"
+
+$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
+$repoRoot = Split-Path -Parent $scriptDir
+
+if ([string]::IsNullOrWhiteSpace($ConfigPath)) {
+ $ConfigPath = Join-Path $repoRoot "project_info.ini"
+}
+
+function Read-ProjectInfo {
+ param([string]$Path)
+
+ if (-not (Test-Path -LiteralPath $Path)) {
+ throw "Config file not found: $Path"
+ }
+
+ $result = @{}
+ foreach ($line in Get-Content -LiteralPath $Path) {
+ $trimmed = $line.Trim()
+ if ($trimmed.Length -eq 0 -or $trimmed.StartsWith("#") -or $trimmed.StartsWith(";")) {
+ continue
+ }
+
+ $parts = $trimmed.Split("=", 2)
+ if ($parts.Count -ne 2) {
+ continue
+ }
+
+ $key = $parts[0].Trim()
+ $value = $parts[1].Trim()
+ if ($key.Length -gt 0) {
+ $result[$key] = $value
+ }
+ }
+
+ return $result
+}
+
+function Require-Value {
+ param(
+ [hashtable]$Info,
+ [string]$Key
+ )
+
+ if (-not $Info.ContainsKey($Key) -or [string]::IsNullOrWhiteSpace([string]$Info[$Key])) {
+ throw "Missing required config value: $Key"
+ }
+
+ return [string]$Info[$Key]
+}
+
+$info = Read-ProjectInfo -Path $ConfigPath
+$product = Require-Value -Info $info -Key "PRODUCT"
+$version = Require-Value -Info $info -Key "VERSION"
+$chip = Require-Value -Info $info -Key "CHIP"
+
+if ([string]::IsNullOrWhiteSpace($Mac)) {
+ if ($info.ContainsKey("OFFLINE_MAC")) {
+ $Mac = [string]$info["OFFLINE_MAC"]
+ } else {
+ $Mac = "40-ab-00-cd-01-01"
+ }
+}
+
+if ([string]::IsNullOrWhiteSpace($Count)) {
+ if ($info.ContainsKey("OFFLINE_COUNT")) {
+ $Count = [string]$info["OFFLINE_COUNT"]
+ } else {
+ $Count = "1000000"
+ }
+}
+
+if ([string]::IsNullOrWhiteSpace($OnlineBinPath)) {
+ $OnlineBinPath = Join-Path $repoRoot "project\example\ble\ble_peripheral\mdk\ble_peripheral.bin"
+}
+
+if ([string]::IsNullOrWhiteSpace($OtaBinPath)) {
+ $OtaBinPath = Join-Path $repoRoot "project\example\ble\ble_peripheral\mdk\output_bin\ota_data_aes.bin"
+}
+
+$offlineDir = Join-Path $repoRoot "tools\offline_burn"
+$offlineTool = Join-Path $offlineDir "Xinc_mac_tool.exe"
+$offlineInput = Join-Path $offlineDir "download.bin"
+$releaseDir = Join-Path $repoRoot "release"
+$onlineReleaseDir = Join-Path $releaseDir "online"
+$otaReleaseDir = Join-Path $releaseDir "ota"
+
+if (-not (Test-Path -LiteralPath $OnlineBinPath)) {
+ throw "Online BIN not found: $OnlineBinPath"
+}
+
+if (-not (Test-Path -LiteralPath $offlineTool)) {
+ throw "Offline checksum tool not found: $offlineTool"
+}
+
+Copy-Item -LiteralPath $OnlineBinPath -Destination $offlineInput -Force
+
+Push-Location $offlineDir
+try {
+ & $offlineTool $Mac $Count
+ if ($LASTEXITCODE -ne 0) {
+ throw "Xinc_mac_tool.exe failed with exit code $LASTEXITCODE"
+ }
+} finally {
+ Pop-Location
+}
+
+$namePattern = "^" + [regex]::Escape($Mac) + "_([0-9A-Fa-f]{8})_" + [regex]::Escape($Count) + "\.bin$"
+$generated = Get-ChildItem -LiteralPath $offlineDir -File -Filter "$Mac`_*.bin" |
+ Where-Object { $_.Name -match $namePattern } |
+ Sort-Object LastWriteTimeUtc -Descending |
+ Select-Object -First 1
+
+if ($null -eq $generated) {
+ throw "Checksum output was not found in $offlineDir"
+}
+
+$checksum = ([regex]::Match($generated.Name, $namePattern)).Groups[1].Value.ToUpperInvariant()
+
+New-Item -ItemType Directory -Force -Path $onlineReleaseDir | Out-Null
+$onlineName = "{0}_{1}_{2}_{3}.bin" -f $product, $version, $chip, $checksum
+$onlineReleasePath = Join-Path $onlineReleaseDir $onlineName
+Copy-Item -LiteralPath $OnlineBinPath -Destination $onlineReleasePath -Force
+
+Write-Host "Checksum source: $($generated.FullName)"
+Write-Host "Online BIN: $onlineReleasePath"
+
+if (-not $NoOta) {
+ if (Test-Path -LiteralPath $OtaBinPath) {
+ New-Item -ItemType Directory -Force -Path $otaReleaseDir | Out-Null
+ $otaName = "{0}_{1}_{2}_{3}_OTA.bin" -f $product, $version, $chip, $checksum
+ $otaReleasePath = Join-Path $otaReleaseDir $otaName
+ Copy-Item -LiteralPath $OtaBinPath -Destination $otaReleasePath -Force
+ Write-Host "OTA BIN: $otaReleasePath"
+ } else {
+ Write-Warning "OTA BIN not found, skipped: $OtaBinPath"
+ }
+}
diff --git a/tools/offline_burn/Mcu_download.bin b/tools/offline_burn/Mcu_download.bin
new file mode 100644
index 0000000..4a56475
Binary files /dev/null and b/tools/offline_burn/Mcu_download.bin differ
diff --git a/tools/offline_burn/README.md b/tools/offline_burn/README.md
new file mode 100644
index 0000000..1691e05
--- /dev/null
+++ b/tools/offline_burn/README.md
@@ -0,0 +1,14 @@
+# Offline checksum tool
+
+This folder keeps the original XC6517 offline burn helper used only to calculate
+the checksum segment for release file names.
+
+Normal release flow:
+
+1. Build the Keil project and generate `mdk\ble_peripheral.bin`.
+2. Run `tools\make_release_bin.ps1` from the repository root.
+3. The script copies `ble_peripheral.bin` to `download.bin`, runs
+ `Xinc_mac_tool.exe`, extracts the checksum from the generated offline file
+ name, then copies the real online burn file to `release\online`.
+
+Do not use the generated offline BIN as the online burn file.
diff --git a/tools/offline_burn/Readme.txt b/tools/offline_burn/Readme.txt
new file mode 100644
index 0000000..aa84fc8
--- /dev/null
+++ b/tools/offline_burn/Readme.txt
@@ -0,0 +1,2 @@
+如果要烧录与烧录器最开始同一MAC的程序,需要先烧录erase.bin
+MCU烧录Mcu_download.bin文件
diff --git a/tools/offline_burn/STM32F0308_Discovery.hex b/tools/offline_burn/STM32F0308_Discovery.hex
new file mode 100644
index 0000000..20be53a
--- /dev/null
+++ b/tools/offline_burn/STM32F0308_Discovery.hex
@@ -0,0 +1,163 @@
+:020000040800F2
+:1000000020040020D50000085D020008E30100087C
+:1000100000000000000000000000000000000000E0
+:10002000000000000000000000000000CD030008F8
+:100030000000000000000000B10200086904000890
+:10004000E7000008E7000008E7000008E7000008F4
+:10005000E7000008E7000008E7000008E7000008E4
+:10006000E7000008E7000008E7000008E7000008D4
+:10007000E7000008E7000008E7000008E7000008C4
+:10008000E7000008E700000800000000E7000008A3
+:10009000E7000008E7000008E7000008E7000008A4
+:1000A000E7000008E7000008E7000008CD040008AA
+:1000B000E700000800000000E70000080000000062
+:1000C0000348854600F02AF800480047C5080008A4
+:1000D000200400200448804704480047FEE7FEE76C
+:1000E000FEE7FEE7FEE7FEE76D040008C10000083A
+:1000F00030B50B46014600202022012409E00D46C0
+:10010000D5409D4205D31D469540491B2546954047
+:1001100040191546521E002DF1DC30BD064C01255C
+:10012000064E05E0E36807CC2B430C3C984710349F
+:10013000B442F7D3FFF7C8FFC4090008E409000878
+:10014000F0B50022032501230C6893401C409C421B
+:100150002AD10C79012C01D0022C12D187685400CD
+:100160002E46A640B74387604E79A6408468264352
+:10017000866084889C43848084888B7993401C4368
+:100180008480066853002C469C40A64306600E7986
+:1001900007689E403E430660C668A643C660CC79A9
+:1001A0009C40C3681C43C460521C102ACBD3F0BDD2
+:1001B0004B07DB0E9A40C90810B589000818016A80
+:1001C0000F249C40A1430162016A1143016210BDEA
+:1001D0000246128A00200A4200D001207047816145
+:1001E0007047FEE7FEB50121880400F063F80121A5
+:1001F000480400F05FF8012468460094047100256B
+:1002000085710226C671032141710927FF066946DF
+:100210003846FFF795FF102000906846047144713E
+:10022000C57169463846FFF78BFF0A48009068465B
+:1002300005714471C47169463846FFF781FF68460D
+:10024000009605714471C47169460348FFF778FF51
+:10025000FEBD0000C26600000004004870470000B8
+:1002600030B5827801240178002A15D08B080E4A17
+:100270009B009A1813688907C90EFF258D40AB4370
+:100280004578AD072D0E8D401D4315600078C006E2
+:10029000C00E8440054804E0C806C00E84400348F0
+:1002A0008030046030BD000000E400E000E100E0C8
+:1002B00070470000044A0029516901D0014300E061
+:1002C000814351617047000000100240044A002938
+:1002D000916901D0014300E08143916170470000C2
+:1002E00000100240F8B5334E044670680C21324DC0
+:1002F000084003D0042801D0082801D0256012E06E
+:10030000716870680122890212040F0F1040BF1C2F
+:1003100000281CD0F06A0107090F2846491CFFF786
+:10032000E7FE784320607068244B0006000F1A5CDB
+:1003300020680146D140616072685205520F9A5C94
+:10034000D140A160326BD20505D41D4A09E01D4899
+:1003500047432760E7E77268520401D44A0800E087
+:100360008A08E260326B184B520603D4164A1232E6
+:10037000226100E02361326BD20601D4656100E0A6
+:100380006061326B92070FD0316B8907890F0129A9
+:100390000CD0306B8007800F022809D0306BC0432F
+:1003A000800700D1A561F8BDA161F8BDA061F8BDCD
+:1003B000A361F8BD0010024000127A000000002086
+:1003C000809FD50000093D000080000070470000BC
+:1003D0001CB50023224800930193016801221204F6
+:1003E0001143016051000524240302680A40019270
+:1003F000009A521C0092019A002A02D1009AA2424D
+:10040000F3D10168890328D501210191154A1121F1
+:100410001160416841604168416041683F221204B7
+:100420009143416041681122120411434160016807
+:10043000012212061143016001688901FCD541685F
+:100440008908890041604168022211434160416886
+:100450000907890F0229FAD11CBD01931CBD0000B8
+:1004600000100240002002407047000010B5144800
+:1004700001680122114301604168124A1140416044
+:100480000168114A11400160016801229204914300
+:10049000016041683F22120491434160C16A090929
+:1004A0000901C162016BFF22543291430163416B28
+:1004B00049084900416300218160FFF789FF10BDB1
+:1004C000001002400CB8FFF8FFFFF6FE10B50B4C11
+:1004D0000949204600F06FF800280CD0204600F0B3
+:1004E000E1F80146204600F0E1F88021204600F0C6
+:1004F0005BF80028F9D010BD050105000038014067
+:10050000F0B5012189B04804FFF7D4FE012188032A
+:10051000FFF7DCFE092001220221C006FFF748FE9A
+:10052000092001220321C006FFF742FE0C26022704
+:1005300068460096077103214171002484710125EA
+:10054000C57109206946C006FFF7FAFDE120049451
+:1005500005940694089440020C4C039003A9079656
+:10056000204600F059F801220949204600F03FF8E2
+:100570000121204600F00EF81B21684601724772E7
+:10058000857202A8FFF76CFE09B0F0BD003801408B
+:10059000050105000029016802D00122114301E094
+:1005A00049084900016070470246D26900200A42AA
+:1005B00000D00120704730B50A04130E01252A46E9
+:1005C00000248A40012B0ED0022B0ED08368090C28
+:1005D0001340C0698D402840002B02D0002800D075
+:1005E0000124204630BD0368F1E74368EFE710B50A
+:1005F0000B041C0E01238B40022C02D0032C02D0D2
+:1006000002E0001D00E008300168002A01D0194313
+:1006100000E09943016010BD30B50446006887B022
+:100620000D464008400020606068032109038843AC
+:10063000A9680143616020681749EA680840696851
+:1006400011432A69024311432160A0680321090272
+:10065000884369690143A1606846FFF743FE0F487C
+:10066000844201D1069800E00298216809042968B3
+:1006700000D54000FFF73CFD2A6852088A4200D8A6
+:10068000401C2168090404D50107054A490F1040A0
+:100690000843A08107B030BDF3E9FFFF00380140F7
+:1006A000F0FF0000808CC005C00D7047C905C90D62
+:1006B000018570470FB410B503A9044B044A029892
+:1006C00000F018F810BC08BC04B01847A1080008D6
+:1006D0001800002002E008C8121F08C1002AFAD141
+:1006E00070477047002001E001C1121F002AFBD1B2
+:1006F00070470000FFB58DB00446002506E02528B0
+:100700000AD0109A0F999047641C6D1C207800281D
+:10071000F5D1284611B0F0BD00270121484A0097C5
+:1007200000E00743641C23780846203B98401042B1
+:10073000F7D120782E2817D1042007436078641C55
+:100740002A280CD10E98641C02C800910E900BE070
+:1007500000990A22514330394018641C00902078D7
+:10076000014630390929F3D920780028D1D06428EE
+:1007700008D0692806D075281ED0109A0F99904786
+:100780006D1C5BE00A200E99019001C90E910028B2
+:1007900002DA40422D2102E0390504D52B216A46B8
+:1007A0001172012103E0F90704D02021F7E70BAE15
+:1007B0000B910DE00021FAE70A200E99019001C982
+:1007C0000E91F7E70199FFF793FC3031761E3170F7
+:1007D0000028F7D103A8801B20300190780701D5AD
+:1007E000009801E0012000900199884201DD401A43
+:1007F00000E000200027009006E002A8109AC05DEB
+:100800000F9990476D1C7F1C0B988742F5DB04E025
+:10081000109A30200F9990476D1C0099481E009047
+:100820000029F5DC05E03078109A761C0F99904786
+:100830006D1C0199481E01900029F4DC641C65E7D9
+:1008400009280100FEB501218804FFF733FD0121CD
+:100850004804FFF72FFD09200121C006FFF7BFFC68
+:100860000D48009001266846067100278771022412
+:10087000C4710325457109206946C006FFF760FC75
+:100880006846009406718771C471457169460348D2
+:10089000FFF756FCFEBD0000C062000000040048E7
+:1008A00070B5074D0446C1B22846FFF7FFFE402150
+:1008B0002846FFF779FE0028F9D0204670BD0000D9
+:1008C00000380140FFF71CFE19A0FFF7F3FE21A03E
+:1008D000FFF7F0FE28A0FFF7EDFEFFF783FC0927E6
+:1008E0002F4EFF062F4D00243046401EFDD12EA076
+:1008F0002A686968FFF7DEFE02213846FFF768FCC8
+:10090000002804D06C602868401C286006E02C6039
+:100910006868401C68601E2802DA20461E28E3DB57
+:10092000FFF790FF10213846FFF759FCFEE7000063
+:10093000BBB6D3ADCAB9D3C3D4B4B5D859442D537B
+:10094000544D3332463033304634BACBD0C4B0E5A0
+:100950000D0A0000CDF8B5EAB5D8D6B76874747042
+:100960003A2F2F7663632D676E642E74616F626118
+:100970006F2E636F6D0D0A004D4355B4AEBFDABDE7
+:10098000D3CAD5B5BDD0C5CFA2BAF3B7B4C0A1BD47
+:10099000D3CAD5B5BDB5C4D0C5CFA20D0A000000DD
+:1009A000FFFF0F001000002068656172745F696EC0
+:1009B00076657273653A25643A2068656172743AA7
+:1009C00025640A00E4090008000000201C00000063
+:1009D000D4060008000A00081C00002004040000DF
+:1009E000E406000800000000010203040102030401
+:1009F00006070809000000000000000000000000D9
+:04000005080000C12E
+:00000001FF
diff --git a/tools/offline_burn/Xinc_mac_tool.exe b/tools/offline_burn/Xinc_mac_tool.exe
new file mode 100644
index 0000000..b14adf2
Binary files /dev/null and b/tools/offline_burn/Xinc_mac_tool.exe differ
diff --git a/tools/offline_burn/Z_ReadMe.png b/tools/offline_burn/Z_ReadMe.png
new file mode 100644
index 0000000..ffeff2d
Binary files /dev/null and b/tools/offline_burn/Z_ReadMe.png differ
diff --git a/tools/offline_burn/Z_Xinc_tool.bat b/tools/offline_burn/Z_Xinc_tool.bat
new file mode 100644
index 0000000..1478b84
--- /dev/null
+++ b/tools/offline_burn/Z_Xinc_tool.bat
@@ -0,0 +1,2 @@
+Xinc_mac_tool.exe 40-ab-00-cd-01-01 1000000
+REM pause
\ No newline at end of file
diff --git a/tools/offline_burn/erase.bin b/tools/offline_burn/erase.bin
new file mode 100644
index 0000000..c2c1d63
Binary files /dev/null and b/tools/offline_burn/erase.bin differ
diff --git a/tools/offline_burn/offline.bin b/tools/offline_burn/offline.bin
new file mode 100644
index 0000000..6de3c54
Binary files /dev/null and b/tools/offline_burn/offline.bin differ
diff --git a/tools/offline_burn/ramboot.bin b/tools/offline_burn/ramboot.bin
new file mode 100644
index 0000000..c007b51
Binary files /dev/null and b/tools/offline_burn/ramboot.bin differ