kubabuda / ecat_servo

Open EtherCAT CiA402 servo drive implementation
GNU General Public License v2.0
164 stars 50 forks source link

DIG_process in interrupt #4

Open qiayuanl opened 1 year ago

qiayuanl commented 1 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:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
 if (GPIO_Pin == ESC_INT_Pin) {
    ESC_updateALevent();
    if (ESCvar.ALevent & ESCREG_ALEVENT_SM2) {
      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);
   }
}

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()?

kubabuda commented 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?

qiayuanl commented 1 year ago

What you mentioned is about Interrupt mode. I use the Mixed Polling/Interrupt (SM or DC Synchronous) mode.

kubabuda commented 1 year ago

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

kubabuda commented 5 months ago

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

qiayuanl commented 5 months ago

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.

qiayuanl commented 4 months ago

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);
  }
}

I am very confused, not sure if you can reproduce this problem.

kubabuda commented 4 months ago

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.

qiayuanl commented 4 months ago

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

kubabuda commented 4 months ago

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

qiayuanl commented 4 months ago

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.

kubabuda commented 4 months ago

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?

qiayuanl commented 4 months ago

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)?