Global Interrupt

Hi

How can I enable or disable global interrupt in STM32?

Duplicate post!

Sorry but how can I disable the global interrupt?

You can use “cpsie i” in order to enable the interrupts and “cpsid i” in order to disable them globally.

Anyway it is better if you read the Cortex-M3 technical reference manual, the interrupt architecture is quite complicated.

Giovanni

I am writing a small RTOS kernel and I also want to disable all interrupts globally. I looked at your code and also found “cpsid i”. But for me it does not seem to work as I expected it to.

I follow ARM’s recommendations and start the first thread by returning from an SVC using “bx lr”. The PSP is properly set up and using gdb I can also see that the PC is moved to the first instruction of the thread. However, when stepping that first instruction (tried different instructions, such as “svc” and a push using a valid stackpointer) I end up in a handler for an external interrupt with number 321 (according to OpenOCD).

OpenOCD also spits out things like the following:

Error:   cortex_swjdp.c:224 swjdp_transaction_endcheck(): SWJ-DP STICKY ERROR
Error:   cortex_swjdp.c:238 swjdp_transaction_endcheck(): dcb_dhcsr 0x109000d, nvic_shcsr 0x20000, nv
ic_cfsr 0x20000, nvic_bfar 0xe000edf8
Error:   cortex_swjdp.c:224 swjdp_transaction_endcheck(): SWJ-DP STICKY ERROR
Error:   cortex_swjdp.c:238 swjdp_transaction_endcheck(): dcb_dhcsr 0x9000d, nvic_shcsr 0x20000, nvic
_cfsr 0x20000, nvic_bfar 0xe000edf8
Error:   cortex_swjdp.c:224 swjdp_transaction_endcheck(): SWJ-DP STICKY ERROR
Error:   cortex_swjdp.c:238 swjdp_transaction_endcheck(): dcb_dhcsr 0x9000d, nvic_shcsr 0x20000, nvic
_cfsr 0x20000, nvic_bfar 0xe000edf8
Error:   cortex_swjdp.c:224 swjdp_transaction_endcheck(): SWJ-DP STICKY ERROR
Error:   cortex_swjdp.c:238 swjdp_transaction_endcheck(): dcb_dhcsr 0x9000d, nvic_shcsr 0x20000, nvic
_cfsr 0x20000, nvic_bfar 0xe000edf8

I am not sure what your problem is but you should take care of interrupt priorities.

“svc” cannot be executed between a “cpsid i” and a “cpsie i”, it is a common error.

If you execute a “svc” while the interrupts are disabled using “cpsid i” you will end up in the hard fault handler because the svc priority can be only lower or equal to zero, “cpsid i” masks all interrupts with priorities up to zero (highest).

Originally, I had no “cpsid i” at all. I just set up some thread stacks and then called ‘svc’, running in privileged thread mode. Calling svc worked fine then. Now that i added ‘cpsid i’ just before the svc call, ‘svc’ still appears to work fine.

Does that mean that I actually have interrupts enabled? Interesting… I thought that interrupts were globally disabled after sysreset.

The SWJ-DP STICKY ERRORs appear after I am doing a return from the SVC handler (bx lr).

Reading the documentation it appears that the interrupts are globally enabled on reset but disabled at NVIC level. I added a “cpsid i” in my startup file just in case.

I am not sure how you are able to invoke a “svc” after a “cpsid i”, may be the effect of the global disable is delayed by the internal pipeline.

The svc should be escalated to an hard fault.

That is also my understanding from the documentation…

I agree with you - it seems strange that the svc works, my code has a few instructions between the ‘cpsid i’ and the ‘svc’, so the pipeline effect should not explain why it works! Here’s the piece of code:

   asm("mov r0, 0x1\n\t"
       "msr CONTROL, r0\n\t"
       "isb\n\t"
       "cpsid i\n\t"
       "mov r0, 0x0\n\t"
       "msr BASEPRI, r0\n\t"
       "mov r0, 0x0\n\t"
       "svc\n\t"
       : : : "r0");

The BASEPRI assignment is new, I did not have it before, and I could not notice any difference regarding the ‘svc’ functionality.

A small update; I still don’t have the answer why svc works after ‘cpsid i’. However, my original problem with my first thread crashing after the “bx lr” return from the SVC handler that started the thread has been solved:

My small kernel initializes the stack for every process, by pre-pushing all registers that a context switch to the specific thread would pop. Thus, at the top of the stack I push the registers that “bx lr” automatically pops when returning from an exception. r0-r3 and r12 just have random values, PC is set to the process entry point (with LSB set as we’re running Thumb-2 always), LR is zero. What I did wrong was pushing zero for the xPSR as well. The correct value should be 0x01000000, i.e. the T bit must be set. Fixing that, my process started running properly!

Understood, I do pretty much the same thing.

Giovanni