Hi everyone,
I am trying to come up with some macros to enable and disable all interrupts in my LPC2364 while using the Keil RTX and programming in uVision4. After searching through much of the knowledge base, I came across the macros IENABLE and IDISABLE.
unsigned char interrupts_enabled = 0; #define IENABLE __asm{ MRS LR , SPSR }; \ __asm{ STMFD SP! , {LR} }; \ __asm{ MSR CPSR_c , #0x1F }; \ __asm{ STMFD SP! , {LR} }; \ interrupts_enabled = 1; #define IDISABLE __asm{ LDMFD SP! , {LR} }; \ __asm{ MSR CPSR_c , #0x92 }; \ __asm{ LDMFD SP! , {LR} }; \ __asm{ MSR SPSR_cxsf , LR }; \ interrupts_enabled = 0;
Most of that code is a mix of what is suggested in the following links:
http://www.keil.com/support/docs/2910.htm http://www.keil.com/support/man/docs/armcc/armcc_cihccdja.htm http://www.keil.com/support/man/docs/armcc/armcc_Chdgbbia.htm
However, I think I am having a problem due to Virtual Registers. As per the third reference above, we are not allowed to access the LR, SP and PC registers directly. That is the reason why, obviously, I get errors such as the following:
..\RF\mrfi\radios\common\mrfi_f1f2.c(242): error: #20: identifier "LR" is undefined
These instructions that access the LR and SP registers are quite significant in what I am trying to achieve though. How can I express this behavior in terms of what inline assembly can do for me? Has anyone done anything like this before, for enabling/disabling interrupts in a LPC microcontroller?
Remember that "named" variables or your intrinsics doesn't change anything in reality.
You still have to remember the mode of the processor.
Your link contains this text: "The __disable_irq intrinsic can only be executed in privileged modes, that is, in non user modes. In User mode this intrinsic does not change the interrupt flags in the CPSR."
Privileged modes are a part of the processor and can't be ignored by "magic" features in the compiler.
Per,
Yes, I realize that, but thanks for contributing.
I am still a bit unsure about this, but I assume that the way to go here is to use that macro inside a SWI? I believe that way the processor will be in privileged mode and will be able to perform that operation. Is that correct?
More related posts: http://www.keil.com/forum/15921/ http://www.keil.com/forum/15819/
Another question: should I have my own flag to determine whether interrupts are currently enabled or disabled by me, or is there another way for me to check that in my code?
Can anyone help me with these last few questions?
Why would you need to know if interrupts are disabled or not? That would imply that your program have randomly disabled interrupts before you get to your critical section.
The goal of the application is that interrupts are enabled with the exception of special - small and quick - critical sections. So when you do write such a critical section, you would then know to disable interrupts and reenable them before leaving the critical section.
The reason why you should have very small and quick critical sections with interrupts turned off is that the time spent with interupts off adds to the worst-case interrupt latency you get, quickly making it almost impossible to know what latency you may have. And too much latencies means you will get buffer overflows for UART code and lots of other problems.
Thank you for trying to answer and be as informative as you can.
I do realize all of the things you have said, but there is a reason why I need to know whether I have enabled/disabled interrupts -- simply to be compliant with the protocol stack I am trying to port to my platform.
Describing the application is really out of scope in this forum, but what I am doing is porting the SimpliciTI protocol stack from Texas Instruments to the Keil environment with LPC23xx.
To do that, I have to change some macros that are right now specific to TI microcontrollers, and adapt them to the ARM LPC23xx reality, which means that if they have macros such as "BSP_INTERRUPTS_ARE_ENABLED()" or "BSP_DISABLE_INTERRUPTS()", I should be able to provide proper output so the software will function as expected.
For now I am keeping a variable whose value I change whenever I disable or enable interrupts in my SWI, but if there is a better way to do that I would very much like to know about it.