Skip to content

Commit a18d00f

Browse files
committed
projects: max78000: reset ADIS robustly on boot
The ADIS keeps power across an MCU reset/reflash, so the coprocessor routinely starts against a chip left in whatever state the previous run (or a mid-frame debugger halt) left it in. A single blind software reset does not reliably recover a wedged part -- if the ADIS SPI bit counter was left mid-word, the reset write lands byte-misaligned and is ignored, leaving DATA_CNTR stuck at 0xFFFF with zero data until a hard power cycle. Re-frame the SPI word boundary with CS-framed dummy reads, issue the reset, then verify the part is actually sampling (DATA_CNTR readable, not 0xFFFF, and advancing). Retry a bounded number of times before failing to the ARM as any other init error. Assisted-by: Claude Opus 4.8 Signed-off-by: Victor Pascu <victor.pascu@analog.com>
1 parent 3c14fe7 commit a18d00f

1 file changed

Lines changed: 59 additions & 3 deletions

File tree

projects/max78000/src/examples/imu_dual_core/imu_dual_core_example_riscv.c

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,56 @@ static struct adis_init_param adis_ip = {
165165
.dev_id = ADIS16577_2,
166166
};
167167

168+
/* Software-reset attempts before reporting an error to the ARM. */
169+
#define IMU_ADIS_RESET_ATTEMPTS 3u
170+
171+
/*
172+
* The ADIS keeps power across an MCU reset/reflash, so it can come up wedged
173+
* (DATA_CNTR stuck at 0xFFFF, data 0) where only a hard power cycle recovers it.
174+
* Confirm it is sampling: DATA_CNTR must be readable, not 0xFFFF, and advancing.
175+
* Returns 0 when sampling, -EIO otherwise.
176+
*/
177+
static int imu_adis_check_sampling(struct adis_dev *dev)
178+
{
179+
uint32_t dc0 = 0, dc1 = 0;
180+
int ret;
181+
182+
ret = adis_read_data_cntr(dev, &dc0);
183+
if (ret)
184+
return ret;
185+
186+
no_os_mdelay(2); /* > one 2 kHz ODR period */
187+
188+
ret = adis_read_data_cntr(dev, &dc1);
189+
if (ret)
190+
return ret;
191+
192+
if (dc0 == 0xFFFF || dc0 == dc1)
193+
return -EIO;
194+
195+
return 0;
196+
}
197+
198+
/*
199+
* Re-align the ADIS SPI frame before a reset: an MCU reset mid-transaction can
200+
* leave the ADIS bit counter mid-word, so the next command lands misaligned. Each
201+
* CS-framed read ends on a CS rising edge, resetting that counter; the value is
202+
* discarded. Runs under the caller's bus lock.
203+
*/
204+
static void imu_adis_reframe(struct adis_dev *dev)
205+
{
206+
uint32_t scratch;
207+
208+
for (uint32_t i = 0; i < 2; i++)
209+
(void)adis_read_prod_id(dev, &scratch);
210+
}
211+
168212
static int imu_adis_init_staged(struct adis_dev **adis)
169213
{
170214
struct adis_diag_flags diag_flags;
171215
struct adis_dev *dev;
172-
int ret;
216+
int ret = -EIO;
217+
uint32_t attempt;
173218

174219
if (!adis_ip.info)
175220
return -EINVAL;
@@ -191,8 +236,19 @@ static int imu_adis_init_staged(struct adis_dev **adis)
191236
dev->is_locked = false;
192237
g_shared->state = IMU_STATE_SPI_OK;
193238

194-
set_stage(IMU_STAGE_ADIS_RESET_CMD);
195-
ret = adis_cmd_sw_res(dev);
239+
/* Re-frame, reset, and verify the ADIS is sampling; retry if not. */
240+
for (attempt = 0; attempt < IMU_ADIS_RESET_ATTEMPTS; attempt++) {
241+
set_stage(IMU_STAGE_ADIS_RESET_CMD);
242+
imu_adis_reframe(dev);
243+
ret = adis_cmd_sw_res(dev);
244+
if (ret)
245+
goto error;
246+
247+
set_stage(IMU_STAGE_ADIS_RESET_WAIT);
248+
ret = imu_adis_check_sampling(dev);
249+
if (!ret)
250+
break;
251+
}
196252
if (ret)
197253
goto error;
198254

0 commit comments

Comments
 (0)