bgkatz / motorcontrol

motor controller firmware
MIT License
241 stars 101 forks source link

the new version stuck when setting zero position #6

Closed chongxi closed 2 years ago

chongxi commented 2 years ago

The update of the firmware 2.0 looks nice. Thanks, @bgkatz, so far I have entered one problem consistently.

This issue is triggered when the code runs into the function of HAL_Delay(20) in the step of update_fsm, which is in the fsm.c file. It just stuck there and never goes to the next step.

Since update_fsm is reused in both the CAN1_RX0_IRQHandler and USART2_IRQHandler, set zero position makes the firmware stuck either from serial configuration or from CAN communication.

Here is part of the code in update_fsm:

    switch(fsmstate->state){
        case MENU_MODE:
            switch (fsm_input){
                case CAL_CMD:
                    fsmstate->next_state = CALIBRATION_MODE;
                    fsmstate->ready = 0;
                    break;
                case MOTOR_CMD:
                    fsmstate->next_state = MOTOR_MODE;
                    fsmstate->ready = 0;
                    break;
                case ENCODER_CMD:
                    fsmstate->next_state = ENCODER_MODE;
                    fsmstate->ready = 0;
                    break;
                case SETUP_CMD:
                    fsmstate->next_state = SETUP_MODE;
                    fsmstate->ready = 0;
                    break;
                case ZERO_CMD:
                    printf("\n\r Try setting new zero position. \n\r");
                    comm_encoder.m_zero = 0;
                    ps_sample(&comm_encoder, DT);
                    HAL_Delay(20);
                    M_ZERO = comm_encoder.count;
                    //if (!prefs.ready()) prefs.open();
                    //    prefs.flush();                                                  // Write new prefs to flash
                    //    prefs.close();
                    //    prefs.load();
                    //spi.SetMechOffset(M_OFFSET);
//                  printf("\n\r Saved new zero position\n\r\n\r");
//                  printf(M_ZERO);
                    printf("\n\r  Saved new zero position:  %d\n\r\n\r", M_ZERO);
                    break;
                }

I appreciate it if any solution is suggested @bgkatz. Thanks!

chongxi commented 2 years ago

I think this is an ISR priority issue, change NVIC_PRIORITYGROUP from 0 to 4.

In stm32f4xx_hal_msp.c make sure the priority grouping is not 0. When the NVIC_PriorityGroup_0 is selected, IRQ preemption is no more possible. The pending IRQ priority will be managed only by the subpriority. Here I changed it to 4:

  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);  // here I change NVIC_PRIORITYGROUP_0 to NVIC_PRIORITYGROUP_4

And in can.c and uart.c make sure both ISRs use lower priority than the SysTick:

  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(SysTick_IRQn);

in uart.c:

    HAL_NVIC_SetPriority(USART2_IRQn, 1, 1);
    HAL_NVIC_EnableIRQ(USART2_IRQn);

in can.c:

    HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 1);
    HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);

Then it seems to solve the problem in my case.

chongxi commented 2 years ago

As pointed out here:

All delay and timeout HAL functions rely on a counter incremented in the SysTick handler. If you are using any of these functions in another interrupt, you have to make sure that the SysTick interrupt has a higher priority than that interrupt. Otherwise, the SysTick handler is never called and you will end up in an infinite loop, as the counter will never be increased.

Other people have reported the same issue when both the UART ISR and SysTick shared the same priority

If you use @bgkatz code here with your own library setting and you have this issue:

Possibilities: 1) SysTick interrupt isn't set up or enabled. 2) interrupts are disabled. 3) priority of SysTick is less or equal to that of the UART/CAN. Note that a priority of 0 is the highest priority. 4) interrupts cannot preempt each other. Check priority grouping setting (HAL_NVIC_SetPriorityGrouping cannot use NVIC_PRIORITYGROUP_4).

bgkatz commented 2 years ago

The issue here was simply that I had not implemented saving the zero position. Should work now.