Skip to content

Commit 6782cc1

Browse files
committed
feat: Allow fw to reboot-to-bootloader when special sequence is sent to I2C, addr 0x39
1 parent 8519e05 commit 6782cc1

3 files changed

Lines changed: 51 additions & 6 deletions

File tree

firmware/userapp/Core/Inc/slave.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ extern "C" {
99

1010
#define REG_MAP_SIZE 0x25
1111

12+
// I2C1 main slave address (unshifted)
13+
#define MAX6958_SLAVE_I2C_ADDR 0x38
14+
// Secondary I2C1 own-address (7-bit, unshifted): writing BOOTLOADER_TRIGGER_MAGIC
15+
// here reboots straight into the STM32 system bootloader (DFU), letting the
16+
// board be reflashed without physical button/SWD access.
17+
#define BOOTLOADER_TRIGGER_I2C_ADDR 0x39
18+
// Magic bytes, MSB first: 0xB0 0x07 0xB0 0x07 ("B007 B007" / "BOOT BOOT")
19+
#define BOOTLOADER_TRIGGER_MAGIC 0xB007B007UL
20+
1221
void Slave_Init(void);
1322

1423
uint8_t Slave_RegRead(uint8_t addr);

firmware/userapp/Core/Src/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,10 @@ static void MX_I2C1_Init(void)
219219
/* USER CODE END I2C1_Init 1 */
220220
hi2c1.Instance = I2C1;
221221
hi2c1.Init.Timing = 0x00C12166;
222-
hi2c1.Init.OwnAddress1 = 112;
222+
hi2c1.Init.OwnAddress1 = (MAX6958_SLAVE_I2C_ADDR << 1);
223223
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
224-
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
225-
hi2c1.Init.OwnAddress2 = 0;
224+
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
225+
hi2c1.Init.OwnAddress2 = (BOOTLOADER_TRIGGER_I2C_ADDR << 1);
226226
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
227227
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
228228
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;

firmware/userapp/Core/Src/slave.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "slave.h"
2+
#include "bootloader.h"
23

34
extern I2C_HandleTypeDef hi2c1;
45

@@ -9,6 +10,9 @@ static uint8_t reg_index = 0; // Current write address
910
static uint32_t error = HAL_OK;
1011
static uint8_t error_state = 0;
1112

13+
static uint8_t bootloader_magic_buf[4] = {0};
14+
static uint8_t receiving_boot_magic = 0; // Set while a BOOTLOADER_TRIGGER_I2C_ADDR write is in flight
15+
1216
void Slave_Start(void);
1317

1418
/**
@@ -43,7 +47,17 @@ void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, ui
4347
// Check if master->slave transmission
4448
if (TransferDirection == I2C_DIRECTION_TRANSMIT)
4549
{
46-
HAL_StatusTypeDef ret = HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, &reg_index, 1, I2C_NEXT_FRAME);
50+
HAL_StatusTypeDef ret;
51+
52+
// AddrMatchCode is delivered pre-shifted by 1 (same convention as
53+
// Init.OwnAddress1/OwnAddress2), not the raw 7-bit address.
54+
if (AddrMatchCode == (BOOTLOADER_TRIGGER_I2C_ADDR << 1)) {
55+
receiving_boot_magic = 1;
56+
ret = HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, bootloader_magic_buf, sizeof(bootloader_magic_buf), I2C_LAST_FRAME);
57+
} else {
58+
ret = HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, &reg_index, 1, I2C_NEXT_FRAME);
59+
}
60+
4761
if (ret != HAL_OK) {
4862
Error_Handler();
4963
}
@@ -65,6 +79,20 @@ void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
6579
return;
6680
}
6781

82+
if (receiving_boot_magic) {
83+
receiving_boot_magic = 0;
84+
85+
uint32_t magic = ((uint32_t)bootloader_magic_buf[0] << 24)
86+
| ((uint32_t)bootloader_magic_buf[1] << 16)
87+
| ((uint32_t)bootloader_magic_buf[2] << 8)
88+
| (uint32_t)bootloader_magic_buf[3];
89+
90+
if (magic == BOOTLOADER_TRIGGER_MAGIC) {
91+
resetToSystemBootLoader(); // Does not return
92+
}
93+
return;
94+
}
95+
6896
if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, &register_map[reg_index++], 1, I2C_NEXT_FRAME) != HAL_OK) {
6997
Error_Handler();
7098
}
@@ -105,9 +133,17 @@ void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
105133
default:
106134
Error_Handler();
107135
}
108-
136+
109137
hi2c->ErrorCode = 0;
110-
Slave_HandleComplete();
138+
139+
if (receiving_boot_magic) {
140+
// Truncated bootloader-trigger write; discard it rather than
141+
// let stale reg_index state be mistaken for a completed
142+
// register-map transfer below.
143+
receiving_boot_magic = 0;
144+
} else {
145+
Slave_HandleComplete();
146+
}
111147

112148
Slave_Start();
113149

0 commit comments

Comments
 (0)