Open qiayuanl opened 1 year ago
Hi, have a look at https://rt-labs.com/refman/ethercat-sdk_refman.pdf page 38:
In addition to SM2 add SMCHANGE, EEP(if EEPROM emulated), ALCONTROL, SM0 and SM1 to the mask to generate PDI interrupt
Have you done this?
What you mentioned is about Interrupt mode
. I use the Mixed Polling/Interrupt (SM or DC Synchronous)
mode.
Ah, I had not tried this yet. I just ported some example code to STM32 and have not looked into it more. Sounds like good idea to try it out at some point
Hey, have you figured it out that you are closing issue? Now as I read your original post, it looks like you tried to call stack handler from interrupt, while stack was in mixed mode. This sounds wrong. SOES stack originally was really intended to be used in polled mode, if you want it's handler in interrupt then configure it and call in interrupt mode
I think the original problem is the interrupt priority. All ESC relative interrupts should be in the same priority, if not, the ESC_write and ESC_read will be interrupted. However, I don't remember too much since there are tons of new code after this issue.
I meet this problem again, a clearer description should be: "The PDI interrupt will randomly disappear when the bus running high frequency (1khz~4khz)."
Here is some behavior:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == ESC_INT_Pin) {
ESC_updateALevent();
if (ESCvar.dcsync == 0) // If DC sync is not active, run the application, all except for the Watchdog
DIG_process(DIG_PROCESS_OUTPUTS_FLAG | DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
else // If DC sync is active, call output handler only
DIG_process(DIG_PROCESS_OUTPUTS_FLAG);
} else if (GPIO_Pin == ESC_SYNC_Pin) {
ESC_updateALevent();
DIG_process(DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim == &TIM_ESC) {
ecat_slv_poll();
DIG_process(DIG_PROCESS_WD_FLAG);
}
}
red_test.c
in SOEM, this small program can auto-detect the loss of slave and auto-recover, also easy to change the cycletime.DIG_process(DIG_PROCESS_OUTPUTS_FLAG)
, the watchdog was triggered and the slave got into safeoperation.pdi_irq_flag
and sync0_irq_flag
in the callback function and process everything in main() like your example got the same result. ecat_slv()
for everything without interrupts work perfectlyecat_slv_poll()
to DIG_process(DIG_PROCESS_WD_FLAG | DIG_PROCESS_OUTPUTS_FLAG);
and it works perfectly (the watchdog protection is also working)I am very confused, not sure if you can reproduce this problem.
Hello, good you were able to localize problem.
Looks like I was testing my code with TwinCAT at 500 Hz, will check with 1 KHz or more, and SOES red_test
I have some STM32F401 board somewhere, and spare AX58100 breakout. If you can publish your firmware I should be able to reproduce your setup (and problem)
First potential problem I see: looks like you are running mixed mode code but using it in interrupt operation. ecat_slv_poll
is meant to be polled, running in some kind of main function. The way it is done in SOES mixed mode examples:
https://github.com/OpenEtherCATsociety/SOES/blob/8f3841e3cefd83c48d866ffaeb2d92c146bf3cd7/applications/tiesc_am335x/main.c#L77
Look at slv_poll implementation, it is doing a lot of stuff starting with reading local time from ESC (over SPI in our case). You do not want this in interrupt handler, that must finish quickly.
Per docs, for running in interrupt you want ecat_slv_worker
(and still
Do you have a copy of SOES docs - ethercat-sdk_refman.pdf
?
Another possibility is wrong interrupt priority. My example had equal priority and subpriority on SYNC and PDI IRQ EXTI, I think this should be OK - test with master in higher frequency should tell.
Putting ecat_slv_poll
to main() does change the result, the reason I put it in timer interrupt is to control the watchdog timeout.
I don't have ethercat-sdk_refman.pdf
Have a look at tiesc_am335x example, watchdog kick is done in main too. The same setup in examples in docs PDF.
Manual PDF used to be available, now you need to log in on rt-labs page
That is what I mean, whether the
ecat_slv_poll();
DIG_process(DIG_PROCESS_WD_FLAG);
inside the main loop or not does not affect the result. The problem I describe still remains.
I tried SOEM red_test
(on old thinkpad laptop with Linux if that even matters) with SOES_CIA402_AX58100
code.
I tested cycletime from 1000 down to 100 us and could not reproduce the problem. Slave just kept working, and after RJ45 cable disconnect+reconnect it recovered to OP every time.
I will now try with ecat_slv_poll();\r\n DIG_process(DIG_PROCESS_WD_FLAG);
in IRQ handler but if you want me to really reproduce your setup, I am going to need your F401 code
What HW are you using for ethercat master, by the way?
I am using a ThinkPad laptop for ethercat master. I can share some code privately. However, my newest code is running on H755 (AX58400), can you port it to f401 or let me find some old code (one year ago)?
Your code and documents are awesome! Thank you for your sharing.
Following your SOES_CIA402_AX58100 code, I wrote my code using CubeMX(HAL) and successfully ran it in NUCLEO-F401RE and AX58100-REF-1 without CIA402 applications.
After success, I try to call the DIG_process in the interrupt callback. The code is shown below:
However, after getting into the
Operational
state, the ESI stops sending PDI to interrupt MCU. As a result, MCU no longer processes the output.Have you tried what I mentioned above? Why do we need to process the interrupt in the
while()
?