Skip to content

Commit d9dba2c

Browse files
authored
Fix i2s probing hang (bdring#608)
* Fix I2S stepper hung just after the completion of motor moving * Fix recompile issue Fixed a problem with the recompile not being recompiled even if the files under the Custom folder are changed. * More comment for macOS in debug.ini * Fix the timing of calling I2S out's exclusion function and reset sequence The reset sequence did not seem to be correct, so I changed it. According to the ESP-IDF PR, the correct sequence is as follows: 1)TX module 2)DMA 3)FIFO espressif/esp-idf@c7f3352#diff-27688c6b3c29373d2a2b142b8471981c * Changed the message level for I2S swtiching from warning to debug * Add some comments
1 parent 27061bf commit d9dba2c

File tree

6 files changed

+79
-45
lines changed

6 files changed

+79
-45
lines changed

Grbl_Esp32/src/GCode.cpp

-14
Original file line numberDiff line numberDiff line change
@@ -1502,9 +1502,6 @@ Error gc_execute_line(char* line, uint8_t client) {
15021502
if (gc_state.modal.motion != Motion::None) {
15031503
if (axis_command == AxisCommand::MotionMode) {
15041504
GCUpdatePos gc_update_pos = GCUpdatePos::Target;
1505-
#ifdef USE_I2S_STEPS
1506-
stepper_id_t save_stepper = current_stepper;
1507-
#endif
15081505
if (gc_state.modal.motion == Motion::Linear) {
15091506
//mc_line(gc_block.values.xyz, pl_data);
15101507
mc_line_kins(gc_block.values.xyz, pl_data, gc_state.position);
@@ -1527,12 +1524,6 @@ Error gc_execute_line(char* line, uint8_t client) {
15271524
// upon a successful probing cycle, the machine position and the returned value should be the same.
15281525
#ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
15291526
pl_data->motion.noFeedOverride = 1;
1530-
#endif
1531-
#ifdef USE_I2S_STEPS
1532-
save_stepper = current_stepper; // remember the stepper
1533-
if (save_stepper == ST_I2S_STREAM) {
1534-
stepper_switch(ST_I2S_STATIC); // Change the stepper to reduce the delay for accurate probing.
1535-
}
15361527
#endif
15371528
gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags);
15381529
}
@@ -1544,11 +1535,6 @@ Error gc_execute_line(char* line, uint8_t client) {
15441535
} else if (gc_update_pos == GCUpdatePos::System) {
15451536
gc_sync_position(); // gc_state.position[] = sys_position
15461537
} // == GCUpdatePos::None
1547-
#ifdef USE_I2S_STEPS
1548-
if (save_stepper == ST_I2S_STREAM && current_stepper != ST_I2S_STREAM) {
1549-
stepper_switch(ST_I2S_STREAM); // Put the stepper back on.
1550-
}
1551-
#endif
15521538
}
15531539
}
15541540
// [21. Program flow ]:

Grbl_Esp32/src/I2SOut.cpp

+34-21
Original file line numberDiff line numberDiff line change
@@ -291,21 +291,15 @@ static int IRAM_ATTR i2s_out_start() {
291291

292292
// Attach I2S to specified GPIO pin
293293
i2s_out_gpio_attach(i2s_out_ws_pin, i2s_out_bck_pin, i2s_out_data_pin);
294-
//start DMA link
295-
i2s_out_reset_fifo_without_lock();
296294

297-
# ifdef USE_I2S_OUT_STREAM_IMPL
298-
if (i2s_out_pulser_status == PASSTHROUGH) {
299-
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
300-
I2S0.conf_single_data = port_data;
301-
} else {
302-
I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
303-
I2S0.conf_single_data = 0;
304-
}
305-
# endif
295+
// reest TX/RX module
296+
I2S0.conf.tx_reset = 1;
297+
I2S0.conf.tx_reset = 0;
298+
I2S0.conf.rx_reset = 1;
299+
I2S0.conf.rx_reset = 0;
306300

307301
# ifdef USE_I2S_OUT_STREAM_IMPL
308-
//reset DMA
302+
// reset DMA
309303
I2S0.lc_conf.in_rst = 1;
310304
I2S0.lc_conf.in_rst = 0;
311305
I2S0.lc_conf.out_rst = 1;
@@ -314,10 +308,19 @@ static int IRAM_ATTR i2s_out_start() {
314308
I2S0.out_link.addr = (uint32_t)o_dma.desc[0];
315309
# endif
316310

317-
I2S0.conf.tx_reset = 1;
318-
I2S0.conf.tx_reset = 0;
319-
I2S0.conf.rx_reset = 1;
320-
I2S0.conf.rx_reset = 0;
311+
// reset FIFO
312+
i2s_out_reset_fifo_without_lock();
313+
314+
// start DMA link
315+
# ifdef USE_I2S_OUT_STREAM_IMPL
316+
if (i2s_out_pulser_status == PASSTHROUGH) {
317+
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
318+
I2S0.conf_single_data = port_data;
319+
} else {
320+
I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
321+
I2S0.conf_single_data = 0;
322+
}
323+
# endif
321324

322325
I2S0.conf1.tx_stop_en = 1; // BCK and WCK are suppressed while FIFO is empty
323326

@@ -339,13 +342,14 @@ static int IRAM_ATTR i2s_out_start() {
339342
}
340343

341344
# ifdef USE_I2S_OUT_STREAM_IMPL
342-
345+
// Fill out one DMA buffer
346+
// Call with the I2S_OUT_PULSER lock acquired.
347+
// Note that the lock is temporarily released while calling the callback function.
343348
static int IRAM_ATTR i2s_fillout_dma_buffer(lldesc_t* dma_desc) {
344349
uint32_t* buf = (uint32_t*)dma_desc->buf;
345350
o_dma.rw_pos = 0;
346351
// It reuses the oldest (just transferred) buffer with the name "current"
347352
// and fills the buffer for later DMA.
348-
I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock pulser status
349353
if (i2s_out_pulser_status == STEPPING) {
350354
//
351355
// Fillout the buffer for pulse
@@ -408,7 +412,6 @@ static int IRAM_ATTR i2s_fillout_dma_buffer(lldesc_t* dma_desc) {
408412
o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow
409413
i2s_out_remain_time_until_next_pulse = 0;
410414
}
411-
I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status
412415

413416
return 0;
414417
}
@@ -591,10 +594,18 @@ i2s_out_pulser_status_t IRAM_ATTR i2s_out_get_pulser_status() {
591594
int IRAM_ATTR i2s_out_set_passthrough() {
592595
I2S_OUT_PULSER_ENTER_CRITICAL();
593596
# ifdef USE_I2S_OUT_STREAM_IMPL
597+
// Triggers a change of mode if it is compiled to use I2S stream.
598+
// The mode is not changed directly by this function.
599+
// Pull the trigger
594600
if (i2s_out_pulser_status == STEPPING) {
595-
i2s_out_pulser_status = WAITING; // Start stopping the pulser
601+
i2s_out_pulser_status = WAITING; // Start stopping the pulser (trigger)
596602
}
603+
// It is a function that may be called via i2sOutTask().
604+
// (i2sOutTask() -> stepper_pulse_func() -> st_go_idle() -> Stepper_Timer_Stop() -> this function)
605+
// And only i2sOutTask() can change the state to PASSTHROUGH.
606+
// So, to change the state, you need to return to i2sOutTask() as soon as possible.
597607
# else
608+
// If it is compiled to not use I2S streams, change the mode directly.
598609
i2s_out_pulser_status = PASSTHROUGH;
599610
# endif
600611
I2S_OUT_PULSER_EXIT_CRITICAL();
@@ -627,6 +638,7 @@ int IRAM_ATTR i2s_out_set_stepping() {
627638
I2S_OUT_PULSER_EXIT_CRITICAL();
628639
return 0;
629640
}
641+
// Now, DMA completed. Fallthrough.
630642
}
631643

632644
// Change I2S state from PASSTHROUGH to STEPPING
@@ -772,7 +784,6 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
772784
//
773785

774786
// configure I2S data port interface.
775-
i2s_out_reset_fifo();
776787

777788
//reset i2s
778789
I2S0.conf.tx_reset = 1;
@@ -786,6 +797,8 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
786797
I2S0.lc_conf.out_rst = 1; // Set this bit to reset out DMA FSM. (R/W)
787798
I2S0.lc_conf.out_rst = 0;
788799

800+
i2s_out_reset_fifo_without_lock();
801+
789802
//Enable and configure DMA
790803
I2S0.lc_conf.check_owner = 0;
791804
I2S0.lc_conf.out_loop_test = 0;

Grbl_Esp32/src/MotionControl.cpp

+34-2
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,25 @@ static bool axis_is_squared(uint8_t axis_mask) {
260260
return mask_is_single_axis(axis_mask) && mask_has_squared_axis(axis_mask);
261261
}
262262

263+
#ifdef USE_I2S_STEPS
264+
# define BACKUP_STEPPER(save_stepper) \
265+
do { \
266+
if (save_stepper == ST_I2S_STREAM) { \
267+
stepper_switch(ST_I2S_STATIC); /* Change the stepper to reduce the delay for accurate probing. */ \
268+
} \
269+
} while (0)
270+
271+
# define RESTORE_STEPPER(save_stepper) \
272+
do { \
273+
if (save_stepper == ST_I2S_STREAM && current_stepper != ST_I2S_STREAM) { \
274+
stepper_switch(ST_I2S_STREAM); /* Put the stepper back on. */ \
275+
} \
276+
} while (0)
277+
#else
278+
# define BACKUP_STEPPER(save_stepper)
279+
# define RESTORE_STEPPER(save_stepper)
280+
#endif
281+
263282
// Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
264283
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
265284
// executing the homing cycle. This prevents incorrect buffered plans after homing.
@@ -371,6 +390,13 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
371390
if (sys.abort) {
372391
return GCUpdatePos::None; // Return if system reset has been issued.
373392
}
393+
394+
#ifdef USE_I2S_STEPS
395+
stepper_id_t save_stepper = current_stepper; /* remember the stepper */
396+
#endif
397+
// Switch stepper mode to the I2S static (realtime mode)
398+
BACKUP_STEPPER(save_stepper);
399+
374400
// Initialize probing control variables
375401
uint8_t is_probe_away = bit_istrue(parser_flags, GCParserProbeIsAway);
376402
uint8_t is_no_error = bit_istrue(parser_flags, GCParserProbeIsNoError);
@@ -381,7 +407,8 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
381407
if (probe_get_state() ^ is_probe_away) { // Check probe pin state.
382408
sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial;
383409
protocol_execute_realtime();
384-
return GCUpdatePos::None; // Nothing else to do but bail.
410+
RESTORE_STEPPER(save_stepper); // Switch the stepper mode to the previous mode
411+
return GCUpdatePos::None; // Nothing else to do but bail.
385412
}
386413
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
387414
mc_line(target, pl_data);
@@ -392,9 +419,14 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
392419
do {
393420
protocol_execute_realtime();
394421
if (sys.abort) {
395-
return GCUpdatePos::None; // Check for system abort
422+
RESTORE_STEPPER(save_stepper); // Switch the stepper mode to the previous mode
423+
return GCUpdatePos::None; // Check for system abort
396424
}
397425
} while (sys.state != State::Idle);
426+
427+
// Switch the stepper mode to the previous mode
428+
RESTORE_STEPPER(save_stepper);
429+
398430
// Probing cycle complete!
399431
// Set state variables and error out, if the probe failed and cycle with error is enabled.
400432
if (sys_probe_state == Probe::Active) {

Grbl_Esp32/src/Stepper.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,10 @@ void stepper_switch(stepper_id_t new_stepper) {
457457
#ifdef USE_I2S_STEPS
458458
if (current_stepper == ST_I2S_STREAM) {
459459
if (i2s_out_get_pulser_status() != PASSTHROUGH) {
460-
// This switching function should not be called during streaming.
461-
// However, if it is called, it will stop streaming.
462-
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Warning, "Stop the I2S streaming and switch to the passthrough mode.");
460+
// Called during streaming. Stop streaming.
461+
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Debug, "Stop the I2S streaming and switch to the passthrough mode.");
463462
i2s_out_set_passthrough();
464-
i2s_out_delay();
463+
i2s_out_delay(); // Wait for a change in mode.
465464
}
466465
}
467466
#endif

debug.ini

+7-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
upload_port = COM3
77
monitor_port = COM3
88
; macOS
9-
;upload_port = /dev/cu.usbserial-*
10-
;monitor_port = /dev/cu.usbserial-*
9+
;upload_port = /dev/cu.SLAB_USBtoUART
10+
;monitor_port = /dev/cu.SLAB_USBtoUART
11+
; macOS ESP-Prog
12+
;upload_port = /dev/cu.usbserial-14200
13+
;monitor_port = /dev/cu.usbserial-14201
14+
;upload_protocol = esp-prog
1115
; Linux
1216
;upload_port = /dev/ttyUSB*
1317
;monitor_port = /dev/ttyUSB*
1418
build_flags =
1519
${common.build_flags}
16-
-DMACHINE_FILENAME=test_drive.h
20+
-DMACHINE_FILENAME=test_drive.h
1721

1822
[env:debug]
1923
; You can switch between debugging tools using debug_tool option

platformio.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ board_build.flash_mode = qio
4949
build_flags = ${common.build_flags}
5050
src_filter =
5151
+<*.h> +<*.s> +<*.S> +<*.cpp> +<*.c> +<*.ino> +<src/>
52-
-<.git/> -<data/> -<test/> -<tests/> -<Custom/>
52+
-<.git/> -<data/> -<test/> -<tests/>
5353

5454
[env:release]
5555

0 commit comments

Comments
 (0)