11#include "slave.h"
22#include "bootloader.h"
3+ #include "postcodes.h"
34
45extern I2C_HandleTypeDef hi2c1 ;
56
67static uint8_t register_map [REG_MAP_SIZE ] = {0 }; // Register map storage
78static uint8_t new_segment_available = 0 ;
8- static uint8_t reg_index = 0 ; // Current write address
9+ static uint8_t reg_index = 0 ;
910
1011static uint32_t error = HAL_OK ;
1112static uint8_t error_state = 0 ;
1213
1314static uint8_t bootloader_magic_buf [4 ] = {0 };
1415static uint8_t receiving_boot_magic = 0 ; // Set while a BOOTLOADER_TRIGGER_I2C_ADDR write is in flight
1516
17+ static uint8_t rx_scratch [REG_MAP_SIZE + 1 ]; // [0]=target register, [1..]=data
18+
19+ // Set by ISR callbacks, checked by Slave_Poll() from the main loop.
20+ static volatile uint8_t need_restart = 0 ;
21+
1622void Slave_Start (void );
1723
1824/**
@@ -24,6 +30,14 @@ void Slave_Init(void)
2430 Slave_Start ();
2531}
2632
33+ void Slave_Poll (void )
34+ {
35+ if (need_restart ) {
36+ need_restart = 0 ;
37+ Slave_Start ();
38+ }
39+ }
40+
2741void Slave_Start (void )
2842{
2943 while (HAL_I2C_GetState (& hi2c1 ) == HAL_I2C_STATE_BUSY ) {}
@@ -36,7 +50,6 @@ void Slave_Start(void)
3650 HAL_I2C_EnableListen_IT (& hi2c1 );
3751}
3852
39-
4053void HAL_I2C_AddrCallback (I2C_HandleTypeDef * hi2c , uint8_t TransferDirection , uint16_t AddrMatchCode )
4154{
4255 if (hi2c != & hi2c1 ) {
@@ -55,11 +68,12 @@ void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, ui
5568 receiving_boot_magic = 1 ;
5669 ret = HAL_I2C_Slave_Seq_Receive_IT (& hi2c1 , bootloader_magic_buf , sizeof (bootloader_magic_buf ), I2C_LAST_FRAME );
5770 } else {
58- ret = HAL_I2C_Slave_Seq_Receive_IT (& hi2c1 , & reg_index , 1 , I2C_NEXT_FRAME );
71+ // Single call for the whole transaction
72+ ret = HAL_I2C_Slave_Seq_Receive_IT (& hi2c1 , rx_scratch , sizeof (rx_scratch ), I2C_NEXT_FRAME );
5973 }
6074
6175 if (ret != HAL_OK ) {
62- Error_Handler () ;
76+ need_restart = 1 ;
6377 }
6478 }
6579}
@@ -70,7 +84,29 @@ void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
7084 return ;
7185 }
7286
73- Slave_Start ();
87+ need_restart = 1 ;
88+ }
89+
90+ static void Slave_FlushRxScratch (void )
91+ {
92+ if (hi2c1 .pBuffPtr >= rx_scratch && hi2c1 .pBuffPtr <= rx_scratch + sizeof (rx_scratch )) {
93+ uint16_t received = (uint16_t )(hi2c1 .pBuffPtr - rx_scratch );
94+
95+ if (received >= 1 ) {
96+ uint8_t start_addr = rx_scratch [0 ];
97+ uint16_t data_len = received - 1 ;
98+
99+ for (uint16_t i = 0 ; i < data_len ; i ++ ) {
100+ register_map [(start_addr + i ) % REG_MAP_SIZE ] = rx_scratch [1 + i ];
101+ }
102+ reg_index = (uint8_t )(start_addr + data_len );
103+
104+ // Did the received range contain Segment register?
105+ if (start_addr <= REG_Segments && REG_Segments < start_addr + data_len ) {
106+ new_segment_available = 1 ;
107+ }
108+ }
109+ }
74110}
75111
76112void HAL_I2C_SlaveRxCpltCallback (I2C_HandleTypeDef * hi2c )
@@ -93,9 +129,7 @@ void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
93129 return ;
94130 }
95131
96- if (HAL_I2C_Slave_Seq_Receive_IT (hi2c , & register_map [reg_index ++ ], 1 , I2C_NEXT_FRAME ) != HAL_OK ) {
97- Error_Handler ();
98- }
132+ Slave_FlushRxScratch ();
99133}
100134
101135void HAL_I2C_AbortCpltCallback (I2C_HandleTypeDef * hi2c )
@@ -104,16 +138,9 @@ void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c)
104138 return ;
105139 }
106140
107- Error_Handler ();
108- }
109-
110- void Slave_HandleComplete ()
111- {
112- if (reg_index == 0x26 /*&& (register_map[0x24] & 0x0F) > 0*/ )
113- new_segment_available = 1 ;
141+ need_restart = 1 ;
114142}
115143
116-
117144void HAL_I2C_ErrorCallback (I2C_HandleTypeDef * hi2c )
118145{
119146 if (hi2c != & hi2c1 ) {
@@ -122,31 +149,31 @@ void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
122149
123150 error = HAL_I2C_GetError (& hi2c1 );
124151
125- switch (error ) {
126- case HAL_I2C_ERROR_AF :
127- __HAL_I2C_CLEAR_FLAG (hi2c , I2C_FLAG_AF );
128- break ;
129- case HAL_I2C_ERROR_BERR :
130- __HAL_I2C_CLEAR_FLAG (hi2c , I2C_FLAG_BERR );
131- error_state = 1 ;
132- break ;
133- default :
134- Error_Handler ();
135- }
136-
152+ // error is a bitmask
153+ if (error & HAL_I2C_ERROR_AF ) {
154+ __HAL_I2C_CLEAR_FLAG (hi2c , I2C_FLAG_AF );
155+ }
156+ if (error & HAL_I2C_ERROR_ARLO ) {
157+ __HAL_I2C_CLEAR_FLAG (hi2c , I2C_FLAG_ARLO );
158+ }
159+ if (error & HAL_I2C_ERROR_OVR ) {
160+ __HAL_I2C_CLEAR_FLAG (hi2c , I2C_FLAG_OVR );
161+ }
162+ if (error & HAL_I2C_ERROR_BERR ) {
163+ __HAL_I2C_CLEAR_FLAG (hi2c , I2C_FLAG_BERR );
164+ error_state = 1 ;
165+ }
166+
137167 hi2c -> ErrorCode = 0 ;
138168
139169 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.
170+ // Truncated bootloader-trigger write; discard it.
143171 receiving_boot_magic = 0 ;
144172 } else {
145- Slave_HandleComplete ();
173+ Slave_FlushRxScratch ();
146174 }
147175
148- Slave_Start ();
149-
176+ need_restart = 1 ;
150177}
151178
152179uint8_t Slave_RegRead (uint8_t addr ) { return register_map [addr % REG_MAP_SIZE ]; }
0 commit comments