Closed Pascal8749 closed 1 year ago
Your unlock does not work correctly. If interrupts were locked before you locked them again, your unlock method will unlock them.
Actually __set_PRIMASK((CAN_MODULE)->primask_od)
will unlock them only if they were previously unlocked.
Process is:
uint32_t primask = __get_PRIMASK(); // Get interrupt status
__disable_irq(); // Force interrupt disabled
// do the job
__set_PRIMASK(primask); //Re-enable interrupts only if these have been enabled before the disable call
Anything else is wrong and can sooner or later lead to issues.
Driver is done like explained above. Issue you are facing lays somewhere else, not in the interrupt management.
/* (un)lock critical section in CO_CANsend() */
// Why disabling the whole Interrupt
#define CO_LOCK_CAN_SEND(CAN_MODULE) \
do { \
(CAN_MODULE)->primask_send = __get_PRIMASK(); \
__disable_irq(); \
} while (0)
#define CO_UNLOCK_CAN_SEND(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_send)
/* (un)lock critical section in CO_errorReport() or CO_errorReset() */
#define CO_LOCK_EMCY(CAN_MODULE) \
do { \
(CAN_MODULE)->primask_emcy = __get_PRIMASK(); \
__disable_irq(); \
} while (0)
#define CO_UNLOCK_EMCY(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_emcy)
/* (un)lock critical section when accessing Object Dictionary */
#define CO_LOCK_OD(CAN_MODULE) \
do { \
(CAN_MODULE)->primask_od = __get_PRIMASK(); \
__disable_irq(); \
} while (0)
#define CO_UNLOCK_OD(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_od)
Okay thanks for the feedback. I don't understand exactly what the two macros do, but I believe you. I could not solve the problem, and so I ran the function canopen_app_interrupt() in a timer interrupt again, despite freertos. Just like it is solved in the example to freertos. This is a bit unsatisfying, but at least now everything runs as expected.
I have observed an interesting phenomenon. The following scenario: I ran CanopenNode_STM32 under FreeRtOS. There are three tasks in total. One task is the send and process routine for CanopenNode. One task is a controller. The third task is the receive routine for CanopenNode, so basically the function "canopen_app_interrupt()".
Everything works fine until I enable CRC. In this case FreeRtOS ignores the delay function (osDelay(1)) and does not process any other task except the receive routine. Why the CRC unit does this is beyond me, but in this case it is because of the macros "CO_LOCK_OD" and "CO_UNLOCK_OD". After some research I rewrote the macro "CO_UNLOCK_OD" from
to
And now my code seems to work even with CRC unit turned on. Tests are still pending. I am not a computer scientist, so please correct me if my approach was stupid.