MDK-ARM RealView
I am converting some gcc based code and I am wondering how to convert the following C inline asm. The RealView compiler has slightly different syntax for inline, and the manual seems to spend more time telling you what you can't do than showing you what works.
//gcc inline asm volatile ( \ "mrs r3,cpsr;" \ "bic r3,r3,#0xC0;" \ "msr cpsr,r3" \ : \ : \ : "r3" \ )
As far as I can tell (and I could be missing something) from the gcc docs, this bit above clears the irq,fiq bits in the cspr, the 'volatile' keeps it all from being optimized away, and I think the "r3" notation tells the compiler that r3 is going to be messed with so preserve it. I assume that cpsr here is the real physical register (it wouldn't work otherwise), but 'r3' may be some virtual version with no connection to the real r3. Any substitute code I come up with would have to do all of the above things.
Not surprising the gcc code does not compile under RealView. 'asm' needs to be '__asm' (for C), I think 'volatile' is not supported in this way, and the : "r3" syntax is totally rejected as well.
The manual states that the inline register references will almost always be virtual and have nothing to do with the physical registers, but it does seem to make an exception for psr (I assume this means cpsr,spsr), so the following inline does compile. The manual suggests that RealView will automatically preserve any used regs (but hopefully allow direct access to cspr). What's missing is the 'volatile'. Does RealView automatically preserve & protect inline asm code or do I have to take extra steps?
int r3;//this ones virtual _asm ( mrs r3,cpsr bic r3,r3,#0xC0 msr cpsr,r3 )
Another simple option (less efficient?) seems to be using the intrinsic functions:
__enable_irq; __enable_fiq;
Another possibility may be to use the named register variable feature which is supposed to access the real physical register:
register unsigned int mycspr __asm ("cspr"); unsigned int value; value = mycspr & 0xFFFFFF3F; mycspr = value;
Another possibility is to use an embedded asm function:
__asm void disable_intrs(void) { mrs r3,cpsr bic r3,r3,#0xC0 msr cpsr,r3 } disable_intrs()
I have not checked these out yet, so let me know if there are any problems/comments with these methods or if there is a method I missed.
Everything seems correct. There is another method: have a separate source file written in assembly and link it to the C program. Just one comment about clearing the irq and fiq bits in CPSR. Make sure you read this article: infocenter.arm.com/.../3677.html
Regards, - mike
as you stated, there are major differences between the compilers when it comes down to dealing with inline assembly. RealView puts severe limitations on its usage (see compiler guide), and encourages the usage of embedded assembly instead. one other serious drawback when using inline assembly is that it is exposed to compiler optimizations - so what you write is _not_ necessarily what you get!
Great. Hard to find bugs in the most time sensitive part of the design. I had hoped that picking a mature architecture would avoid this kind of nonsense.
Unless Realview has built in some of the fixes, it sounds like what is needed is a set of C intrinsics or macros to implement these interrupt bug fixes. Anyone?
Use this one. It will give you the most efficient implementation for the specified CPU target.
Inline assembler (in the RealView compiler) has been deprecated for newer architectures. It has several limitations (see docs) and intrinsics should be used instead where possible. Makes you code more readable, too.
Regards Marcus http://www.doulos.com/arm/
Does anyone know of a simple guide to translate between Realview asm syntax and Gnu asm syntax?
I mainly have problems with directives and pragmas, which aren't as similar as you might think. The manuals are not as clear as they could be.
The manuals are not as clear as they could be
I disagree - RV documentation is outstanding, most of the time. but either way, the manuals are clear about one thing without any doubt: inline assembly - YUK! don't do it, do yourself a favor...
Realview docs are better than gnu docs, but far from the best I have seen. Anyway, right now I am talking about plain assembly, not inline. I have both realview and gnu manuals in front of me. The language differences make even simple conversions confusing.
In the following gnu as statements, the size of a body of code is assigned to a pre-exiting function symbol, so I assume the symbol has both an address and a size attribute. How would this be done in Realview?:
.func _startup _startup: ;function body goes here .size _startup, . - _startup .endfunc
which I translate to:
_startup FUNCTION ;function body goes here ;how to do the size assignment? ENDFUNC
Or the following which creates labels with constant absolute address values:
.struct SRAM_START + 0x20 HandleReset: .struct SRAM_START + 0x24 HandleUndef:
Since gnu as already has an .equ statement, it seems like this should translate to more than just:
HandleReset equ SRAM_START + 0x20 HandleUndef equ SRAM_START + 0x24
The gcc startup.S files refer to the usual bunch of symbols defined in the linker script: '_text','_etext','_data','_edata','__bss_start__','__bss_end__'
In realview I thought I ran across a set of predefined symbols to do the same, but can't find them now. Do they exist, if not how do I create them?
http://www.keil.com/support/man/docs/armlink/armlink_chdcgbjd.htm