Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested OC_LOCK_OD causing permanently disabled interrupts. #34

Open
somlioy opened this issue Jun 20, 2023 · 7 comments
Open

Nested OC_LOCK_OD causing permanently disabled interrupts. #34

somlioy opened this issue Jun 20, 2023 · 7 comments

Comments

@somlioy
Copy link

somlioy commented Jun 20, 2023

Hi

After the update in CanopenNode where OD is always locked on a SDO call (Always call OD lock macros on SDO operations), my code broke down; the interrupts isnt enabled again.

This change caused nested OC_LOCK_OD to happen and since there is only one variable for storing the primask in the CO_CANmodule_t struct, the interrupts will never be enabled again.

The result was that the code stopped working on a HAL_Delay (infinite while loop) in anothert part of the application since OC_LOCK/__disable_irq apparantly also disable systicks.

I noticed this during a eeprom save (0x1010) because I had OC_LOCK_OD/UNLOCK on the OD-entry to be saved in the "storeEeprom"-function.

Is there any better way to implement this?
Ie. not disabling global interrupts, only the timer in charge of the interrupts and some other way of storing primask?

@MaJerle
Copy link
Collaborator

MaJerle commented Jun 20, 2023

Very technically, primask shall always be stored as local variable. Can you point out how your call stack looks like when this happens?

@MaJerle
Copy link
Collaborator

MaJerle commented Jun 20, 2023

Or maybe disable CO_CONFIG_FLAG_SDO_ALWAYS_LOCK_OD instead?

@somlioy
Copy link
Author

somlioy commented Jun 20, 2023

Yeah primask stored in a local variable would be the optimal choice for such an event, altought I'm not sure how that would be done when using macros like that. A local variable inside the do-while would be limited to access within that scope.

See Call stack below (breakpoint at the point where I call OC_LOCK_OD (in storeEeprom).
So CO_LOCK_OD is first called by CO_SDOserver_process() and then by me in storeEeprom()
image

I've already updated CANopenNode to latest version, so CO_CONFIG_FLAG_SDO_ALWAYS_LOCK_OD is deprecated. See commit attached in first post.

Technically I guess it safe to assume storeEeprom() and restoreEeprom() never would be called from anything else than via SDO such that the LOCKs I have in store-/restoreEeprom safely can be removed.

However there's still the "issue" where systicks are disabled doing a LOCK causing HAL_Delay to be stuck in a while-loop. Encountered this during my first implementation of the eeprom-writing function where HAL_Delay was used to allow for eeprom-page writing to be finished, thought this was fixed by polling the eeprom wether it is ready or not (HAL_I2C_IsDeviceReady).

@skpang
Copy link

skpang commented Jul 7, 2023

I'm seeing this problem is well.

CO_LOCK_OD has a __disable_irq() function inside:
#define CO_LOCK_OD(CAN_MODULE) \ do { \ (CAN_MODULE)->primask_od = __get_PRIMASK(); \ __disable_irq(); \ } while (0)

Where as CO_UNLOCK_OD only set the mask:
#define CO_UNLOCK_OD(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_od)

Should there be an enable irq inside CO_UNLOCK_OD ?

@MaJerle
Copy link
Collaborator

MaJerle commented Jul 7, 2023

No. __set_PRIMASK will enable the interrupts, if these have been enabled before __disable_irq() has been called.

@skpang
Copy link

skpang commented Jul 7, 2023

Ok, somehow the __set_PRIMASK is not re-enabling the interrupts for me.

@MaJerle
Copy link
Collaborator

MaJerle commented Jul 7, 2023

This will happen if this happens:

CO_LOCK_OD();
CO_LOCK_OD(); <--- previous value is overwritten
CO_UNLOCK_OD(); <--- invalid previous value 
CO_UNLOCK_OD(); <--- invalid previous value

So is there a case when LOCK is called twice in a sequence

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants