Example of C and inline ASM in a file?
2006-04-07 by ah_sandiego
Yahoo Groups archive
Index last updated: 2026-04-28 23:31 UTC
Thread
2006-04-07 by ah_sandiego
Can someone post a simple example of C and inline ASM in a single file. I use the LPC2148 but any LPC board example would be helpful. Thanks, AH
2006-04-07 by Danish Ali
Hi AH,
You don't mention which C compiler you use. This makes
a big difference to how you include inline assembly code.
Attached is an example of something that gcc likes (as
supplied with Rowley Crossworks).
Key points:
volatile should discourage the compiler from re-ordering
and optimising the assembly away. But so fat I have not
turned on the optimiser.
C merges the assembly code into a single line, so you must
supply the "\n" to separate assembly instructions.
The subroutine relies on the fact that FIQ does not (yet)
occur in my system.
I do not fully understand the information you should put
in the : : : sections.
The first couple of lines of assembly code pass a value from
assembly to C, using the %0 and the "=r" (irqstat) phrases.
The last part is registers you use (warning the compiler not
to rely on values in those registers remaining constant).
void Watchdog_Feed(void) { /* NOT fiq safe! */
int irqStat;
asm volatile (
" mrs r0, cpsr\n"
" mov %0,r0\n" : "=r" (irqStat) : : "r0" );
if (128 & ~irqStat)
__ARMLIB_disableIRQ();
asm volatile (
"WDFEED = 0xE0000008\n"
" LDR r0, =WDFEED\n"
" MOV r1,#0xAA\n"
" MOV r2,#0x55\n"
" STRB r1,[r0]\n"
" STRB r2,[r0]\n" : : : "r0", "r1", "r2");
if (128 & ~irqStat)
__ARMLIB_enableIRQ();
}
Hope this helps,
Danish
--- In lpc2000@yahoogroups.com, "ah_sandiego" <ah_sandiego@...> wrote:> > Can someone post a simple example of C and inline ASM in a single > file. I use the LPC2148 but any LPC board example would be helpful. > > Thanks, > AH >
2006-04-07 by brendanmurphy37
In the long run, using in-line assembler is probably not a good idea. It is very compiler specific, and you need to have a good understanding of how the particular compiler interacts with the assembler. If you need to use assembler you can invariably do it in a separate function, callable from 'C' (or the other way round where assembler calls a 'C' function). Just make sure you stick to the ATPCS (ARM- Thumb Procedure Call Standard), which is very simple for simple functions, and you'll be OK (see ARM site for details on this). You don't mention why you're using assembler: if it's for efficiency reasons, try compiling with maximum optimisation first and taking a look at the code produced. Brendan --- In lpc2000@yahoogroups.com, "ah_sandiego" <ah_sandiego@...> wrote:
> > Can someone post a simple example of C and inline ASM in a single > file. I use the LPC2148 but any LPC board example would be helpful. > > Thanks, > AH >
2006-04-07 by ian.scanlon
--- In lpc2000@yahoogroups.com, "ah_sandiego" <ah_sandiego@...> wrote: > > Can someone post a simple example of C and inline ASM in a single > file. I use the LPC2148 but any LPC board example would be helpful. > > Thanks, > AH > Depending on the compiler optimization levels, inline asm has minimal benefit for size or speed. Inline asm also limits portability for hardware and compilers. Even if you think it will never be an issue... What are you goals for this? A few bytes? A save a bit of time- 50ns? 100ns? Access to a hardware specific feature or registers? It will be difficult to beat the compiler for speed and/or density. The ARM was designed for compilers and the compilers are very good at optimization. There are several good 'c' solutions but it really depends on what you are doing. "Function Inlining" (check your compiler options) will avoid the timer overhead of calling a function. This is from the IAR C reference: "Function inlining means that a simple function, whose definition is known at compile time, is integrated into the body of its caller to eliminate the overhead of the call. This optimization, which is performed at optimization level High, normally reduces execution time, but increases code size. The resulting code might also be difficult to debug." If it is execution speed you are after, time the C function with a some io bit toggling either side of the call with an oscilloscope. Then add up the execution time of your hand written instructions and compare.* Expect better results from the compiler code. If it is size, compare the size of the C function in the map file with the size of your hand written code.* If it is access to the hardware, use the compiler extensions or pragma. *(both of these techniques introduce some inaccuracy but the results will be close. Let's not start a debate on the finer points of measurement) ~Ian
2006-04-07 by Robert Adsett
Quoting "ian.scanlon" <scanlon.design@...>: > --- In lpc2000@yahoogroups.com, "ah_sandiego" <ah_sandiego@...> wrote: >> >> Can someone post a simple example of C and inline ASM in a single >> file. I use the LPC2148 but any LPC board example would be helpful. >> >> Thanks, >> AH >> > Depending on the compiler optimization levels, inline asm has minimal > benefit for size or speed. Inline asm also limits portability for > hardware and compilers. Even if you think it will never be an issue... Indeed, I've yet to see a good reason to use inline assembler on any processor and that's doubly true for the ARM. Robert
2006-04-07 by brendanmurphy37
Indeed! Which begs the question: Can anyone put forward a good argument (and example) for the use of in- line assembler for an ARM-based system? Personally, I can't think of one. Brendan --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> > Indeed, I've yet to see a good reason to use inline assembler on any processor
> and that's doubly true for the ARM. > > Robert >
2006-04-07 by rtstofer
OK, I'll bite! I have used inline assembly in cc5x (sort of C for the PIC) to control exactly the number of cycles in a delay routine. No active interrupts in this code. I suppose it could be done in C but that would change with compilers and optimization. There are times... Not many, perhaps, but they do exist. Richard
2006-04-08 by jayasooriah
Hello AH. Thanks for your very short and simple question:
--- In lpc2000@yahoogroups.com, "ah_sandiego" <ah_sandiego@...> wrote:
> Can someone post a simple example of C and inline ASM in a single
> file. I use the LPC2148 but any LPC board example would be helpful.
If you wanted to branch to an address stored in a variable (pointer),
"addr" in arm or thumb mode as appropriate, you could use the
following statement:
> asm volatile (" bx %0" : : "r" (addr));
The ":" syntax in ASM constructs is specific to GCC (AFAIK) and it is
used as a way of getting the instruction generator to do what you want
it to do. The following reference is a good start:
http://www.ethernut.de/en/documents/arm-inline-asm.html
Hope this helps.
Jaya2006-04-08 by Robert Adsett
At 10:31 PM 4/7/2006 +0000, rtstofer wrote: >OK, I'll bite! I have used inline assembly in cc5x (sort of C for the >PIC) to control exactly the number of cycles in a delay routine. No >active interrupts in this code. I suppose it could be done in C but >that would change with compilers and optimization. An argument for assembly yes, but I don't see it as an argument for inline assembly. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-09 by Boris Estudiez
On 07/04/2006 at 21:29:55 -0400 Robert Adsett Wrote: > At 10:31 PM 4/7/2006 +0000, rtstofer wrote: > > >OK, I'll bite! I have used inline assembly in cc5x (sort of C for the > >PIC) to control exactly the number of cycles in a delay routine. No > >active interrupts in this code. I suppose it could be done in C but > >that would change with compilers and optimization. > > An argument for assembly yes, but I don't see it as an argument for inline > assembly. > > Robert > One advantage of inline assembly is that you don't have to worry about of the calling convention used by the compiler (such as ATPCS or APCS). Regards, Boris Estudiez.- -- Contacteme en: * Mail(1): stk@... * Mail(2): 43824@... * Mail(3): slicetex@... * Website: http://stk.freeshell.org EOF
2006-04-09 by Stephen Pelc
> Robert Adsett <subscriptions@...> > Indeed, I've yet to see a good reason to use inline > assembler on any processor and that's doubly true for the > ARM. When you need efficient access to ideas not supported by the programming language. These are usually things like the state of the Carry and Overflow flags. Using assembler rather than high level kluges can improve performance by factors of 2..5, depending on CPU. A client of ours performs financial calculations using 128 bit integers. The difference between their app and the competition's floating point app for part of the Hong Kong airport construction was US dollars 10,000,000. The on-screen recalculation performance was important, so they coded the quad- integer routines. Stephen -- Stephen Pelc, stephen@... MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads
2006-04-09 by Robert Adsett
At 12:56 PM 4/9/06 +0100, Stephen Pelc wrote: > > Robert Adsett <subscriptions@...> > > > Indeed, I've yet to see a good reason to use inline > > assembler on any processor and that's doubly true for the > > ARM. > >When you need efficient access to ideas not supported by the >programming language. These are usually things like the state of >the Carry and Overflow flags. Using assembler rather than high >level kluges can improve performance by factors of 2..5, >depending on CPU. > >A client of ours performs financial calculations using 128 bit >integers. The difference between their app and the competition's >floating point app for part of the Hong Kong airport >construction was US dollars 10,000,000. The on-screen >recalculation performance was important, so they coded the quad- >integer routines. OK, but how is that an argument for making the assembler inline? I do see uses for assembler, I am just of the opinion, informed by my experiences, that inline assembler causes more problems than it fixes. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-09 by Robert Adsett
At 11:50 PM 4/8/06 -0300, Boris Estudiez wrote: >On 07/04/2006 at 21:29:55 -0400 Robert Adsett Wrote: > > At 10:31 PM 4/7/2006 +0000, rtstofer wrote: > > > > >OK, I'll bite! I have used inline assembly in cc5x (sort of C for the > > >PIC) to control exactly the number of cycles in a delay routine. No > > >active interrupts in this code. I suppose it could be done in C but > > >that would change with compilers and optimization. > > > > An argument for assembly yes, but I don't see it as an argument for inline > > assembly. > > > > Robert > > > >One advantage of inline assembly is that you don't have to worry >about of the calling convention used by the compiler (such as ATPCS >or APCS). An argument yes, but I don't think a good one. In the same time, or less, that it takes to figure all the peculiarities of how inline interacts with the main code (if indeed it's documented even close to properly) you can learn the calling conventions of the compiler and do a 'proper' assembly routine. And the resulting code is a whole lot less fragile. If you are serious about embedded work then at some point you have to learn the calling conventions anyway so you've not saved any effort. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-09 by brendanmurphy37
Robert, I agree completely. I'd much rather spend time figuring out the calling conventions for a particular platform (which as you point out, you need to know anyway) than learning some obscure syntax and set of rules for some compiler-specific non-standard feature like in- line assembler. Until you're faced with it, it's too easy to ignore portability issues. However, even a brief review of the problems people have reported to this group over the past while will show how common those issues are. In-line assembler, "__irq" and "__fiq" function modifiers, bit-masks to access hardware registers, take your pick. I think they're all best avoided. To take another example given recently, I can easily imagine implementing a set of math functions for 128-bit numbers in assembler for efficiency reasons, and calling them from some application. When you want to (or more likely are forced to) move to a different target platform, all you have to do is re-code the small number of lower-most level assembler functions, instead of re- writing an entire application. None of this is to say that any of these features don't or can't be made work, and if it suits then fine. Just be aware that most of them have more than their fair share of capacity to bite at some stage down the line. Finally, to the original questioner that started this thread I'd recommend reading the relevant compiler's documentation for an example, as it is typically compiler dependent on how it operates. Brendan --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > > At 11:50 PM 4/8/06 -0300, Boris Estudiez wrote: > >On 07/04/2006 at 21:29:55 -0400 Robert Adsett Wrote: > > > At 10:31 PM 4/7/2006 +0000, rtstofer wrote: > > > > > > >OK, I'll bite! I have used inline assembly in cc5x (sort of C for the > > > >PIC) to control exactly the number of cycles in a delay routine. No > > > >active interrupts in this code. I suppose it could be done in C but > > > >that would change with compilers and optimization. > > > > > > An argument for assembly yes, but I don't see it as an argument for inline > > > assembly. > > > > > > Robert > > > > > > >One advantage of inline assembly is that you don't have to worry > >about of the calling convention used by the compiler (such as ATPCS > >or APCS). > > An argument yes, but I don't think a good one. In the same time, or less, > that it takes to figure all the peculiarities of how inline interacts with > the main code (if indeed it's documented even close to properly) you can > learn the calling conventions of the compiler and do a 'proper' assembly > routine. And the resulting code is a whole lot less fragile. > > If you are serious about embedded work then at some point you have to learn > the calling conventions anyway so you've not saved any effort. > > Robert > > " 'Freedom' has no meaning of itself. There are always restrictions, be > they legal, genetic, or physical. If you don't believe me, try to chew a
> radio signal. " -- Kelvin Throop, III > http://www.aeolusdevelopment.com/ >
2006-04-10 by jayasooriah
Dear Robert, let me address an advocacy issue here ... --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > I do see uses for assembler, I am just of the opinion, informed > by my experiences, that inline assembler causes more problems > than it fixes. My experience tells me otherwise. Inline assembler has its place just like any other feature *provided* one understands how to use it before one does. If you can give us some examples of where it has caused more problems than it fixed, I might be able to explain what I think went wrong. The original question that started this thread was quite simple and specific. A couple responded to the point with examples. It is interesting those who go on and on against inline assembly have not come up with examples. My guess is that these posters do not know enough enough about inline assembly to use it effectively or to come up with examples of their own. Jaya
2006-04-10 by brendanmurphy37
Jaya, I think your suggestion is misplaced: why would you think that anyone pointing out the pitfalls of a particular feature doesn't understand it? Somone asked for an example of a feature, to which there were three basic responses: - Provide an example, as asked. This has the merit of answering the direct question, but is of limited use otherwise - Point out that the feature is compiler-specific, and it's best to look up the particular compiler's documentation. Personally, I think it is always more useful if someone looking for information is told where to find it themselves rather than being spoon-fed the answer. Hence, I'd suggest this is actually a more useful answer. - Point out some of the pitfalls of the feature, the main one being that it is a very non-standard, non-portable feature. This to my mind is more useful again, as it puts forward people's experience from which people can benefit, and provides information that is not readily available elsewhere. There's nothing inherently wrong with the feature, just that there is usually (always?) a less error prone and simple way of achieving the same result. As for an example of the pitfalls, I gave one in my last post, based on a suggested use of the feature from a previous poster (to implement 128-bit numbers). You don't have to take anyone's advice or learn from their experience: there's noone forcing it on anyone. You certainly don't have to use it as yet another opportunity to disparage other's hard- one experience, insult their capabilities and promote yourself yet again as the font of all knowledge. Best wishes Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > Dear Robert, let me address an advocacy issue here ... > > --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@> wrote: > > I do see uses for assembler, I am just of the opinion, informed > > by my experiences, that inline assembler causes more problems > > than it fixes. > > My experience tells me otherwise. Inline assembler has its place just > like any other feature *provided* one understands how to use it before > one does. > > If you can give us some examples of where it has caused more problems > than it fixed, I might be able to explain what I think went wrong. > > The original question that started this thread was quite simple and > specific. A couple responded to the point with examples. > > It is interesting those who go on and on against inline assembly have > not come up with examples. My guess is that these posters do not know > enough enough about inline assembly to use it effectively or to come
> up with examples of their own. > > Jaya >
2006-04-10 by Stephen Pelc
> From: Robert Adsett <subscriptions@...> > OK, but how is that an argument for making the assembler inline? I do see > uses for assembler, I am just of the opinion, informed by my experiences, > that inline assembler causes more problems than it fixes. If I only needed a few instructions, and the register usage is well documented, then inline assembler is less of a maintenance nightmare than an external routine in another file. Stephen -- Stephen Pelc, stephen@... MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads
2006-04-10 by jayasooriah
--- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...> wrote: > I think your suggestion is misplaced: why would you think that > anyone pointing out the pitfalls of a particular feature doesn't > understand it? Your interpretation is misplaced. I asked Robert for an example of inline assembler that "causes more problems than it fixes". If you have one, put it up for discussion. If not, I have nothing more to say to you. Jaya
2006-04-10 by Paul Curtis
Jaya,
> Your interpretation is misplaced.
>
> I asked Robert for an example of inline assembler that
> "causes more problems than it fixes".
>
> If you have one, put it up for discussion. If not, I have
> nothing more to say to you.
You're acting like a spoilt child.
Something concrete:
void do_something_nasty(void)
{
// I need to do something fast without a call, I need a register,
// so I'll pick r5 as the/ code generator seems it's not using that
// one when I run it under the debugger.
asm("ldr r5, =0x12345678");
// Now do soemthing with r5 because I did something above.
}
There is just so much wrong with the above it's untrue. I'm happy to
say I've never used inline assemler. If you need that crap, it's
because you have a toolset that doesn't have intrinsics for what you
want to do.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors2006-04-10 by brendanmurphy37
Jaya, I've already provided an example of where it can cause problems: If you have an application that makes extensive use of processing on 128-bit numbers using in-line assembler (as someone suggested) , what happens when you want to port that application to another environment? Bit of a problem, I think. All I suggested for this case was to implement a few core functions in assembler in a separate compilation unit (i.e. file) and re-code that for the new environment. No need to touch the application itself. Jaya, I'm well aware that others take a different view and have different experiences to draw on and will come to different conclusions about how to use particular features. All I'm and others are doing is pointing out some potential pitfalls. There's no need to be abusive about it! Brendan P.S. you might want to correct some of the factual errors in your own writings on your Web site, before attacking others so aggressively. --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
> > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@> > wrote: > > > I think your suggestion is misplaced: why would you think that > > anyone pointing out the pitfalls of a particular feature doesn't > > understand it? > > Your interpretation is misplaced. > > I asked Robert for an example of inline assembler that "causes more > problems than it fixes". > > If you have one, put it up for discussion. If not, I have nothing > more to say to you. > > Jaya >
2006-04-10 by jayasooriah
--- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...> wrote: > I've already provided an example of where it can cause problems: Sorry I must have missed it becuase it was not clear. > If you have an application that makes extensive use of processing > on 128-bit numbers using in-line assembler (as someone suggested), > what happens when you want to port that application to another > environment? Bit of a problem, I think. Which environment are you switching to? What is the problem? Examples of simple needs where inline assembly meets the requiremnt well have been presented here. If there is a problem, I like to know what it is in specific terms. Jaya
2006-04-10 by brendanmurphy37
Jaya, I fear I'm repeating myself: the problem isn't that in-line assembler doesn't work, the problem is that it is completely non-standard and non-portable. If you insist on using it, when you move to a new platform you have to re-write the application (as in the hypothetical example I presented). Better by far I think to follow the well-known technique of isolating the platform-specific parts (i.e. the assembler) into a small separate compilation unit (i.e. assembler source file), and providing different versions of that file for different platforms. In other words, rather than mixing portable with non-portable code (as in-line assembler does), separate it out. Now if you believe portablility between environments isn't an issue for you, I suggest you read back over some recent posts to see the difficulties encountered by those attempting to port code to ARM when non-portable features have been used. I'm sure the authors would have said when the code was 1st produced "I doin't have to worry about portablility". I really can't think of another way of saying this, though I could supply a real example if you or anyone else is really interested. Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@> > wrote: > > > I've already provided an example of where it can cause problems: > > Sorry I must have missed it becuase it was not clear. > > > If you have an application that makes extensive use of processing > > on 128-bit numbers using in-line assembler (as someone suggested), > > what happens when you want to port that application to another > > environment? Bit of a problem, I think. > > Which environment are you switching to? What is the problem? > > Examples of simple needs where inline assembly meets the requiremnt > well have been presented here. If there is a problem, I like to know
> what it is in specific terms. > > Jaya >
2006-04-10 by jayasooriah
--- In lpc2000@yahoogroups.com, "Paul Curtis" <plc@...> wrote:
> You're acting like a spoilt child.
I will ignore this comment knowing you for what you are :)
> Something concrete:
>
> void do_something_nasty(void)
> {
> // I need to do something fast without a call, I need a register,
> // so I'll pick r5 as the/ code generator seems it's not using that
> // one when I run it under the debugger.
> asm("ldr r5, =0x12345678");
>
> // Now do soemthing with r5 because I did something above.
> }
Excellent example of INCORRECT use of inline assembly.
You want to use "r5" for your own purpose but have chosen not to tell
the compiler. You appear not to know, or to have forgotten, that the
compiler is responsible for allocation of registers.
Although I question the validity your particular requirement (as I can
gather from your comments), the compiler nonetheless will accodomate
your requirement (subject to reasonable limits) if you were to include
the following declaraction in your function:
> register int r5 asm ("r5");
If you do not tell the compiler you are using a register that it also
uses, you should not be surprised at what happens as a result.
While the reference to "r5" in the ASM statement may be obvious to you
as a human, the compiler does not parse this string at all.
Jaya2006-04-10 by Paul Curtis
Jaya,
> > You're acting like a spoilt child.
>
> I will ignore this comment knowing you for what you are :)
We all have opinions about each other here. You don't know what I am,
I've never met you, so how you know what I am is just more supposition
on your part, just like your CRP "facts".
> > Something concrete:
> >
> > void do_something_nasty(void)
> > {
> > // I need to do something fast without a call, I need a register,
> > // so I'll pick r5 as the/ code generator seems it's not
> using that
> > // one when I run it under the debugger.
> > asm("ldr r5, =0x12345678");
> >
> > // Now do soemthing with r5 because I did something above.
> > }
>
> Excellent example of INCORRECT use of inline assembly.
Yes, of course it is incorrect, that's the whole f'ing point.
> You want to use "r5" for your own purpose but have chosen not
> to tell the compiler. You appear not to know, or to have
> forgotten, that the compiler is responsible for allocation of
> registers.
Too bloody true. The whole point is that customers write this shit and
don't have a clue. It might work when debugging, but it won't work when
you turn the optimizer on. And it won't work when you change the
function.
> Although I question the validity your particular requirement
> (as I can gather from your comments), the compiler
> nonetheless will accodomate your requirement (subject to
> reasonable limits) if you were to include the following
> declaraction in your function:
>
> > register int r5 asm ("r5");
>
> If you do not tell the compiler you are using a register that
> it also uses, you should not be surprised at what happens as a result.
>
> While the reference to "r5" in the ASM statement may be
> obvious to you as a human, the compiler does not parse this
> string at all.
Yawn. I know all this. This is an example of stuff customers will
write. The point is that customers write this crap without knowing what
they're doing. It's not enough that they can screw themselves with
non-portable C, now inline assembler has given them yet another
dimension to screw around and "solve" problems with. The problems, of
course, come when somebody has to maintain it, move it to a new
compiler, or even move to a new architecture as has been pointed out.
In short, I have never used inline assembler and I see no reason to
start using it. Our own compilers do not offer this feature and with
the wealth of customers we have, each time they ask for it I show them
why they don't need it.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors2006-04-10 by jayasooriah
--- In lpc2000@yahoogroups.com, "Paul Curtis" <plc@...> wrote: > In short, I have never used inline assembler and I see no reason to > start using it. Our own compilers do not offer this feature and with > the wealth of customers we have, each time they ask for it I show them > why they don't need it. I appreciate the need to use inline assembly features of GCC in embedded systems especially. I find them very handy to meet that odd requirement that takes a lot of contortion to do otherwise. The benefit I find in using inline assembly for such reasons is that not only does it avoid having open up the interface (by creating an external call), but also makes the code more readable, and in many cases also compact and efficient. Jaya
2006-04-10 by brendanmurphy37
Jaya,
I have to say, you're a great source of amusement and entertainment!
Someone presents an example of incorrect usage, and you go to great
lengths to show how incorrect it is! Doh!
I haven't enjoyed myself so much since reading about your "surprise"
interrupts. Based as they are on a complete misunderstanding of how
ARM's handle interrupts, it's no wonder you were surprised.....
Keep up the good work!
Brendan
--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
>
> --- In lpc2000@yahoogroups.com, "Paul Curtis" <plc@> wrote:
>
> > You're acting like a spoilt child.
>
> I will ignore this comment knowing you for what you are :)
>
> > Something concrete:
> >
> > void do_something_nasty(void)
> > {
> > // I need to do something fast without a call, I need a
register,
> > // so I'll pick r5 as the/ code generator seems it's not using
that
> > // one when I run it under the debugger.
> > asm("ldr r5, =0x12345678");
> >
> > // Now do soemthing with r5 because I did something above.
> > }
>
> Excellent example of INCORRECT use of inline assembly.
>
> You want to use "r5" for your own purpose but have chosen not to
tell
> the compiler. You appear not to know, or to have forgotten, that
the
> compiler is responsible for allocation of registers.
>
> Although I question the validity your particular requirement (as I
can
> gather from your comments), the compiler nonetheless will accodomate
> your requirement (subject to reasonable limits) if you were to
include
> the following declaraction in your function:
>
> > register int r5 asm ("r5");
>
> If you do not tell the compiler you are using a register that it
also
> uses, you should not be surprised at what happens as a result.
>
> While the reference to "r5" in the ASM statement may be obvious to
you> as a human, the compiler does not parse this string at all. > > > Jaya >
2006-04-10 by Stephen Pelc
> From: "brendanmurphy37" <brendan.murphy@...> > I fear I'm repeating myself: the problem isn't that in-line assembler > doesn't work, the problem is that it is completely non-standard and > non-portable. Especially in embedded work, device drivers aren't portable whatever they are written in. > If you insist on using it, when you move to a new platform you have > to re-write the application (as in the hypothetical example I > presented). > > Better by far I think to follow the well-known technique of isolating > the platform-specific parts (i.e. the assembler) into a small > separate compilation unit (i.e. assembler source file), and providing > different versions of that file for different platforms. In other > words, rather than mixing portable with non-portable code (as in-line > assembler does), separate it out. That's a consequence of working in C/C++. Other languages handle things differently. When I look at where MPE (as opposed to its clients) uses in- line assembly, we find it in device-specific drivers, e.g. UART and Ethernet drivers, and in CPU specific sections, e.g. schedulers, where we are striving for performance. In our world, interrupt latency and task-switching speed really matter, regardless of CPU performance - the faster the CPU, the more we are asked to do with it. Paul's comment about intrinsics is relevant, but I would really hate to have to guarantee that a client won't find another useful one that we haven't already provided. Today I had a tech- support conversation about bank-switched RAM ... he had found another way of perverting the hardware/software trade-offs in our standard libraries. In-line assembler isn't evil, you just have to be able to make a good case for it, and that case has to include maintenance and portability. Stephen -- Stephen Pelc, stephen@... MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads
2006-04-10 by brendanmurphy37
Stephen, I don't necessarily agree with all you say, but I like your sensible conclusion, that hopefully everyone can agree on: --- In lpc2000@yahoogroups.com, "Stephen Pelc" <stephen@...> wrote: > In-line assembler isn't evil, you just have to be able to make a > good case for it, and that case has to include maintenance and > portability. > > Stephen By the way, why is that that some people feel the need to inisist their own view is 100% correct and nobody's else views, experience or opinion matters? I find I learn something from most contributors here, even if I don't agree with their conclusions. Brendan
2006-04-10 by jayasooriah
Brendan Please refrain from disrupting the thread with such digressions. If you do not like my characterisation of interrupts and feel you must say something, raise it as a separate thread. If I see a question that has not already been answered I usually respond. Jaya --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...> wrote:
> > > Jaya, > > I have to say, you're a great source of amusement and entertainment! > > Someone presents an example of incorrect usage, and you go to great > lengths to show how incorrect it is! Doh! > > I haven't enjoyed myself so much since reading about your "surprise" > interrupts. Based as they are on a complete misunderstanding of how > ARM's handle interrupts, it's no wonder you were surprised..... > > Keep up the good work! > > Brendan
2006-04-10 by brendanmurphy37
Jaya, Sorry - I'll ask for permission next time, before making any comments. I'd hate to upset you. My comment was made in passing and in jest. If you're interested in where your misunderstanding of ARM interrupts arises, you can let me know in a separate thread. Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > Brendan > > Please refrain from disrupting the thread with such digressions. > > If you do not like my characterisation of interrupts and feel you must > say something, raise it as a separate thread. If I see a question > that has not already been answered I usually respond. > > Jaya > > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@> > wrote: > > > > > > Jaya, > > > > I have to say, you're a great source of amusement and entertainment! > > > > Someone presents an example of incorrect usage, and you go to great > > lengths to show how incorrect it is! Doh! > > > > I haven't enjoyed myself so much since reading about your "surprise" > > interrupts. Based as they are on a complete misunderstanding of how
> > ARM's handle interrupts, it's no wonder you were surprised..... > > > > Keep up the good work! > > > > Brendan >
2006-04-10 by Michael Rubitschka
Guys Make code not war! ;-) Cheers Michael
>From: "brendanmurphy37" <brendan.murphy@...> >Reply-To: lpc2000@yahoogroups.com >To: lpc2000@yahoogroups.com >Subject: [lpc2000] Re: Example of C and inline ASM in a file? >Date: Mon, 10 Apr 2006 14:52:08 -0000 > > >Jaya, > >Sorry - I'll ask for permission next time, before making any >comments. I'd hate to upset you. > >My comment was made in passing and in jest. > >If you're interested in where your misunderstanding of ARM interrupts >arises, you can let me know in a separate thread. > >Brendan > >--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > > > Brendan > > > > Please refrain from disrupting the thread with such digressions. > > > > If you do not like my characterisation of interrupts and feel you >must > > say something, raise it as a separate thread. If I see a question > > that has not already been answered I usually respond. > > > > Jaya > > > > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@> > > wrote: > > > > > > > > > Jaya, > > > > > > I have to say, you're a great source of amusement and >entertainment! > > > > > > Someone presents an example of incorrect usage, and you go to >great > > > lengths to show how incorrect it is! Doh! > > > > > > I haven't enjoyed myself so much since reading about >your "surprise" > > > interrupts. Based as they are on a complete misunderstanding of >how > > > ARM's handle interrupts, it's no wonder you were surprised..... > > > > > > Keep up the good work! > > > > > > Brendan > > > > > > >
2006-04-10 by brendanmurphy37
Michael, Your right, of course. In my defence, I find it hard not to respond to the ongoing insults and abusive comments from certain quarters. I'll stop now, though: genuine apologies all round. Brendan --- In lpc2000@yahoogroups.com, "Michael Rubitschka" <rubitschka@...> wrote:
> > Guys > > Make code not war! ;-) > > Cheers > Michael >
2006-04-10 by Steve Franks
At risk of being flamed myself, there are at least 3 people on this list who consistently contribute a significant amount of technical info, along with a singificant amount of unpleasant philosophy. I can see that they all desire to make a contribution, and all hold valid points at times. Each at times asserts things that are either not well thought out or reseached at times, just like the rest of us. Each has made comments that I respect and have increased my understanding of the Arm/Lpc. Please keep that in mind when assaulting eachother, guys. You all start out on the defensive because this has been going on too long. Please do not make the mistake of my home government (not to confused with my home people) and assert that increased violence will somehow secure peace. ~Steve [Non-text portions of this message have been removed]
2006-04-10 by jayasooriah
This is an add-on to Danish Ali's contribution to AH's original question.
I hope it will show how one can use GCC's inline assembly features in
an effective way to produce code that is both readable *and* efficient.
I am not sure if I could have handcrafted the assembler code to be
that efficient, considering the three primitives I created in the
header file are not specific to the WATCHDOG or the LPC.
Sorry it is longish but striking a balance between being brief and
clear is not always easy considering the nature of this audience.
Enjoy!
Jaya
PS: All you need to know about inline assembly for purposes of
understanding this tutorial can be found at:
http://www.ethernut.de/en/documents/arm-inline-asm.html
I am happy to explain finer points if anyone wants to know more.
--- In lpc2000@yahoogroups.com, "Danish Ali" <danish@...> wrote:
> Attached is an example of something that gcc likes (as
> supplied with Rowley Crossworks).
> void Watchdog_Feed(void) { /* NOT fiq safe! */
> int irqStat;
> asm volatile (
> " mrs r0, cpsr\n"
> " mov %0,r0\n" : "=r" (irqStat) : : "r0" );
> if (128 & ~irqStat)
> __ARMLIB_disableIRQ();
> asm volatile (
> "WDFEED = 0xE0000008\n"
> " LDR r0, =WDFEED\n"
> " MOV r1,#0xAA\n"
> " MOV r2,#0x55\n"
> " STRB r1,[r0]\n"
> " STRB r2,[r0]\n" : : : "r0", "r1", "r2");
> if (128 & ~irqStat)
> __ARMLIB_enableIRQ();
> }
I wrote a header file, foo.h with three primitives to do what the
above code does. This is included at the end of this post E&OE.
I wrote foo.c which includes foo.h (and other header files), and in
which I invoked the equivalent of the Watchdog_Feed() function as follows:
> feedSeq(&WATCHDOG);
I used GCC to generate the optimised assembler source file as follows:
> arm-esdk-gcc -Wall -Werror -O3 -S foo.c
The assembler output for the feedSeq() call I got is as follows
(comments added)
> mov r0, #128 @ 0x80 (IRQ BIT)
> mov lr, #-536870912 @ 0xe0000000 (&WATCHDOG)
> mrs ip, cpsr @ save copy of CPSR
> orr r0, r0, ip @ set IRQ bit in temp
> msr cpsr, r0 @ disable interrupts
> mov r0, #170 @ 0xAA (feed byte #1)
> mov r3, #85 @ 0x55 (feed byte #2)
> str r0, [lr, #0] @ WATCHDOG FEED #1
> str r3, [lr, #0] @ WATCHDOG FEED #2
> msr cpsr, ip @ restore interrupts
The header file where I make use of inline functions and inline
assembly to achieve the above result follows. Note that I do not
refer to any register by name, but let the compiler tell me what
register to use.
The name of the game here is not to override the compiler with your
choices, but to tell the compiler (in the nicest way possible) what
you want it to do for you ... to produce the code shown above.> // ===========================================================
> // 'irqMask'
>
> // mask either irq or fiq bit
> inline int
> irqMask(mask)
> {
> int mode;
>
> // set mask bit
> asm volatile
> (
> "mrs\t%0, cpsr" "\n\t"
> "orr\t%1, %1, %0" "\n\t"
> "msr\tcpsr, %1"
> : "=&r" (mode)
> : "r" (mask)
> );
>
> // previous mode
> return (mode);
>
> } // irqMask()
>
> // End of 'irqMask'
> // ===========================================================
>
>
> // ===========================================================
> // 'irqMode'
>
> // restore mode and irq bits
> inline void
> irqMode(int mode)
> {
>
> // restore CPSR
> asm volatile ("msr\tcpsr, %0" : : "r" (mode));
>
> } // irqMode()
>
> // End of 'irqMode'
> // ===========================================================
>
>
> // ===========================================================
> // 'feedSeq'
>
> // atomic feed sequence
> inline void
> feedSeq(int *loc)
> {
> int mode;
>
> // enter critical section
> mode = irqMask(IRQ_BIT);
>
> // atomic feed sequence
> asm volatile
> (
> "str\t%1, [%0, #0]" "\n\t"
> "str\t%2, [%0, #0]"
> :
> : "r" (loc), "r" (0xaa), "r" (0x55)
> : "r1", "r2"
> );
>
> // leave critical section
> irqMode(mode);
>
> } // feedSeq()
>
> // End of 'feedSeq'
> // ===========================================================2006-04-10 by jayasooriah
Sorry for typo error in my tutorial. Pleae replace WATCHDOG with
WDFEED. E&OE comes in handy at times like this :)
--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
>
> This is an add-on to Danish Ali's contribution to AH's original
question.
>
> I hope it will show how one can use GCC's inline assembly features in
> an effective way to produce code that is both readable *and* efficient.
>
> I am not sure if I could have handcrafted the assembler code to be
> that efficient, considering the three primitives I created in the
> header file are not specific to the WATCHDOG or the LPC.
>
> Sorry it is longish but striking a balance between being brief and
> clear is not always easy considering the nature of this audience.
>
> Enjoy!
>
> Jaya
>
> PS: All you need to know about inline assembly for purposes of
> understanding this tutorial can be found at:
>
> http://www.ethernut.de/en/documents/arm-inline-asm.html
>
> I am happy to explain finer points if anyone wants to know more.
>
> --- In lpc2000@yahoogroups.com, "Danish Ali" <danish@> wrote:
>
> > Attached is an example of something that gcc likes (as
> > supplied with Rowley Crossworks).
>
> > void Watchdog_Feed(void) { /* NOT fiq safe! */
> > int irqStat;
> > asm volatile (
> > " mrs r0, cpsr\n"
> > " mov %0,r0\n" : "=r" (irqStat) : : "r0" );
> > if (128 & ~irqStat)
> > __ARMLIB_disableIRQ();
> > asm volatile (
> > "WDFEED = 0xE0000008\n"
> > " LDR r0, =WDFEED\n"
> > " MOV r1,#0xAA\n"
> > " MOV r2,#0x55\n"
> > " STRB r1,[r0]\n"
> > " STRB r2,[r0]\n" : : : "r0", "r1", "r2");
> > if (128 & ~irqStat)
> > __ARMLIB_enableIRQ();
> > }
>
> I wrote a header file, foo.h with three primitives to do what the
> above code does. This is included at the end of this post E&OE.
>
> I wrote foo.c which includes foo.h (and other header files), and in
> which I invoked the equivalent of the Watchdog_Feed() function as
follows:>
> > feedSeq(&WATCHDOG);
>
> I used GCC to generate the optimised assembler source file as follows:
>
> > arm-esdk-gcc -Wall -Werror -O3 -S foo.c
>
> The assembler output for the feedSeq() call I got is as follows
> (comments added)
>
> > mov r0, #128 @ 0x80 (IRQ BIT)
> > mov lr, #-536870912 @ 0xe0000000 (&WATCHDOG)
> > mrs ip, cpsr @ save copy of CPSR
> > orr r0, r0, ip @ set IRQ bit in temp
> > msr cpsr, r0 @ disable interrupts
> > mov r0, #170 @ 0xAA (feed byte #1)
> > mov r3, #85 @ 0x55 (feed byte #2)
> > str r0, [lr, #0] @ WATCHDOG FEED #1
> > str r3, [lr, #0] @ WATCHDOG FEED #2
> > msr cpsr, ip @ restore interrupts
>
>
> The header file where I make use of inline functions and inline
> assembly to achieve the above result follows. Note that I do not
> refer to any register by name, but let the compiler tell me what
> register to use.
>
> The name of the game here is not to override the compiler with your
> choices, but to tell the compiler (in the nicest way possible) what
> you want it to do for you ... to produce the code shown above.
>
> > // ===========================================================
> > // 'irqMask'
> >
> > // mask either irq or fiq bit
> > inline int
> > irqMask(mask)
> > {
> > int mode;
> >
> > // set mask bit
> > asm volatile
> > (
> > "mrs\t%0, cpsr" "\n\t"
> > "orr\t%1, %1, %0" "\n\t"
> > "msr\tcpsr, %1"
> > : "=&r" (mode)
> > : "r" (mask)
> > );
> >
> > // previous mode
> > return (mode);
> >
> > } // irqMask()
> >
> > // End of 'irqMask'
> > // ===========================================================
> >
> >
> > // ===========================================================
> > // 'irqMode'
> >
> > // restore mode and irq bits
> > inline void
> > irqMode(int mode)
> > {
> >
> > // restore CPSR
> > asm volatile ("msr\tcpsr, %0" : : "r" (mode));
> >
> > } // irqMode()
> >
> > // End of 'irqMode'
> > // ===========================================================
> >
> >
> > // ===========================================================
> > // 'feedSeq'
> >
> > // atomic feed sequence
> > inline void
> > feedSeq(int *loc)
> > {
> > int mode;
> >
> > // enter critical section
> > mode = irqMask(IRQ_BIT);
> >
> > // atomic feed sequence
> > asm volatile
> > (
> > "str\t%1, [%0, #0]" "\n\t"
> > "str\t%2, [%0, #0]"
> > :
> > : "r" (loc), "r" (0xaa), "r" (0x55)
> > : "r1", "r2"
> > );
> >
> > // leave critical section
> > irqMode(mode);
> >
> > } // feedSeq()
> >
> > // End of 'feedSeq'
> > // ===========================================================
>2006-04-10 by brendanmurphy37
Jaya, In the interests of following your lead and sticking to positive rather than negative contributions, some may find the following example useful too. It is actually a very similar example, based on a `C' API used by an RTOS I was involved in a while ago. The ARM implementation is as follows: /* * Disable/Restore interrupt processing * * Use as: * int disabled = HwIntrDisable(); * /* Critical section that needs interrupts OFF */ * .... * HwIntrRestore(disabled); */ HwIntrDisable: mrs r1, cpsr /* get CPSR into work register */ mov r0, r1 /* return copy of original CPSR to caller */ orr r1, r1, #0x80 msr cpsr_c, r1 /* update CPSR with I=1 */ bx lr /* return to caller */ HwIntrRestore: msr cpsr_c, r0 /* update CPSR with value supplied by caller */ bx lr /* return to caller */ You'll notice they can be called from Thumb mode as well. There are versions for NEC NV850, MIPS and (used for development, debug and test) Win32 (the Win32 version is coded in `C' and uses critical sections). The main-body of the RTOS itself is 100% ANSI `C' and just needs a compile to get it up on a new platform, once the functions above and any other assembler has been written (about 10-50 lines, depending on platform). Although this portability is useful, the biggest win we found with this approach was the speed of development and ease of maintenance. Basically, our experience is that separating out portable from non-portable code will generally simplify ongoing maintenance and support. This helps guarentee high-quality software which we regard as being far more important than saving one ot two cycles where it won't be noticed in any case. Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > This is an add-on to Danish Ali's contribution to AH's original question. > > I hope it will show how one can use GCC's inline assembly features in > an effective way to produce code that is both readable *and* efficient. >
2006-04-11 by Robert Adsett
At 10:15 AM 4/10/2006 +0100, Stephen Pelc wrote: > > From: Robert Adsett <subscriptions@...> > > OK, but how is that an argument for making the assembler inline? I do see > > uses for assembler, I am just of the opinion, informed by my experiences, > > that inline assembler causes more problems than it fixes. > >If I only needed a few instructions, and the register usage is >well documented, then inline assembler is less of a maintenance >nightmare than an external routine in another file. There. I think, we will just have to disagree. I've found the reverse to be true in my experience. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-11 by Bruce Paterson
> In-line assembler isn't evil, you just have to be able to > make a good case for it, and that case has to include > maintenance and portability. I'll agree with this conclusion. In most embedded applications I avoid it for two reasons: 1) Portability issues. I often find myself re-using code again on another project/environment, even if I didn't expect to initially. 2) Learning curve. Inline assembler means you have to learn the syntax, probably study up on how to reserve the registers you need or find out what the compiler doesn't use. If it doesn't use it, you need to then be careful that your own interrupt routines are saving all the context they have to (especially if you use inline in them too). All in all, there are certainly more chances to stuff up with inline unless you've gone into it properly. That said, I have had application where inline was very handy. It was a gcc C compiler for a motorola DSP. The DSP assembler allowed many instructions in the one line, and the inline syntax was powerful enough to support this. The C compiler itself rarely generated code that was that smart. If a time critical task was big enough you were better off using an assembler subroutine (but for this also you have to be aware of the C compiler calling and return methods and what has to be saved). For simple things the inline was very useful (eg. Divide by a constant was one I remember using where it was more efficient to multiply by the reciprical of the constant fractionally). I wrote a fixed-point complex number library that was a mixture of C, inline and assembly routines. The efficiency argument only really applies where the routine calling overhead is large compared to the task your assembly is performing. Interestingly this library was ported....by rewriting entirely in C with no regard for efficiency. We wanted to test all the higher level algorithms on the PC where it was much easier to develop at the time than on the DSP. So, there is a case for inline in some specific applications, where the case can be made. Even when it can, try to isolate the inline into one easily replaceable library which you can unplug. There is no justifcation for inline assembly in main.c ! It all comes down to how you design your project from the start. Cheers, Bruce
2006-04-11 by Robert Adsett
At 02:43 PM 4/10/2006 +0100, Stephen Pelc wrote:
> > From: "brendanmurphy37" <brendan.murphy@...>
> > I fear I'm repeating myself: the problem isn't that in-line assembler
> > doesn't work, the problem is that it is completely non-standard and
> > non-portable.
>Especially in embedded work, device drivers aren't portable
>whatever they are written in.
Portability, is about items other than porting code. It's also about the
portability of knowledge and skill. It's about the portability of tools
(editors, analyzers, generators etc..). In this particular case it's also
about limiting the egregious growth of languages (from 2 [C, ASM] to 3 {C,
ASM and inline ASM]) :)
>When I look at where MPE (as opposed to its clients) uses in-
>line assembly, we find it in device-specific drivers, e.g. UART
>and Ethernet drivers, and in CPU specific sections, e.g.
>schedulers, where we are striving for performance. In our world,
>interrupt latency and task-switching speed really matter,
>regardless of CPU performance - the faster the CPU, the more we
>are asked to do with it.
Why not do them in assembly rather than inline? I don't expect either of
us to change the others mind but I am curious as to the reasoning.
Robert
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-11 by Robert Adsett
At 01:35 AM 4/10/2006 +0000, jayasooriah wrote:
>--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
> > I do see uses for assembler, I am just of the opinion, informed
> > by my experiences, that inline assembler causes more problems
> > than it fixes.
>
>My experience tells me otherwise. Inline assembler has its place just
>like any other feature *provided* one understands how to use it before
>one does.
Apparently we have experienced different projects and tools.
I have never used a compiler seriously and not had it break at some point
on me. The only exception so far is GCC. The most common point of
failure, by far, are the architecture specific extensions. Interrupt
keywords, inline assembly, memory placement modifiers etc... Curiously,
the second most common failure point seems to be switch statements.
>If you can give us some examples of where it has caused more problems
>than it fixed, I might be able to explain what I think went wrong.
Problem 1: Nearly all implementations suffer from a lack of
documentation. One case in particular I remember the documentation boiling
down to more or less "the inline asm syntax is asm assembly
instruction;" Needless to say, I didn't even attempt that one.
Problem 2: Incompatible C syntax The form above is obviously not
compatible, so is the form
#asm
assembly instructions
#endasm
They both cause problems with tools and reuse. Tools are generally the
bigger issue.
Problem 3: optimization. If the assembly is just inserted in the middle of
the generated code before being passed to the backend it is sometimes
optimized away.
Problem 4: Register reappropriation. Not a good term but it will do. The
compiler documents the calling convention but when using inline even at the
beginning of the function the compiler appropriates the register for other
temporary uses first so you can never be sure that you will get what you
were expecting when you originally wrote it.
That being said I have run across compilers that only allowed inline (they
had no separate assembler) In both cases though the compilers resembled C
in much the same way Java does so the solution in both cases was really to
get a proper tool chain.
I have used multiple compilers on multiple architectures and experience has
taught me to approach architecture specific extensions with caution and if
their are clear simple alternatives as there are for interrupts and
assembler avoid them all together. I'd rather not spend my time
debugging the compiler if I can avoid it.
Robert
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-11 by Eric Engler
--- In lpc2000@yahoogroups.com, "Stephen Pelc" <stephen@...> wrote: > When I look at where MPE (as opposed to its clients) uses in- > line assembly, we find it in device-specific drivers, e.g. UART > and Ethernet drivers, and in CPU specific sections, e.g. > schedulers, where we are striving for performance. That's true with me, too. The few times I get involved with low-level issues not already handled by libraries I need to spend a lot of hours with irritating registers, processor modes and the like. Frankly, these types of things make me employable, so I shouldn't complain too much! But I have never used any inline assember except for the code recommended by compiler vendors (which used to happen more than it does now - libs weren't well developed back then). I always prefer to isolate my asm code in separate modules with well-defined API's, and then I link them to C programs. I also use asm for things that need to be kept secret, like licensing support code, and the like. It's much harder to disassemble hand-coded assembly routines than compiled C code, especially if the asm code was written with this in mind. Sometimes the art of deception even involves code for peripherals that aren't even being used for anything - it's the old magicians trick of attracting you to one hand while the other hand is doing something completely different. Assembler routines take about 10 - 20 times longer to write than C, and a much longer time to debug. Most companies simply can't afford this kind of development except for those cases where there is no alternative. And when this kind of need arises it often makes sense to use a consultant who specializes in this. Eric
2006-04-11 by brendanmurphy37
In looking at this again, it struck me that another reason not to use in-line assembler such as the example below (i.e. particularly where macros are involved) is to ask what happens when you want to re-compile the code using Thumb mode (as you might want to do to reduce code size)? My guess is that the macros will no longer work, so you'll be forced to do Thumb versions of the same. Then you have to figure out a way to use the correct macros at the correct places. This is a typical example of not considering portability issues at the start, and having them come back to haunt you at a later date. 1. Start off with some neat code that exploits some compiler feature, in this case by writing some clever macros that use in-line assembler. 2. There's no issue with Thumb mode, because all the code is compiled in ARM mode: where's the problem? 3. The macros are so good they get to be used all over the place. 4. Suddenly someone wants to use this software: the problem is they're insisting on using a part with a minimal amount of code space. 5. We know we can achieve this if we used the preferred ARM mechanism for reducing code space (Thumb mode), but we have all these ARM-code inline assembler macros scattered throughout the code. 6. What do we do? I'm not saying this scenario is the case here, but hopefully people can see what the big deal is with using non-standard, non-portable features: you can never tell how requirements will evolve over time. The alternative I approach I posted doesn't suffer from this problem. I'm not saying it's perfect, but I'd argue that at the very least it is easier to maintain and modify. I have seen many, many examples of the sequence of events listed above (details changed obviously), and each time there's been a lot of pain involved in solving the self-inflicted problems thrown up. Please note that none of this is a criticism of the actual code below: I'm simply using it to illustrate a point. Brendan. --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > This is an add-on to Danish Ali's contribution to AH's original question. [[items removed here]]
>
> > // ===========================================================
> > // 'irqMask'
> >
> > // mask either irq or fiq bit
> > inline int
> > irqMask(mask)
> > {
> > int mode;
> >
> > // set mask bit
> > asm volatile
> > (
> > "mrs\t%0, cpsr" "\n\t"
> > "orr\t%1, %1, %0" "\n\t"
> > "msr\tcpsr, %1"
> > : "=&r" (mode)
> > : "r" (mask)
> > );
> >
> > // previous mode
> > return (mode);
> >
> > } // irqMask()
> >
> > // End of 'irqMask'
> > // ===========================================================
> >2006-04-11 by Stephen Pelc
> From: Robert Adsett <subscriptions@...>
> Subject: Re: Re: Example of C and inline ASM in a file?
>
> At 02:43 PM 4/10/2006 +0100, Stephen Pelc wrote:
> >When I look at where MPE (as opposed to its clients) uses in-
> >line assembly, we find it in device-specific drivers, e.g. UART
> >and Ethernet drivers, and in CPU specific sections, e.g.
> >schedulers, where we are striving for performance. In our world,
> >interrupt latency and task-switching speed really matter,
> >regardless of CPU performance - the faster the CPU, the more we
> >are asked to do with it.
>
> Why not do them in assembly rather than inline? I don't expect either of
> us to change the others mind but I am curious as to the reasoning.
Here's my standard response to this question. Just to confuse
you, the example is not in C, and it's not for an ARM, but the
principles apply. The example is for a very simple UART driver
with interrupts enabled on receive.
: key0 \ -- char
\ *G Wait for character from USART0 and return it.
begin
di rx0-avail c@ 0=
while
[asm bis # _cpuoff _gie + sr asm] \ cpu to sleep, GIE set
repeat
rx0-char c@ 0 rx0-avail c!
ei
;
The compiler 'knows' about DI and EI to disable/enable
interrupts. The ways to the put an MSP430 to sleep are myriad.
The objective is to minimise the time for which interrupts are
disabled. Putting in a single assembler instruction achieves
that objective and documents everything the user needs to know.
Doing it this way gives faster code, better interrupt latency,
shorter source, and keeps everything together. Yes, I could have
tweaked the compiler to do this, but I prefer to do that only
when the required functionality is itself portable across CPUs.
Where I will code a complete routine is for something like the
TCP/IP checksum, where a hand-coded assembly routine will beat
the pants off the output of most compilers.
For an ARM7, each call/ret pair costs at least six cycles. For
matched entry/exit routines, that costs at least 12 additional
clocks. On the LPC2xxx there are four potential MAM stalls.
When you have an effectively 12MHz ARM (not an LPC2xxx),
thirteen tasks, and a bomb-disposal machine to control, you
learn to be paranoid!
Stephen
--
Stephen Pelc, stephen@...
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeforth.com - free VFX Forth downloads2006-04-11 by Paul Curtis
Hi Stephen,
> > Why not do them in assembly rather than inline? I don't
> expect either
> > of us to change the others mind but I am curious as to the
> reasoning.
>
> Here's my standard response to this question. Just to confuse
> you, the example is not in C, and it's not for an ARM, but
> the principles apply. The example is for a very simple UART
> driver with interrupts enabled on receive.
>
> : key0 \ -- char
> \ *G Wait for character from USART0 and return it.
> begin
> di rx0-avail c@ 0=
> while
> [asm bis # _cpuoff _gie + sr asm] \ cpu to sleep, GIE set
> repeat
> rx0-char c@ 0 rx0-avail c!
> ei
> ;
>
> The compiler 'knows' about DI and EI to disable/enable
> interrupts. The ways to the put an MSP430 to sleep are myriad.
> The objective is to minimise the time for which interrupts
> are disabled. Putting in a single assembler instruction
> achieves that objective and documents everything the user
> needs to know.
>
> Doing it this way gives faster code, better interrupt
> latency, shorter source, and keeps everything together. Yes,
> I could have tweaked the compiler to do this, but I prefer to
> do that only when the required functionality is itself
> portable across CPUs.
In C, if I remember Forth control words well enough:
#include <inmsp.h>
#include <msp430x14x.h>
unsigned char rx0_avail;
unsigned char rx0_char;
unsigned key0(void)
{
unsigned char ch;
for (;;)
{
__disable_interrupts();
if (rx0_avail)
{
ch = rx0_char;
rx0_avail = 0;
__enable_interrupts();
return ch;
}
__bis_SR_register(CPUOFF + GIE);
}
}
Generates:
__disable_interrupt();
1100 32c2 DINT
if (rx0_avail)
1102 c2930102 CMP.B #0, &_rx0_avail
1106 0624 JZ 0x1114
ch = rx0_char;
1108 5f420002 MOV.B &_rx0_char, R15
rx0_avail = 0;
110c c2430102 MOV.B #0, &_rx0_avail
__enable_interrupt();
1110 32d2 EINT
return ch;
1112 3041 RET
__bis_SR_register(CPUOFF + GIE);
1114 32d01800 BIS.W #0x18, SR
1118 f33f JMP 0x1100
I believe this is pretty good code from our CrossWorks MSP430 compiler.
:-) No assembly inserts in sight.
Ok, this is an MSP430 example, but for each architectural feature of the
MSP430 I believe I have provided an intrinsic which means that inline
assembly code is not required. It's done in such a way that it is also
compatible with the IAR MSP430 compiler, which means you can take code
written for ours and recompile on a competing compiler without resorting
the recoding any assembly language items. Of course, we find the tide
is in the opposite direction... ;-)
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors2006-04-11 by brendanmurphy37
--- In lpc2000@yahoogroups.com, "Stephen Pelc" <stephen@...> wrote: > The compiler 'knows' about DI and EI to disable/enable > interrupts. The ways to the put an MSP430 to sleep are myriad. > The objective is to minimise the time for which interrupts are > disabled. Putting in a single assembler instruction achieves > that objective and documents everything the user needs to know. > Good example of an appropriate use of in-line assembler. The side effects of issuing the "DI" and "EI" are pretty much non-existent in this case: there really is very little argument for taking another approach (though I would hide the implementation behind macros just in case). For an in-appropriate use, see the recent example of ARM macros to do a similar task. > Where I will code a complete routine is for something like the > TCP/IP checksum, where a hand-coded assembly routine will beat > the pants off the output of most compilers. I'd be careful about making this argument. We do a lot of DSP stuff on RISC processors (digital filters of various types). For the low- level stuff, our starting point is a 'C' implementation. On a couple of platforms we coded these up in assembler. However, we stopped doing this, as by measuring the performance of the optimised 'C' version we found there was little difference in performance: certainly not enough to justify the additional development and test time required. The greatest performance gains came from algorithm optimisation rather than coding in assembler. > > For an ARM7, each call/ret pair costs at least six cycles. For > matched entry/exit routines, that costs at least 12 additional > clocks. On the LPC2xxx there are four potential MAM stalls. > Someone presented this argument in relation to coding a context switching implementation. I'd argue that if you can't afford a few extra cycles in your context switches, you're doing too many of them. Try another approach. I've seen this argument so many times: a particular way of doing something saves a few cycles. In the vast majority of cases it makes absolutely no difference to a system's performance. If you really are that close to the edge, you're much better off at reconsidering the overall approach you're using. Unless something is inside a loop with many iterations, or part of a very high frequency event (e.g. a high frequency interrupt), it is pretty much guaranteed not to have any impact on system throughput. If it is in either of those situations, and performance was an issue (determined by quantitative analysis or empirically), I'd look at re- coding the entire offending section. If you really, really feel the need for in-line assembler, I'd isolate the relevant code into a separate source file. > When you have an effectively 12MHz ARM (not an LPC2xxx), > thirteen tasks, and a bomb-disposal machine to control, you > learn to be paranoid! I'd argue that this would lead one to maximise quality rather than speed of code. Simplicity, ease of maintenance, absence of side- effects, portability all tend to drive quality up. Squeezing the last drop of performance, using non-standard compiler extensions and the like all tend to drive it down. Please don't get upset anyone, the above is just an opinion! I'm happy to accept that the counter argument is perfectly valid: all I'm saying is that based on my own experience, using in-line assembler would be my last rather than first choice.
2006-04-11 by jayasooriah
Robert, Thanks for your detailed response. Here is an alternate view. --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > >My experience tells me otherwise. Inline assembler has its place just > >like any other feature *provided* one understands how to use it before > >one does. > > Apparently we have experienced different projects and tools. I have had considerable experience in training programmers from 18 to 50, in academia and in industry, using Borland, ByteCraft, Keil compiler variants besides K&R C, on 8-bit, 16-bit, 32-bit, CPUs and DSPs. I have written compilers, assemblers, linkers, operating systems, mostly all in C. I also have a good record in trouble shooting problems to their root causes when it is not clear if the compiler or the code being compiled is at fault. > Problem 1: Nearly all implementations suffer from a lack of > documentation. One case in particular I remember the documentation boiling > down to more or less "the inline asm syntax is asm assembly > instruction;" Needless to say, I didn't even attempt that one. I do not agree with your "nearly all" characterisation. Perhaps many. The ARM GCC Inline Assembler Cookbook is one that comes to mind. I have seen some others documented reasonably well too but I will admit, it is very hard to get programmers (whether 18 of 50) to reading the manual. > Problem 2: Incompatible C syntax The form above is obviously not > compatible, so is the form > #asm > assembly instructions > #endasm > They both cause problems with tools and reuse. Tools are generally the > bigger issue. I agree, *if* the compiler does not support inline assembly properly. Do you think GCC falls in this category? I am not sure about the rest, but in GCC, the ASM feature is a (clever) hook to the code generator internals. > Problem 3: optimization. If the assembly is just inserted in the middle of > the generated code before being passed to the backend it is sometimes > optimized away. I would classify this more a myth than fact. One has to understand the limitations of the feature before one uses it. More often I find that the programmer forgets to use the volatile qualifier. I am not saying optimisers do not screw up. But they are bugs just like other bugs. There are bugs in how compilers implement switch statements. That is not sufficient grounds IMO to advocate not using switch construct. > Problem 4: Register reappropriation. Not a good term but it will do. The > compiler documents the calling convention but when using inline even at the > beginning of the function the compiler appropriates the register for other > temporary uses first so you can never be sure that you will get what you > were expecting when you originally wrote it. I classify this the myth category. More often than not, one forgets and names a register and forgets to tell the compiler. I provided an example in GCC where you do not have to name a register -- get the compiler to allocate it. This way, the compiler always knows what is being used. I am happy to consider real examples, past or present, which I hope will make it easier to illustrate the points I have raised. Jaya
2006-04-11 by brendanmurphy37
--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > I am happy to consider real examples, past or present, which I hope > will make it easier to illustrate the points I have raised. > > Jaya > Maybe you could consider the issues I raised about your own example in: http://groups.yahoo.com/group/lpc2000/message/15225 I'm sure everyone would welcome your input. Brendan
2006-04-11 by George M. Gallant, Jr.
How to start a flame war by Brendan Murphy. I switch between C/Assembler because it fits my current needs. End of discussion!!! George On Tue, 2006-04-11 at 14:56 +0000, brendanmurphy37 wrote: > --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > > > I am happy to consider real examples, past or present, which I hope > > will make it easier to illustrate the points I have raised. > > > > Jaya > > > > Maybe you could consider the issues I raised about your own example > in: > > http://groups.yahoo.com/group/lpc2000/message/15225 > > I'm sure everyone would welcome your input. > > Brendan > > > > > > > > > > SPONSORED LINKS > > Microcontrollers > Microprocessor > Intel microprocessors > > > > ______________________________________________________________________ > YAHOO! GROUPS LINKS > > > 1. Visit your group "lpc2000" on the web. > > 2. To unsubscribe from this group, send an email to: > lpc2000-unsubscribe@yahoogroups.com > > 3. Your use of Yahoo! Groups is subject to the Yahoo! Terms of > Service. > > > > ______________________________________________________________________ > > [Non-text portions of this message have been removed]
2006-04-11 by Stephen Pelc
> unsigned key0(void)
> {
> unsigned char ch;
> for (;;)
> {
> __disable_interrupts();
> if (rx0_avail)
> {
> ch = rx0_char;
> rx0_avail = 0;
> __enable_interrupts();
> return ch;
> }
> __bis_SR_register(CPUOFF + GIE);
> }
> }
> I believe this is pretty good code from our CrossWorks MSP430 compiler.
> :-) No assembly inserts in sight.
I'm not complaining about your code generators, Paul. Remember
that you've written compilers for MPE!
I'll requote my post:
> Putting in a single assembler instruction
> achieves that objective and documents everything the user
> needs to know.
>
> I could have tweaked the compiler to do this, but I prefer to
> do that only when the required functionality is itself
> portable across CPUs.
[asm bis # _cpuoff _gie + sr asm]
versus
__bis_SR_register(CPUOFF + GIE);
Not much difference either in terms of readability or of
keystrokes. As I implied above, it's a qualitative/subjective
decision, and I personally don't find CPU-dependent pseudo-
portability attractive.
The advantage of your intrinsics is in the protection for the
user against resource usage by the compiler.
[AD] IAR vs Crossworks snipped!
Stephen
--
Stephen Pelc, stephen@...
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeforth.com - free VFX Forth downloads2006-04-11 by Stephen Pelc
> From: "brendanmurphy37" <brendan.murphy@...> > > Where I will code a complete routine is for something like the > > TCP/IP checksum, where a hand-coded assembly routine will beat > > the pants off the output of most compilers. > > I'd be careful about making this argument. We do a lot of DSP stuff > on RISC processors (digital filters of various types). For the low- > level stuff, our starting point is a 'C' implementation. On a couple > of platforms we coded these up in assembler. However, we stopped > doing this, as by measuring the performance of the optimised 'C' > version we found there was little difference in performance: > certainly not enough to justify the additional development and test > time required. In general, I agree, but the gains on an ARM were irresistible and we did the comparisons some years ago. > The greatest performance gains came from algorithm > optimisation rather than coding in assembler. No argument there - complete agreement. > > For an ARM7, each call/ret pair costs at least six cycles. For > > matched entry/exit routines, that costs at least 12 additional > > clocks. On the LPC2xxx there are four potential MAM stalls. > > Someone presented this argument in relation to coding a context > switching implementation. I'd argue that if you can't afford a few > extra cycles in your context switches, you're doing too many of them. > Try another approach. Remember that MPE sells Forth compilers with an RTOS and drivers. We have clients who (some years ago) thought that it was reasonable to run interrupts at 1Mhz on a 10Mhz CPU - we've just learned over the years that spending a couple of hours reducing interrupt latency during development can save days later. For most applications your arguments are valid, but 10% of clients cost 90% of tech support. > > When you have an effectively 12MHz ARM (not an LPC2xxx), > > thirteen tasks, and a bomb-disposal machine to control, you > > learn to be paranoid! > > I'd argue that this would lead one to maximise quality rather than > speed of code. Simplicity, ease of maintenance, absence of side- > effects, portability all tend to drive quality up. Squeezing the last > drop of performance, using non-standard compiler extensions and the > like all tend to drive it down. Define quality. The first requirement is to meet the spec! That job took 100 hour weeks and *all* code was documented. My example was from a low-level device driver, not from application code. Now have a go at Paul's non-standard intrinsics :-} Now let's agree just to disagree on some points. Stephen -- Stephen Pelc, stephen@... MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads
2006-04-12 by jayasooriah
George, I appreciate the sentiment you expressed. I frequently write illustrattive examples on-the-fly that encapsulate the concepts that want to explain. Such examples often look simple but non-trivial. My experience in training has been that is that those who understood from the example move on very quickly. The ideal is that these people are able to extend it to meet their particular requirements. However there are those who will keep going back to the same example over and over again well past its half-life. Although ducationists and psychologists have lots of theories about this kind of behaviour, I usually look at this simplistically as a problem with the level at which the example was pitched at. Solution? Break it down to smaller components and may be add a textual explanation rather than letting the code speak for itself. If there are enough people interested in textual commentary of my example, and perhaps on finer things that come out nicely in this example relating to how GCC optimises the inline assember code in the way we want it to, I am happy to oblige. Regards, Jaya --- In lpc2000@yahoogroups.com, "George M. Gallant, Jr." <ggallant571@...> wrote:
> > How to start a flame war by Brendan Murphy. > > I switch between C/Assembler because it fits my current needs. End of > discussion!!! > > George > > On Tue, 2006-04-11 at 14:56 +0000, brendanmurphy37 wrote: > > > --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote: > > > > > > I am happy to consider real examples, past or present, which I hope > > > will make it easier to illustrate the points I have raised. > > > > > > Jaya > > > > > > > Maybe you could consider the issues I raised about your own example > > in: > > > > http://groups.yahoo.com/group/lpc2000/message/15225 > > > > I'm sure everyone would welcome your input. > > > > Brendan
2006-04-12 by brendanmurphy37
Stephen, First off, thanks for engaging seriously with the points I raised, rather than simply disparaging or insulting those with a different view. Having said that, I think we probably agree far more than we disagree. See some detailed comments below. Regards Brendan --- In lpc2000@yahoogroups.com, "Stephen Pelc" <stephen@...> wrote: > In general, I agree, but the gains on an ARM were irresistible > and we did the comparisons some years ago. In that case, we agree 100%, if what you're saying is: "do the comparisons, then decide assembler or 'C'". We use the following strategy for time-critical systems: (1) find out where the system really spends its time (2) focus on the algorithms used in those sections and modify as appropriate (3) code in assembler (if necessary) and (4) most importantly: measure. The fact that we came up with a different result at stage (4) is kind of irrelevant: the point is that we both used comparative results to come to a reasoned conclusion. Note that you can stop at stage (2) if the system meets its spec at that stage, and save yourself a lot of development and support time and effort. A minor point is that in the example I used of the digital filter stuff, the low-level functions were deliberately written to give the compiler the easiest possible job of optimisation. Sure enough, it spat out the appropriate series of "mac" instructions, one after the other as planned. The algorithm optimisation (which involved a technique of loop unrolling) was done at a higher level to make this possible. > > > The greatest performance gains came from algorithm > > optimisation rather than coding in assembler. > > No argument there - complete agreement. > Nothing more to be said here. > Remember that MPE sells Forth compilers with an RTOS and > drivers. We have clients who (some years ago) thought that it > was reasonable to run interrupts at 1Mhz on a 10Mhz CPU - we've > just learned over the years that spending a couple of hours > reducing interrupt latency during development can save days > later. > I take your point. A related one I guess is that in your case you will be judged amongst other things on benchmark results. So for example a commercial RTOS might be judged on speed of context switch. Another case of where benchmarks are frequently misleading or irrelevant. > Define quality. The first requirement is to meet the spec! That > job took 100 hour weeks and *all* code was documented. > A useful definition of quality: "absence of defects". Meeting the spec is a given. After that anything that aids maintenance and ongoing support will tend to drive quality up. I'm talking generalities here: I'm sure your system was of the highest quality! > My example was from a low-level device driver, not from > application code. Now have a go at Paul's non-standard > intrinsics :-} > I'd rather see non-standard intrinsics than in-line assembler! > Now let's agree just to disagree on some points. > As I said, I suspect we agree far more than disagree. The only real difference is that in our respective toolchests, in-line assembler is likely to be found in a different place (somewhere near the bottom in mine). I wouldn't fall out with anyone because of that: the important thing is to be conscious of all the relevant factors involved in using a particular tool, and to learn from other's experience rather than simply blindly challange it. Brendan
2006-04-12 by brendanmurphy37
Jaya, I'm not sure what you're trying to achieve here. You present an example. I point out that it illustrates a point I'd been making (about how using in-line assembler can cause unintended problems as requirements change). You accuse me of not understanding the original example. If you're interested in a technical discussion, maybe you should read what I actually said, and respond accordingly? If all you're interested in is disparaging and insulting other contributors, can I ask you to please stop? I've had more than enough of it at this stage. Best wishes Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > George, > > I appreciate the sentiment you expressed. > > I frequently write illustrattive examples on-the-fly that encapsulate > the concepts that want to explain. Such examples often look simple > but non-trivial. > > My experience in training has been that is that those who understood > from the example move on very quickly. The ideal is that these people > are able to extend it to meet their particular requirements. > > However there are those who will keep going back to the same example > over and over again well past its half-life. > > Although ducationists and psychologists have lots of theories about > this kind of behaviour, I usually look at this simplistically as a > problem with the level at which the example was pitched at. > > Solution? Break it down to smaller components and may be add a > textual explanation rather than letting the code speak for itself. > > If there are enough people interested in textual commentary of my > example, and perhaps on finer things that come out nicely in this > example relating to how GCC optimises the inline assember code in the > way we want it to, I am happy to oblige. > > Regards, > > Jaya > > --- In lpc2000@yahoogroups.com, "George M. Gallant, Jr." > <ggallant571@> wrote: > > > > How to start a flame war by Brendan Murphy. > > > > I switch between C/Assembler because it fits my current needs. End of > > discussion!!! > > > > George > > > > On Tue, 2006-04-11 at 14:56 +0000, brendanmurphy37 wrote: > > > > > --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote: > > > > > > > > I am happy to consider real examples, past or present, which I hope > > > > will make it easier to illustrate the points I have raised. > > > > > > > > Jaya > > > > > > > > > > Maybe you could consider the issues I raised about your own example
> > > in: > > > > > > http://groups.yahoo.com/group/lpc2000/message/15225 > > > > > > I'm sure everyone would welcome your input. > > > > > > Brendan >
2006-04-12 by jayasooriah
Dear Brendan, Please onsider inline assembly issues as separate from interworking issues. Lumping them together results in the type of problems that you appear to find yourself in. Take a moment, and consider if you can appreciate the purpose of my on-the-fly example. The fact that it looks like operational code is incidental. It is *not* a on size fits all solution. You have peculiar requirements. Write your own if this one will not fit. Have a go. Avoid making ambit claims about what can and cannot be done with the example in a hope that I will respond by providing you the extension that will meet your peculiar requirements. My on-the-fly example serves to demonstrate that: b) the problem I originally extracted my requirements from (a code that I attributed to Rowley Associates) can be solved by identifing three primitives required; b) each of these can be coded as inline assembly or external module as one prefers, and I provided an inline assembly example, and using inline functions; and [Some here seem not to distinguish between the two different use of "inline" attributes.] c) using inline assembly, and letting the compiler know what you are doing in these three primitives, you can take advantage of the merging of the independent primitives, inline, efficiently as shown in the final outcome. I am not proposing that one should avoid procedure calls. The example I started with appears to suggest this is a requirement. I thought of a simpler way to achieve the same end result. So I put it up as my on-the-fly code. I am not interested in your whining every time I point a simpler, better, or for that matter, just another, way of doing things. Have a good day. Jaya --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...> wrote:
> Jaya, > > I'm not sure what you're trying to achieve here. > > You present an example. I point out that it illustrates a point I'd > been making (about how using in-line assembler can cause unintended > problems as requirements change). You accuse me of not understanding > the original example. > > If you're interested in a technical discussion, maybe you should > read what I actually said, and respond accordingly? > > If all you're interested in is disparaging and insulting other > contributors, can I ask you to please stop? I've had more than > enough of it at this stage. > > Best wishes > Brendan
2006-04-12 by Robert Adsett
At 02:32 PM 4/11/2006 +0000, jayasooriah wrote: > > Problem 1: Nearly all implementations suffer from a lack of > > documentation. One case in particular I remember the documentation >boiling > > down to more or less "the inline asm syntax is asm assembly > > instruction;" Needless to say, I didn't even attempt that one. > >I do not agree with your "nearly all" characterisation. Perhaps many. Fair enough, Many/nearly all could well be a sampling error or selective memory. >The ARM GCC Inline Assembler Cookbook is one that comes to mind. I >have seen some others documented reasonably well too but I will admit, >it is very hard to get programmers (whether 18 of 50) to reading the >manual. I would be an exception, annoys some people for some reason. Where would I find that BTW? The one gripe I have against GCC is that the documentation seems to be well hidden. > > Problem 2: Incompatible C syntax The form above is obviously not > > compatible, so is the form > > #asm > > assembly instructions > > #endasm > > They both cause problems with tools and reuse. Tools are generally the > > bigger issue. > >I agree, *if* the compiler does not support inline assembly properly. > Do you think GCC falls in this category? I am not sure about the >rest, but in GCC, the ASM feature is a (clever) hook to the code >generator internals. I've no reason to disparage GCC particularly. Indeed GCC seems to be the best thought out implementation I've seen (mostly from afar) but it as a result it also tends to be most of the way towards being a third language. I've just yet to see an advantage to inline over standard assembler and given the problems I've encountered the 0 benefits/x problem ratio tends to discourage :) Actually (as a side bar), the availability or lack thereof of GCC for an architecture is becoming a major consideration in choosing a microcontroller for me. I've become fed up with the copy protection schemes commercial compilers tend to foist upon me. > > Problem 3: optimization. If the assembly is just inserted in the >middle of > > the generated code before being passed to the backend it is sometimes > > optimized away. > >I would classify this more a myth than fact. One has to understand >the limitations of the feature before one uses it. More often I find >that the programmer forgets to use the volatile qualifier. Since at least one of the compilers that exhibited this had no concept of volatile (pre-ANSI) that would have been difficult. Surely volatile is not used universally to signal this? > > Problem 4: Register reappropriation. Not a good term but it will >do. The > > compiler documents the calling convention but when using inline even >at the > > beginning of the function the compiler appropriates the register for >other > > temporary uses first so you can never be sure that you will get what >you > > were expecting when you originally wrote it. > >I classify this the myth category. More often than not, one forgets >and names a register and forgets to tell the compiler. That presupposes that it is possible to tell the compiler what registers are being used. Both of the last two problems I have seen. It's been long enough I couldn't dredge up the details so it's certainly subject to fuzzy recall and you should feel free to take with as much salt as you like :) My experience has taught me (much as touching a hot stove does) to avoid compiler and architecture specific 'features'. There are times they cannot be avoided or the facilities they provide are very advantageous. Items like mapping into otherwise unaddressable memory spaces come to mind. However, for items like assembly and interrupt prologues and epilogues where there clear, simple well tested alternatives I won't subject myself to the risk any more. I don't expect we are likely to change each others minds, but knowing why we reach the decision we do is useful I think. Now if someone could come up with a credible way of measuring some of this we might be further along. On the other hand that might just destroy the fun of debate ;) Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-12 by jayasooriah
--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > >The ARM GCC Inline Assembler Cookbook is one that comes to mind > Where would I find that BTW? The one gripe I have against GCC is > that the documentation seems to be well hidden. I was referring to: http://www.ethernut.de/en/documents/arm-inline-asm.html I do not like GCC by and large for the same reasons. Having dwelled in it to the extent I have, I appreciate the its evolution to the extent I can sort of "guess" how something works in GCC long before I dive into the code to confirm. Open source has its disadvantages. There are so many variants, many of which are unfortunately just hacks for particular purposes. These tend to break the core philosophy and implementation in unexpected ways. Builds for the popular platforms tend to suffer from this problem more than core platforms. I run from one such popular platform and I always work with my own builds from FSF releases which is better controlled. > Surely volatile is not > used universally to signal this? The creators of C had a phobia about introducing new tokens. So they tended to overload the meaning of the same token in different contexts. The "static" qualifier is a good example. From memory, volatile applied to a variable tells the compiler not to assume that it is normal memory because it may not retain its value until over written, or that reading it repeatedly may not yield the same value. The same qualifier applied to ASM statement tells the compiler not to assume that optimisation techniques applied to memory will work in the context of this code sequence involved. > That presupposes that it is possible to tell the compiler what registers > are being used. Yes, GCC lets you do this. > I don't expect we are likely to change each others minds, but knowing why > we reach the decision we do is useful I think. Now if someone could come > up with a credible way of measuring some of this we might be further > along. On the other hand that might just destroy the fun of debate ;) The root cause of wars IMO is when one side tries to change the others mind! Okay, seriously, I think the truth is somewhere in between. I like knowing both so that I can interwork (to borrow the term) and take advantage of the side that best suits by needs.
2006-04-12 by Michael Rubitschka
Dear Jaya >My experience in training has been that is that those who understood >from the example move on very quickly. The ideal is that these people >are able to extend it to meet their particular requirements. I often noticed that the medicore programmers do the best job. They somehow follow the ASAP-ACAN principle. (As simple as possible, as complex as neccessary). Their code is highly readable and maintanance friedly. The work of gurus or experts is often much more complex as neccessary and one can prepare for a rewrite once that person leaves the company. my 2 cents Michael
2006-04-12 by brendanmurphy37
Jaya,
I take your point about your example being illustrative only, and not
intended as a workable solution to a particular problem.
I had hoped you would take my point of using your example as an
illustration of the problems that can arise with in-line assembler.
We're both doing exactly the same thing: using a particular example
to make a point. They just happen to be different points.
I don't have any particular requirements, nor am I faced with a
particular problem, and I'm certainly not looking for you to provide
any solutions (I'm baffled as to how you could draw this conclusion).
Maybe you should read what I said again, with this clarification in
mind?
Finally, I'd ask you once again to ease up on the disparaging and
insulting language ("peculiar requirements", "whining" etc.). It adds
nothing to your arguments, and simply turns people off.
Best wishes
Brendan
--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
>
> Dear Brendan,
>
> Please onsider inline assembly issues as separate from interworking
> issues. Lumping them together results in the type of problems that
> you appear to find yourself in.
>
> Take a moment, and consider if you can appreciate the purpose of my
> on-the-fly example. The fact that it looks like operational code is
> incidental. It is *not* a on size fits all solution.
>
> You have peculiar requirements. Write your own if this one will not
> fit. Have a go. Avoid making ambit claims about what can and
cannot
> be done with the example in a hope that I will respond by providing
> you the extension that will meet your peculiar requirements.
>
> My on-the-fly example serves to demonstrate that:
>
> b) the problem I originally extracted my requirements from (a code
> that I attributed to Rowley Associates) can be solved by identifing
> three primitives required;
>
> b) each of these can be coded as inline assembly or external module
as
> one prefers, and I provided an inline assembly example, and using
> inline functions; and
>
> [Some here seem not to distinguish between the two different use of
> "inline" attributes.]
>
> c) using inline assembly, and letting the compiler know what you are
> doing in these three primitives, you can take advantage of the
merging
> of the independent primitives, inline, efficiently as shown in the
> final outcome.
>
> I am not proposing that one should avoid procedure calls. The
example
> I started with appears to suggest this is a requirement. I thought
of
> a simpler way to achieve the same end result. So I put it up as my
> on-the-fly code.
>
> I am not interested in your whining every time I point a simpler,
> better, or for that matter, just another, way of doing things.
>
> Have a good day.
>
> Jaya
>
> --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@>
> wrote:
>
> > Jaya,
> >
> > I'm not sure what you're trying to achieve here.
> >
> > You present an example. I point out that it illustrates a point
I'd
> > been making (about how using in-line assembler can cause
unintended
> > problems as requirements change). You accuse me of not
understanding > > the original example. > > > > If you're interested in a technical discussion, maybe you should > > read what I actually said, and respond accordingly? > > > > If all you're interested in is disparaging and insulting other > > contributors, can I ask you to please stop? I've had more than > > enough of it at this stage. > > > > Best wishes > > Brendan >
2006-04-12 by brendanmurphy37
Micheal, If your definition of a "mediocre programmer" is one who strives for "highly readable and maintenance friendly code", I'd be proud to be considered as one! Brendan --- In lpc2000@yahoogroups.com, "Michael Rubitschka" <rubitschka@...> wrote: > > Dear Jaya > > >My experience in training has been that is that those who understood > >from the example move on very quickly. The ideal is that these people
> >are able to extend it to meet their particular requirements. > > I often noticed that the medicore programmers do the best job. > They somehow follow the ASAP-ACAN principle. > (As simple as possible, as complex as neccessary). > Their code is highly readable and maintanance friedly. > > The work of gurus or experts is often much more complex > as neccessary and one can prepare for a rewrite once that > person leaves the company. > > > my 2 cents > Michael >
2006-04-12 by jayasooriah
Hi Michael, you alluded me to a typo. --- In lpc2000@yahoogroups.com, "Michael Rubitschka" <rubitschka@...> wrote: > >My experience in training has been that is that those who understood > >from the example move on very quickly. The ideal is that these people > >are able to extend it to meet their particular requirements. I meant to say "idea" but typed "ideal" and that changed the meaning somewhat. I meant to say that most programmers cope with it well. > I often noticed that the medicore programmers do the best job. > They somehow follow the ASAP-ACAN principle. > (As simple as possible, as complex as neccessary). Cuts both ways. Mediocre programmers accept requirements more readily and are usually easier to manage. Expert programmers often dwell in changing the requirements to meet their notion of a good solution. Expert or mediocre, I like to think requirements come first followed by the KISS (keep it simple, xxx) rule. All else is optional. > The work of gurus or experts is often much more complex > as neccessary and one can prepare for a rewrite once that > person leaves the company. In case you are suggesting (I am not sure), my example is not a guru level solution by any means. I reckon the person who wrote the example I extracted requirements from went to great lengths in making sure that the procedure call to disable or enable interrupts is not taken unless necessary. In my rewrite the procedure call is a non-issue and thus I was able to do away with the conditionals making it simpler and deterministic. > Their code is highly readable and maintanance friedly. The whole idea behind using inline assembly rather than assembler modules for my example is to show that it is both more readable *and* easier to maintain. One could hide ASM details in a header and then you cannot tell the two implementations apart by looking at the code. A maintainer would prefer to maintain C and H files than S files, when the code is generic and common to the different architectures barring inline ASM escapes in conditional context. A client will not appreciate conditional code that handles just about every variant there is on the planet when only one of these is all the client is interested in. > my 2 cents > Michael
2006-04-12 by Michael Rubitschka
Hi Jaya >In case you are suggesting (I am not sure), my example is not a guru >level solution by any means. No I did not want to offend you or put in in the guro or medicore programmer drawer. >Cuts both ways. Mediocre programmers accept requirements more readily >and are usually easier to manage. Expert programmers often dwell in >changing the requirements to meet their notion of a good solution. Yes absolutly right, I see this every day. In the end all that counts is to get the requirements working as fast as possible and kepp them free of bugs. Cheers Michael
2006-04-12 by jayasooriah
--- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...> wrote: > Maybe you should read what I said again, with this clarification in > mind? I have. You include interworking requirements to the original problem from which I extracted the requirements. If you can rephrase your problem without interworking requirements, I am happy to respond. I do not wish to start a thread on interworking at this time because it is a different kettle of fish. (I do not know of any compiler that is capable of optimisating across interworking barrier.) Jaya
2006-04-12 by Michael Rubitschka
Hi Brendan >If your definition of a "mediocre programmer" is one who strives >for "highly readable and maintenance friendly code", I'd be proud to >be considered as one! I am also working hard to become one. :-) Cheers Michael
>From: "brendanmurphy37" <brendan.murphy@...> >Reply-To: lpc2000@yahoogroups.com >To: lpc2000@yahoogroups.com >Subject: [lpc2000] Re: Example of C and inline ASM in a file? >Date: Wed, 12 Apr 2006 09:40:29 -0000 > > >Micheal, > >If your definition of a "mediocre programmer" is one who strives >for "highly readable and maintenance friendly code", I'd be proud to >be considered as one! > >Brendan > >--- In lpc2000@yahoogroups.com, "Michael Rubitschka" <rubitschka@...> >wrote: > > > > Dear Jaya > > > > >My experience in training has been that is that those who >understood > > >from the example move on very quickly. The ideal is that these >people > > >are able to extend it to meet their particular requirements. > > > > I often noticed that the medicore programmers do the best job. > > They somehow follow the ASAP-ACAN principle. > > (As simple as possible, as complex as neccessary). > > Their code is highly readable and maintanance friedly. > > > > The work of gurus or experts is often much more complex > > as neccessary and one can prepare for a rewrite once that > > person leaves the company. > > > > > > my 2 cents > > Michael > > > > > > >
2006-04-12 by brendanmurphy37
Jaya, OK - I think we got off on the wrong track: I'll try and explain further. I was using your example - which is perfectly valid in itself - to illustrate a point. Consider the following sequence of events: 1. We need some mechanism to lock out interrupts, for reasons that should be clear enough to everyone. 2. We decide to implement this as in-line assembler, wrapped up in some nice macros. In fact, we implement exactly the same macros as you presented in your example. 3. We test these out, and they work well. Everyone is delighted with the results. Our macros are a great sucess, and everyone is happy. Everyone uses them, all over the place. 4. Then, as often happens, some new requirement comes along. Code space is now a real issue for everyone. No problem: our chosen architecture has just the solution: re-build all our software using Thumb mode. 5. We re-build our software and are faced with an immediate problem: our nice macros that are used everywhere no longer work, as they use ARM-mode specific instructions. How do we solve this problem? there are all sorts of ways it can be solved: I'm sure you and I could both come up with several without too much effort. The problem is that it will take effort, no matter how it's done. The point I'm making is that the more you use non-standard, compiler- specfic features such as in-line assembler, the more likely it is that changing requirements will cause problems. It's a general point: unfortunately as we all know we can never anticipate all possible requirement changes when we produce a solution to a set of requirements. However, by following some general rules, such as avoiding non-portable features where possible, we increase our chances of being able to modify our system with fewer rather than more changes as requirements change. I completely take your point that your example was for illustrative purposes only, and that you probably wouldn't implement these macros in a working system (possibly for the reasons I outline). However, I'm using also it to illustrate a point: a naïve programmer might very well use solutions such as those in the example, without being conscious of the need to consider portability issues. Best wishes Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@> > wrote: > > > Maybe you should read what I said again, with this clarification in > > mind? > > I have. You include interworking requirements to the original problem > from which I extracted the requirements. > > If you can rephrase your problem without interworking requirements, I > am happy to respond. > > I do not wish to start a thread on interworking at this time because > it is a different kettle of fish. (I do not know of any compiler that
> is capable of optimisating across interworking barrier.) > > Jaya >
2006-04-12 by rtstofer
--- In lpc2000@yahoogroups.com, "Michael Rubitschka" <rubitschka@...> wrote: > > Hi Brendan > > >If your definition of a "mediocre programmer" is one who strives > >for "highly readable and maintenance friendly code", I'd be proud to > >be considered as one! > I am also working hard to become one. :-) > > Cheers > Michael I'm 'mediocre' - even on a good day. But, I can live with it! Heck, I wrote a FORTRAN program a couple of weeks ago to do some curve fitting. It was nice to be home; visiting an old friend. I just can't take the C thing serious... A passing fad, no doubt! So, has anyone enabled FORTRAN for the GCC compiler and the ARM platform? Richard
2006-04-12 by jayasooriah
Dear Brendan, This dialog has gone long enough. I like to finish off by addressing your lingering doubts once more as best as one can, and move on. --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...> wrote: > Consider the following sequence of events: > > 1. We need some mechanism to lock out interrupts, for reasons that > should be clear enough to everyone. > > 2. We decide to implement this as in-line assembler, wrapped up in > some nice macros. In fact, we implement exactly the same macros as > you presented in your example. > > 3. We test these out, and they work well. Everyone is delighted with > the results. Our macros are a great sucess, and everyone is happy. > Everyone uses them, all over the place. Thus my on-the-fly example has served its purpose. > 4. Then, as often happens, some new requirement comes along. Code > space is now a real issue for everyone. No problem: our chosen > architecture has just the solution: re-build all our software using > Thumb mode. > > 5. We re-build our software and are faced with an immediate problem: > our nice macros that are used everywhere no longer work, as they use > ARM-mode specific instructions. > > How do we solve this problem? there are all sorts of ways it can be > solved: I'm sure you and I could both come up with several without > too much effort. The problem is that it will take effort, no matter > how it's done. You cannot turn off interrupts while in thumb mode if you do not interwork. > The point I'm making is that the more you use non-standard, compiler- > specfic features such as in-line assembler, the more likely it is > that changing requirements will cause problems. GCC supports interworking. It has compiler options to select the paradigm you want to adopt for interworking. If you do not want to use it because it is not supported in the same way on all compilers, that is up to you. I like to use the feature given I think GCC supports it well enough. > I completely take your point that your example was for illustrative > purposes only, and that you probably wouldn't implement these macros > in a working system (possibly for the reasons I outline). This is not what I said. I stand by what I said. Finally Brendan, my on-the-fly example having served its purpose, and the forum having moved on, it is about time you do the same. Jaya
2006-04-12 by jayasooriah
--- In lpc2000@yahoogroups.com, "rtstofer" <rstofer@...> wrote: > So, has anyone enabled FORTRAN for the GCC compiler and the ARM platform? I had to enable (build and validate) FORTRAN for GCC for i86 platform just last year. At first I protested vehemently but I changed my mind when I found compensation difficult to refuse :) Jaya
2006-04-12 by brendanmurphy37
Jaya, OK - I give up. I've clearly failed to explain to you the point I was trying to make (which has nothing to do with interworking or whether or not particular features are supported by GCC). Maybe someone else can try. Hopefully others will have understood what I've been trying to say, and it'll provide them some food for thought. Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > Dear Brendan, > > This dialog has gone long enough. I like to finish off by addressing > your lingering doubts once more as best as one can, and move on. > > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@> > wrote: > > > Consider the following sequence of events: > > > > 1. We need some mechanism to lock out interrupts, for reasons that > > should be clear enough to everyone. > > > > 2. We decide to implement this as in-line assembler, wrapped up in > > some nice macros. In fact, we implement exactly the same macros as > > you presented in your example. > > > > 3. We test these out, and they work well. Everyone is delighted with > > the results. Our macros are a great sucess, and everyone is happy. > > Everyone uses them, all over the place. > > Thus my on-the-fly example has served its purpose. > > > 4. Then, as often happens, some new requirement comes along. Code > > space is now a real issue for everyone. No problem: our chosen > > architecture has just the solution: re-build all our software using > > Thumb mode. > > > > 5. We re-build our software and are faced with an immediate problem: > > our nice macros that are used everywhere no longer work, as they use > > ARM-mode specific instructions. > > > > How do we solve this problem? there are all sorts of ways it can be > > solved: I'm sure you and I could both come up with several without > > too much effort. The problem is that it will take effort, no matter > > how it's done. > > You cannot turn off interrupts while in thumb mode if you do not > interwork. > > > The point I'm making is that the more you use non-standard, compiler- > > specfic features such as in-line assembler, the more likely it is > > that changing requirements will cause problems. > > GCC supports interworking. It has compiler options to select the > paradigm you want to adopt for interworking. If you do not want to > use it because it is not supported in the same way on all compilers, > that is up to you. > > I like to use the feature given I think GCC supports it well enough. > > > I completely take your point that your example was for illustrative > > purposes only, and that you probably wouldn't implement these macros > > in a working system (possibly for the reasons I outline). > > This is not what I said. I stand by what I said. > > Finally Brendan, my on-the-fly example having served its purpose, and
> the forum having moved on, it is about time you do the same. > > Jaya >
2006-04-14 by John Heenan
Despised by the 'beautiful people' but practical, macros make it is
easy to retarget ARM inline assembler to work with C code compiled as
Thumb assembler.
Following are expamples for interrupt disable/enable for GCC. The
intention is simply to force the macros through functions compiled as
ARM code so as the compiler will force correct usage of bx to switch
between ARM and Thumb modes, when compiling Thumb code. The beauty of
the macro system is that all ARM generated code can use pure inline
assembler through
#define INTDISABLE INTIF_DISABLE
#define INTENABLE INTIF_ENABLE
and all Thumb generated code can use function wrappers for the same
macro names through
#define INTDISABLE cpsr_if_disable()
#define INTENABLE cpsr_if_enable()
When it comes to portability, the interface definiton is crucial.
Macros make it dead easy to muck around with interface defintions. Of
course debugging through a macro maze is another story!
//part of HEADER FILE such as header.h
//MAKE SURE A DEFAULT ISR HANDLER IS ASSIGNED TO VICDefVectAddr
//THE DEFAULT ISR HANDLER CAN BE EMPTY BUT MUST BE PRESENT
#define INTDISABLE INTIF_DISABLE
//#define INTDISABLE cpsr_if_disable()
#define INTENABLE INTIF_ENABLE
//#define INTENABLE cpsr_if_enable()
#define SLOWINTDISABLE INTI_DISABLE
//#define SLOWINTDISABLE cpsr_i_disable()
#define SLOWINTENABLE INTI_ENABLE
//#define SLOWINTENABLE cpsr_i_enable()
//volatile definition forces stack storage and is not required
//as optimisation sees variable is used by a function and so keeps
//#define INTVAR volatile int cpsr_prior
#define INTVAR int cpsr_prior
#define INTGETDISABLE cpsr_prior=cpsr_ifget_disable()
#define INTRESTORE cpsr_c_restore(cpsr_prior)
void cpsr_if_disable(void); //works with thumb
void cpsr_if_enable(void); //works with thumb
void cpsr_i_disable(void); //works with thumb
void cpsr_i_enable(void); //works with thumb
int cpsr_ifget_disable(void);//works with thumb
void cpsr_c_restore(int cpsr_prior);//works with thumb
//not OK for thumb code
#define INTIF_ENABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"bic r3,r3,#0xC0 \n\t" \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTIF_DISABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"orr r3,r3,#0x80 \n\t" /* I bit. separate disablement: see user
manual */ \
"msr cpsr_c,r3 \n\t" \
"orr r3,r3,#0x40 \n\t" /* F bit */ \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTI_ENABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"bic r3,r3,#0x80 \n\t" \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTI_DISABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"orr r3,r3,#0x80 \n\t" \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
//MODULE FILE compiled as ARM assembler
#include "header.h"
void cpsr_if_disable(void)//works from thumb
{
INTIF_DISABLE;
}
void cpsr_if_enable(void)//works from thumb
{
INTIF_ENABLE;
}
void cpsr_i_disable(void)//works from thumb
{
INTI_DISABLE;
}
void cpsr_i_enable(void)//works from thumb
{
INTI_ENABLE;
}
int cpsr_ifget_disable(void)//works from thumb
{
unsigned int cpsr_prior;
asm volatile (
"mrs %0, cpsr \n\t"
"orr r3, %0, #0x80 \n\t" /* I bit. separate disablement: see
user manual */
"msr cpsr_c, r3 \n\t"
"orr r3, r3, #0x40 \n\t" /* F bit */
"msr cpsr_c, r3 \n\t"
: "=r"(cpsr_prior)
:
: "r3"
);
return cpsr_prior;
//assmembler generated
// mrs r0, cpsr
// orr r3, r0, #0x80
// msr cpsr_c, r3
// orr r3, r3, #0x40
// msr cpsr_c, r3
// bx lr
}
void cpsr_c_restore(int cpsr_prior)//works from thumb
{
asm volatile (
"msr cpsr_c, %0 \n\t"
:
: "r" (cpsr_prior)
);
//assembler generated
// msr cpsr_c, r0
// bx lr
}
John Heenan
--- In lpc2000@yahoogroups.com, "brendanmurphy37"
<brendan.murphy@...> wrote:
>
>
> Jaya,
>
> OK - I give up. I've clearly failed to explain to you the point I
was
> trying to make (which has nothing to do with interworking or
whether
> or not particular features are supported by GCC). Maybe someone
else
> can try.
>
> Hopefully others will have understood what I've been trying to say,
> and it'll provide them some food for thought.
>
> Brendan
>
> --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote:
> >
> > Dear Brendan,
> >
> > This dialog has gone long enough. I like to finish off by
> addressing
> > your lingering doubts once more as best as one can, and move on.
> >
> > --- In lpc2000@yahoogroups.com, "brendanmurphy37"
<brendan.murphy@>
> > wrote:
> >
> > > Consider the following sequence of events:
> > >
> > > 1. We need some mechanism to lock out interrupts, for reasons
> that
> > > should be clear enough to everyone.
> > >
> > > 2. We decide to implement this as in-line assembler, wrapped up
> in
> > > some nice macros. In fact, we implement exactly the same macros
> as
> > > you presented in your example.
> > >
> > > 3. We test these out, and they work well. Everyone is delighted
> with
> > > the results. Our macros are a great sucess, and everyone is
> happy.
> > > Everyone uses them, all over the place.
> >
> > Thus my on-the-fly example has served its purpose.
> >
> > > 4. Then, as often happens, some new requirement comes along.
Code
> > > space is now a real issue for everyone. No problem: our chosen
> > > architecture has just the solution: re-build all our software
> using
> > > Thumb mode.
> > >
> > > 5. We re-build our software and are faced with an immediate
> problem:
> > > our nice macros that are used everywhere no longer work, as
they
> use
> > > ARM-mode specific instructions.
> > >
> > > How do we solve this problem? there are all sorts of ways it
can
> be
> > > solved: I'm sure you and I could both come up with several
> without
> > > too much effort. The problem is that it will take effort, no
> matter
> > > how it's done.
> >
> > You cannot turn off interrupts while in thumb mode if you do not
> > interwork.
> >
> > > The point I'm making is that the more you use non-standard,
> compiler-
> > > specfic features such as in-line assembler, the more likely it
is
> > > that changing requirements will cause problems.
> >
> > GCC supports interworking. It has compiler options to select the
> > paradigm you want to adopt for interworking. If you do not want
to
> > use it because it is not supported in the same way on all
compilers,
> > that is up to you.
> >
> > I like to use the feature given I think GCC supports it well
enough.> > > > > I completely take your point that your example was for > illustrative > > > purposes only, and that you probably wouldn't implement these > macros > > > in a working system (possibly for the reasons I outline). > > > > This is not what I said. I stand by what I said. > > > > Finally Brendan, my on-the-fly example having served its purpose, > and > > the forum having moved on, it is about time you do the same. > > > > Jaya > > >
2006-04-14 by John Heenan
I have extended and tidied up the examples I have just posted to the
thread. I will probably post the code to the file section soon.
John Heenan
//header file interwork.h
#ifndef INTERWORK_H_
#define INTERWORK_H_
//MAKE SURE A DEFAULT ISR HANDLER IS ASSIGNED TO VICDefVectAddr
//THE DEFAULT ISR HANDLER CAN BE EMPTY BUT MUST BE PRESENT
#ifdef THUMB_INTERWORK
#define INTDISABLE cpsr_if_disable()
#define INTENABLE cpsr_if_enable()
#define SLOWINTDISABLE cpsr_i_disable()
#define SLOWINTENABLE cpsr_i_enable()
//volatile definition forces stack storage and is not required
//as optimisation sees variable is used by a function and so keeps
#define INTVAR int cpsr_prior
#define INTGETDISABLE cpsr_prior=cpsr_ifget_disable()
#define INTRESTORE cpsr_c_restore(cpsr_prior)
void cpsr_if_disable(void); //works with thumb
void cpsr_if_enable(void);
void cpsr_i_disable(void);
void cpsr_i_enable(void);
int cpsr_ifget_disable(void);
void cpsr_c_restore(int cpsr_prior);
#else
#define INTDISABLE INTIF_DISABLE
#define INTENABLE INTIF_ENABLE
#define SLOWINTDISABLE INTI_DISABLE
#define SLOWINTENABLE INTI_ENABLE
#define INTVAR volatile int cpsr_prior
#define INTGETDISABLE INTIFGET_DISABLE(cpsr_prior)
#define INTRESTORE INTIF_RESTORE(cpsr_prior)
#endif
/*
Usage example
INTDISABLE
INTENABLE
INTVAR;
INTGETDISABLE;
INTRESTORE;
INTGETDISABLE;
INTRESTORE;
*/
//not OK for thumb code
#define INTIF_ENABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"bic r3,r3,#0xC0 \n\t" \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTIF_DISABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"orr r3,r3,#0x80 \n\t" /* I bit. separate disablement: see user
manual */ \
"msr cpsr_c,r3 \n\t" \
"orr r3,r3,#0x40 \n\t" /* F bit */ \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTI_ENABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"bic r3,r3,#0x80 \n\t" \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTI_DISABLE asm volatile ( \
"mrs r3,cpsr \n\t" \
"orr r3,r3,#0x80 \n\t" \
"msr cpsr_c,r3 \n\t" \
: \
: \
: "r3" \
)
#define INTIFGET_DISABLE(A) asm volatile ( \
"mrs %0, cpsr \n\t" \
"orr r3, %0, #0x80 \n\t" /* I bit. separate disablement: see
user manual */ \
"msr cpsr_c, r3 \n\t" \
"orr r3, r3, #0x40 \n\t" /* F bit */ \
"msr cpsr_c, r3 \n\t" \
: "=r"(A) \
: \
: "r3" \
)
#define INTIF_RESTORE(A) asm volatile ( \
"msr cpsr_c, %0 \n\t" \
: \
: "r"(A) \
)
#endif // INTERWORK_H_
//##########################
//module file interwork.c compiled as ARM assembler
#include "interwork.h"
void cpsr_if_disable(void)
{
INTIF_DISABLE;
}
void cpsr_if_enable(void)
{
INTIF_ENABLE;
}
void cpsr_i_disable(void)
{
INTI_DISABLE;
}
void cpsr_i_enable(void)
{
INTI_ENABLE;
}
int cpsr_ifget_disable(void)
{
unsigned int cpsr_prior;
INTIFGET_DISABLE(cpsr_prior);
return cpsr_prior;
//assembler generated
// mrs r0, cpsr
// orr r3, r0, #0x80
// msr cpsr_c, r3
// orr r3, r3, #0x40
// msr cpsr_c, r3
// bx lr
}
void cpsr_c_restore(int cpsr_prior)
{
INTIF_RESTORE(cpsr_prior);
//assembler generated
// msr cpsr_c, r0
// bx lr
}
--- In lpc2000@yahoogroups.com, "John Heenan" <l10@...> wrote:
>
> Despised by the 'beautiful people' but practical, macros make it is
> easy to retarget ARM inline assembler to work with C code compiled
as
> Thumb assembler.
>
> Following are expamples for interrupt disable/enable for GCC. The
> intention is simply to force the macros through functions compiled
as
> ARM code so as the compiler will force correct usage of bx to
switch
> between ARM and Thumb modes, when compiling Thumb code. The beauty
of
> the macro system is that all ARM generated code can use pure inline
> assembler through2006-04-15 by jayasooriah
John,
Hope this spoilt child will not be grounded for critiquing on dad's
work :)
It certainly dismisses the myth that one can disable interrupts while
in 16-bit mode without interworking!
I hope you will not mind if I critique your design with the view of
improving it becomes a file. I do not wish to kill your efforts by
coming up with yet another interface design.
I do apologise before hand if in aiming to be complete I appear to be
nit picking. It is occupational hazard that I have learnt to live with :)
I feel your design can be made more compiler friendly in relation to
optimisation if you had used inline functions.
I trust my comments will be received in a constructive mode.
Regards,
Jaya
--- In lpc2000@yahoogroups.com, "John Heenan" <l10@...> wrote:
>
> I have extended and tidied up the examples I have just posted to the
> thread. I will probably post the code to the file section soon.
>
> John Heenan
>
> //header file interwork.h
> #ifndef INTERWORK_H_
> #define INTERWORK_H_
Probably your intention was to demonstrate interworking. When you
make it a file, perhaps you could reflect on the purpose of this
interface, which is not interworking.
> //MAKE SURE A DEFAULT ISR HANDLER IS ASSIGNED TO VICDefVectAddr
> //THE DEFAULT ISR HANDLER CAN BE EMPTY BUT MUST BE PRESENT
I do feel this comment is out of place. Certainly it applies to LPC
but is not something generic that I think warrants such a comment if
we look at the portability requirement some here appear preoccupied with.
>
> #ifdef THUMB_INTERWORK
Appears to violate a rule in my KISS book that says:
"Avoid defining a new conditional for one that exists."
Why not use the __thumb__ token that is already defined by GCC when
you invoke it with -mthumb option to produce 16-bit code?
> #define INTDISABLE cpsr_if_disable()
> #define INTENABLE cpsr_if_enable()
> #define SLOWINTDISABLE cpsr_i_disable()
> #define SLOWINTENABLE cpsr_i_enable()
> //volatile definition forces stack storage and is not required
> //as optimisation sees variable is used by a function and so keeps
I think the comment is not clear. I do not understand what you are
getting here. Perhaps you can rephrase it to make it clearer.
> #define INTVAR int cpsr_prior
Appears to violate two rules in my KISS book:
"Avoid defining a new interface for one that exists."
and
"Avoid using macros to alters syntax or semantics."
In relation to the latter rule I am assuming we are taking about a
fresh design, not retrofitting header to existing code.
> #define INTGETDISABLE cpsr_prior=cpsr_ifget_disable()
> #define INTRESTORE cpsr_c_restore(cpsr_prior)
>
> void cpsr_if_disable(void); //works with thumb
> void cpsr_if_enable(void);
> void cpsr_i_disable(void);
> void cpsr_i_enable(void);
> int cpsr_ifget_disable(void);
> void cpsr_c_restore(int cpsr_prior);
> #else
> #define INTDISABLE INTIF_DISABLE
> #define INTENABLE INTIF_ENABLE
> #define SLOWINTDISABLE INTI_DISABLE
> #define SLOWINTENABLE INTI_ENABLE
> #define INTVAR volatile int cpsr_prior
> #define INTGETDISABLE INTIFGET_DISABLE(cpsr_prior)
> #define INTRESTORE INTIF_RESTORE(cpsr_prior)
> #endif
>
> /*
> Usage example
> INTDISABLE
>
> INTENABLE
>
>
> INTVAR;
> INTGETDISABLE;
>
>
> INTRESTORE;
>
> INTGETDISABLE;
>
>
> INTRESTORE;
> */
>
> //not OK for thumb code
> #define INTIF_ENABLE asm volatile ( \
> "mrs r3,cpsr \n\t" \
> "bic r3,r3,#0xC0 \n\t" \
> "msr cpsr_c,r3 \n\t" \
> : \
> : \
> : "r3" \
> )
I prefer to avoid having to name registers explicitly so as not to
impose additional constraints on register optimisation.
Although not naming a register appears to adds one extra instruction
(which can be avoided if we were to design the interface differently),
it can save two move instructions where it is instantiated inline.
>
> #define INTIF_DISABLE asm volatile ( \
> "mrs r3,cpsr \n\t" \
> "orr r3,r3,#0x80 \n\t" /* I bit. separate disablement: see user
> manual */ \
> "msr cpsr_c,r3 \n\t" \
> "orr r3,r3,#0x40 \n\t" /* F bit */ \
> "msr cpsr_c,r3 \n\t" \
> : \
> : \
> : "r3" \
> )
Same issue here with naming register. More such examples below.
>
> #define INTI_ENABLE asm volatile ( \
> "mrs r3,cpsr \n\t" \
> "bic r3,r3,#0x80 \n\t" \
> "msr cpsr_c,r3 \n\t" \
> : \
> : \
> : "r3" \
> )
>
> #define INTI_DISABLE asm volatile ( \
> "mrs r3,cpsr \n\t" \
> "orr r3,r3,#0x80 \n\t" \
> "msr cpsr_c,r3 \n\t" \
> : \
> : \
> : "r3" \
> )
>
>
> #define INTIFGET_DISABLE(A) asm volatile ( \
> "mrs %0, cpsr \n\t" \
> "orr r3, %0, #0x80 \n\t" /* I bit. separate disablement: see
> user manual */ \
> "msr cpsr_c, r3 \n\t" \
> "orr r3, r3, #0x40 \n\t" /* F bit */ \
> "msr cpsr_c, r3 \n\t" \
> : "=r"(A) \
> : \
> : "r3" \
> )
>
> #define INTIF_RESTORE(A) asm volatile ( \
> "msr cpsr_c, %0 \n\t" \
> : \
> : "r"(A) \
> )
>
> #endif // INTERWORK_H_
>
> //##########################
>
> //module file interwork.c compiled as ARM assembler
I recommend naming the interworking options needed if compiled code is
to work when called from 16-bit mode -- caller or callee interworking?
> #include "interwork.h"
> void cpsr_if_disable(void)
> {
> INTIF_DISABLE;
> }
>
> void cpsr_if_enable(void)
> {
> INTIF_ENABLE;
> }
>
> void cpsr_i_disable(void)
> {
> INTI_DISABLE;
> }
>
> void cpsr_i_enable(void)
> {
> INTI_ENABLE;
> }
>
> int cpsr_ifget_disable(void)
> {
> unsigned int cpsr_prior;
> INTIFGET_DISABLE(cpsr_prior);
> return cpsr_prior;
> //assembler generated
> // mrs r0, cpsr
> // orr r3, r0, #0x80
> // msr cpsr_c, r3
> // orr r3, r3, #0x40
> // msr cpsr_c, r3
> // bx lr
> }
>
> void cpsr_c_restore(int cpsr_prior)
> {
> INTIF_RESTORE(cpsr_prior);
> //assembler generated
> // msr cpsr_c, r0
> // bx lr
> }
>
> --- In lpc2000@yahoogroups.com, "John Heenan" <l10@> wrote:
> >
> > Despised by the 'beautiful people' but practical, macros make it is
> > easy to retarget ARM inline assembler to work with C code compiled
> as
> > Thumb assembler.
The macro feature is powerful, so powerful that it can be used to
obfuscate code as much as to make it clearer.
Macros in themselves are not ugly, but it certainly can be used in
very ugly ways. Thus I do not despise the macro feature itself.
The most powerful use of macro is in retrofitting through making
minimal yet effective changes in the header.> > > > Following are expamples for interrupt disable/enable for GCC. The > > intention is simply to force the macros through functions compiled > as > > ARM code so as the compiler will force correct usage of bx to > switch > > between ARM and Thumb modes, when compiling Thumb code. The beauty > of > > the macro system is that all ARM generated code can use pure inline > > assembler through >
2006-04-15 by John Heenan
--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
>
> John,
>
> Hope this spoilt child will not be grounded for critiquing on dad's
> work :)
Don't want to understand.
> It certainly dismisses the myth that one can disable interrupts
while
> in 16-bit mode without interworking!
I was not aware of any such myths. I have simply submitted some
industry standard core code using techniques adapted from numerous
sources to fit a simple idea. I noted there is no MSR or MSR
instruction in Thumb and have not noted any code for the equivalent
in Thumb. The core of the code is firmly based on well documented
examples given by ARM and Philips.
Interrupts can be disabled without interworking on the LPC2xxx
through the VIC registers while in Thumb mode. I have brief notes in
preperation to be submitted as a file to the group.
>
> I hope you will not mind if I critique your design with the view of
> improving it becomes a file. I do not wish to kill your efforts by
> coming up with yet another interface design.
>
> I do apologise before hand if in aiming to be complete I appear to
be
> nit picking. It is occupational hazard that I have learnt to live
with :)
>
> I feel your design can be made more compiler friendly in relation to
> optimisation if you had used inline functions.
I agreed it would give more freedom to the compiler to do its thing.
I have made comments about inline code below.
> I trust my comments will be received in a constructive mode.
As I said it is just standard code adapted to fit a simple idea,
namely force industry standard ARM assembler code into a form
suitable for Thumb through functions compiled for interworking.
More comments below.
John Heenan
>
> Regards,
>
> Jaya
>
> --- In lpc2000@yahoogroups.com, "John Heenan" <l10@> wrote:
> >
> > I have extended and tidied up the examples I have just posted to
the
> > thread. I will probably post the code to the file section soon.
> >
> > John Heenan
> >
> > //header file interwork.h
> > #ifndef INTERWORK_H_
> > #define INTERWORK_H_
>
> Probably your intention was to demonstrate interworking. When you
> make it a file, perhaps you could reflect on the purpose of this
> interface, which is not interworking.
Yes.
>
> > //MAKE SURE A DEFAULT ISR HANDLER IS ASSIGNED TO VICDefVectAddr
> > //THE DEFAULT ISR HANDLER CAN BE EMPTY BUT MUST BE PRESENT
>
> I do feel this comment is out of place. Certainly it applies to LPC
> but is not something generic that I think warrants such a comment if
> we look at the portability requirement some here appear preoccupied
with.
I disagree. It is a practical issue. Both ARM and Philips state a
default handler must be assigned using the standard examples they
provide that has been incorparated into the code.
>
> >
> > #ifdef THUMB_INTERWORK
>
> Appears to violate a rule in my KISS book that says:
>
> "Avoid defining a new conditional for one that exists."
>
> Why not use the __thumb__ token that is already defined by GCC when
> you invoke it with -mthumb option to produce 16-bit code?
Point accepted. Saw THUMB_INTERWORK in another example and took a
punt it was standard. I was wrong.
>
> > #define INTDISABLE cpsr_if_disable()
> > #define INTENABLE cpsr_if_enable()
> > #define SLOWINTDISABLE cpsr_i_disable()
> > #define SLOWINTENABLE cpsr_i_enable()
> > //volatile definition forces stack storage and is not required
> > //as optimisation sees variable is used by a function and so
keeps
>
> I think the comment is not clear. I do not understand what you are
> getting here. Perhaps you can rephrase it to make it clearer.
>
> > #define INTVAR int cpsr_prior
>
> Appears to violate two rules in my KISS book:
>
> "Avoid defining a new interface for one that exists."
>
> and
>
> "Avoid using macros to alters syntax or semantics."
It reflects my attitudes to macros and functions. I tend to make
function names reflect what is really going on at the lower level and
make them lower case. I tend to make macros names closer to the real
intention of the macro is and in upper case. It is a practice that
serves me well personally. I get a marriage of intention (macro name)
with implementation (function name), all in a single line definition!
However it is a practice I can be divorced from if is the democratic
will!
>
> In relation to the latter rule I am assuming we are taking about a
> fresh design, not retrofitting header to existing code.
>
> > #define INTGETDISABLE cpsr_prior=cpsr_ifget_disable()
> > #define INTRESTORE cpsr_c_restore(cpsr_prior)
> >
> > void cpsr_if_disable(void); //works with thumb
> > void cpsr_if_enable(void);
> > void cpsr_i_disable(void);
> > void cpsr_i_enable(void);
> > int cpsr_ifget_disable(void);
> > void cpsr_c_restore(int cpsr_prior);
> > #else
> > #define INTDISABLE INTIF_DISABLE
> > #define INTENABLE INTIF_ENABLE
> > #define SLOWINTDISABLE INTI_DISABLE
> > #define SLOWINTENABLE INTI_ENABLE
> > #define INTVAR volatile int cpsr_prior
> > #define INTGETDISABLE INTIFGET_DISABLE(cpsr_prior)
> > #define INTRESTORE INTIF_RESTORE(cpsr_prior)
> > #endif
> >
> > /*
> > Usage example
> > INTDISABLE
> >
> > INTENABLE
> >
> >
> > INTVAR;
> > INTGETDISABLE;
> >
> >
> > INTRESTORE;
> >
> > INTGETDISABLE;
> >
> >
> > INTRESTORE;
> > */
> >
> > //not OK for thumb code
> > #define INTIF_ENABLE asm volatile ( \
> > "mrs r3,cpsr \n\t" \
> > "bic r3,r3,#0xC0 \n\t" \
> > "msr cpsr_c,r3 \n\t" \
> > : \
> > : \
> > : "r3" \
> > )
>
> I prefer to avoid having to name registers explicitly so as not to
> impose additional constraints on register optimisation.
I only named one register, r3, and specified it was clobbered. Since
the register cannot be attached to an input or output variable and
since I did not to troll through the horrific GAS assembler
documentation to see if there was a qualifier to specify working
registers r0-r3 or r12 only, I took the easy way out.
> Although not naming a register appears to adds one extra instruction
> (which can be avoided if we were to design the interface
differently),
> it can save two move instructions where it is instantiated inline.
Inline code CANNOT get rid of the call and return bx instructions
(bxl for Thumb also) as these instructions are the mode change
instructions. Inline code expands TOTAL code size but does have the
advantage of not refilling the fetch/decode/execute pipeline.
> >
> > #define INTIF_DISABLE asm volatile ( \
> > "mrs r3,cpsr \n\t" \
> > "orr r3,r3,#0x80 \n\t" /* I bit. separate disablement: see
user
> > manual */ \
> > "msr cpsr_c,r3 \n\t" \
> > "orr r3,r3,#0x40 \n\t" /* F bit */ \
> > "msr cpsr_c,r3 \n\t" \
> > : \
> > : \
> > : "r3" \
> > )
>
> Same issue here with naming register. More such examples below.
>
> >
> > #define INTI_ENABLE asm volatile ( \
> > "mrs r3,cpsr \n\t" \
> > "bic r3,r3,#0x80 \n\t" \
> > "msr cpsr_c,r3 \n\t" \
> > : \
> > : \
> > : "r3" \
> > )
> >
> > #define INTI_DISABLE asm volatile ( \
> > "mrs r3,cpsr \n\t" \
> > "orr r3,r3,#0x80 \n\t" \
> > "msr cpsr_c,r3 \n\t" \
> > : \
> > : \
> > : "r3" \
> > )
> >
> >
> > #define INTIFGET_DISABLE(A) asm volatile ( \
> > "mrs %0, cpsr \n\t" \
> > "orr r3, %0, #0x80 \n\t" /* I bit. separate disablement: see
> > user manual */ \
> > "msr cpsr_c, r3 \n\t" \
> > "orr r3, r3, #0x40 \n\t" /* F bit */ \
> > "msr cpsr_c, r3 \n\t" \
> > : "=r"(A) \
> > : \
> > : "r3" \
> > )
> >
> > #define INTIF_RESTORE(A) asm volatile ( \
> > "msr cpsr_c, %0 \n\t" \
> > : \
> > : "r"(A) \
> > )
> >
> > #endif // INTERWORK_H_
> >
> > //##########################
> >
> > //module file interwork.c compiled as ARM assembler
>
> I recommend naming the interworking options needed if compiled code
is
> to work when called from 16-bit mode -- caller or callee
interworking?
Agreed.
>
> > #include "interwork.h"
> > void cpsr_if_disable(void)
> > {
> > INTIF_DISABLE;
> > }
> >
> > void cpsr_if_enable(void)
> > {
> > INTIF_ENABLE;
> > }
> >
> > void cpsr_i_disable(void)
> > {
> > INTI_DISABLE;
> > }
> >
> > void cpsr_i_enable(void)
> > {
> > INTI_ENABLE;
> > }
> >
> > int cpsr_ifget_disable(void)
> > {
> > unsigned int cpsr_prior;
> > INTIFGET_DISABLE(cpsr_prior);
> > return cpsr_prior;
> > //assembler generated
> > // mrs r0, cpsr
> > // orr r3, r0, #0x80
> > // msr cpsr_c, r3
> > // orr r3, r3, #0x40
> > // msr cpsr_c, r3
> > // bx lr
> > }
> >
> > void cpsr_c_restore(int cpsr_prior)
> > {
> > INTIF_RESTORE(cpsr_prior);
> > //assembler generated
> > // msr cpsr_c, r0
> > // bx lr
> > }
> >
> > --- In lpc2000@yahoogroups.com, "John Heenan" <l10@> wrote:
> > >
> > > Despised by the 'beautiful people' but practical, macros make
it is
> > > easy to retarget ARM inline assembler to work with C code
compiled
> > as
> > > Thumb assembler.
>
> The macro feature is powerful, so powerful that it can be used to
> obfuscate code as much as to make it clearer.
>
> Macros in themselves are not ugly, but it certainly can be used in
> very ugly ways. Thus I do not despise the macro feature itself.
>
> The most powerful use of macro is in retrofitting through making
> minimal yet effective changes in the header.
>
> > >
> > > Following are expamples for interrupt disable/enable for GCC.
The
> > > intention is simply to force the macros through functions
compiled
> > as
> > > ARM code so as the compiler will force correct usage of bx to
> > switch
> > > between ARM and Thumb modes, when compiling Thumb code. The
beauty
> > of
> > > the macro system is that all ARM generated code can use pure
inline > > > assembler through > > >
2006-04-15 by jayasooriah
--- In lpc2000@yahoogroups.com, "John Heenan" <l10@...> wrote: > > It certainly dismisses the myth that one can disable interrupts > while > > in 16-bit mode without interworking! > > I was not aware of any such myths. I was referring to the persistent request (to which your first post was a response) that my interrupts example can be extended to 16-bit mode without interworking. > Interrupts can be disabled without interworking on the LPC2xxx > through the VIC registers while in Thumb mode. I have brief notes in > preperation to be submitted as a file to the group. Yes but there are costs. The first (and prohibitive as I have argued) is that the implementation of VIC on the LPC family (based on PL190 design) causes spurious interrupts to be generated when you do this. The second (probably more insidious) is that the distinction between of user and system modes appear to have been lost in the process. > As I said it is just standard code adapted to fit a simple idea, > namely force industry standard ARM assembler code into a form > suitable for Thumb through functions compiled for interworking. The term "industry standard" cuts both ways -- see comment below :) > Both ARM and Philips state a > default handler must be assigned using the standard examples they > provide that has been incorparated into the code. The "default" handler in VIC (PL190) is to handle interrupts that are not vectored. If all the interrupts are vectored, one does not need to dismiss interrupts through the default handler -- one can take a kernel panic when this happens as it indicates a system failure. Philips requirement is different -- it a default interrupt handler is required to dismiss spurious interrupts generated by LPC peripherals. > Point accepted. Saw THUMB_INTERWORK in another example and took a > punt it was standard. I was wrong. I like to make the distinction between "practice" and "standards". This is what I meant by "cuts both ways" earlier :) > It reflects my attitudes to macros and functions. I tend to make > function names reflect what is really going on at the lower level and > make them lower case. I tend to make macros names closer to the real > intention of the macro is and in upper case. It is a practice that > serves me well personally. I get a marriage of intention (macro name) > with implementation (function name), all in a single line definition! > > However it is a practice I can be divorced from if is the democratic > will! My experience from having to look at historical code base, is that this is one of the biggest impediments to code life. The next person has to not only understand and appreciate how the features of the language are used, but also understand new abstractions that sometimes obfuscate the original intent; For example: SAVE_INTERRUPT_STATE; and int mode; mode = getInterruptState() say quite different things. The latter can be understood by anyone with just the language semantics, but to understand the former, one has to include the mind set of the original programmer to discover how is the save achieved, where is it saved, and how does one restore the saved state, what happens when there are more than one saved state, etc. I advocate the philosophy that one uses as much of what is there rather than creating new abstractions, and that a strong case be made each time a new abstraction is contemplated. Programs express precisely what we cannot easily do as prose. Making program look like prose usually works against KISS rules. > > I prefer to avoid having to name registers explicitly so as not to > > impose additional constraints on register optimisation. > > I only named one register, r3, and specified it was clobbered. Since > the register cannot be attached to an input or output variable and > since I did not to troll through the horrific GAS assembler > documentation to see if there was a qualifier to specify working > registers r0-r3 or r12 only, I took the easy way out. You are right in that there is no way to allocate a register that is not attached. However I thought the method I originally proposed that does exactly the same overcomes this limitation. > Inline code CANNOT get rid of the call and return bx instructions > (bxl for Thumb also) as these instructions are the mode change > instructions. Inline code expands TOTAL code size but does have the > advantage of not refilling the fetch/decode/execute pipeline. Not true. The compiler is able to optimise prolog/epilog when it instantiates functions inline. Have look at my original example carefully. Regards, Jaya
2006-04-15 by Robert Adsett
At 04:38 AM 4/15/06 +0000, jayasooriah wrote: >--- In lpc2000@yahoogroups.com, "John Heenan" <l10@...> wrote: > > Interrupts can be disabled without interworking on the LPC2xxx > > through the VIC registers while in Thumb mode. I have brief notes in > > preperation to be submitted as a file to the group. > >Yes but there are costs. The first (and prohibitive as I have argued) >is that the implementation of VIC on the LPC family (based on PL190 >design) causes spurious interrupts to be generated when you do this. > >The second (probably more insidious) is that the distinction between >of user and system modes appear to have been lost in the process. Is this distinction actually useful? If user mode actually provided memory protection or I/O protection mechanisms I could see a use. As it is the only real use I see for the mode distinctions is the register saving/shadowing on interrupts. The inability to manipulate the interrupt flags appears to just be an annoyance/relic held over from ARM's larger general purpose computer roots. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-16 by John Heenan
--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > --- In lpc2000@yahoogroups.com, "John Heenan" <l10@> wrote: > > > > It certainly dismisses the myth that one can disable interrupts > > while > > > in 16-bit mode without interworking! > > > > I was not aware of any such myths. > > I was referring to the persistent request (to which your first post > was a response) that my interrupts example can be extended to 16-bit > mode without interworking. I have not seen your examples. Please provide a link or message number. My posting was simply to provide examples of how inline ARM assembler could be called from Thumb through a function wrapper. I get a daily digest of the list and may go for days without even opening it, let alone scanning it. When I do scan it I look for names that provide useful information. Top of my list is Philips_apps and Tom Walsh. I generally do not scan past even the first few words in a subject line. The only reason I posted to this thread was because I scanned with amusement the words 'I give up' by Brendan Murphy and because I hope I can pay back those who have given up their time freely with something useful myself. Like many I find vague and unsubstantiated accusatory information irritating, not because I find the people irritating but because I find having my time wasted by unnecessary drama irritating. > > > Interrupts can be disabled without interworking on the LPC2xxx > > through the VIC registers while in Thumb mode. I have brief notes in > > preperation to be submitted as a file to the group. > > Yes but there are costs. The first (and prohibitive as I have argued) > is that the implementation of VIC on the LPC family (based on PL190 > design) causes spurious interrupts to be generated when you do this. > > The second (probably more insidious) is that the distinction between > of user and system modes appear to have been lost in the process. > > > As I said it is just standard code adapted to fit a simple idea, > > namely force industry standard ARM assembler code into a form > > suitable for Thumb through functions compiled for interworking. > > The term "industry standard" cuts both ways -- see comment below :) > > > Both ARM and Philips state a > > default handler must be assigned using the standard examples they > > provide that has been incorparated into the code. > > The "default" handler in VIC (PL190) is to handle interrupts that are > not vectored. If all the interrupts are vectored, one does not need > to dismiss interrupts through the default handler -- one can take a > kernel panic when this happens as it indicates a system failure. > > Philips requirement is different -- it a default interrupt handler is > required to dismiss spurious interrupts generated by LPC peripherals. Why the drama over a peripheral that can sensibly clear its own interrupt source? I refused to buy into the 'interrupt debate' as I saw the debate as less illuminating and coherent than the information already available. An application note on spurious interrupts by Philips exapands on information provided by ARM and by Philips in all of their manuals. Leaving aside the issue of IRQ and FIQ disablement, which is well discussed in the manuals and does not require use of a default handler, Philips clearly points out a default handler is required when the VIC may change state in the pipeline between the core latching an interrupt and between when the ISR address is read from the VIC. The application note provides two examples of the VIC changing state as above: one when code changes the VIC state through assignment to VICIntEnClr to feed the watchdog and another when a peripheral changes the VIC state without user code through a UART FIFO clearing an interrupt source. Clearly another way to change the VIC state in a way that may require a default handler is to clear an interrupt source with user code outside an interrupt while interrupts are enabled. I don't feel there is a real problem. Setting up a default handler is trivial and good practice. It is not even necessary to update hardware priority logic through assignment to VicVectAddr if there are no real default interrupts to be handled. The handler can remain empty as the interrupt call will be reissued if the interrupt source is still present. > > Point accepted. Saw THUMB_INTERWORK in another example and took a > > punt it was standard. I was wrong. > > I like to make the distinction between "practice" and "standards". > This is what I meant by "cuts both ways" earlier :) > > > It reflects my attitudes to macros and functions. I tend to make > > function names reflect what is really going on at the lower level and > > make them lower case. I tend to make macros names closer to the real > > intention of the macro is and in upper case. It is a practice that > > serves me well personally. I get a marriage of intention (macro name) > > with implementation (function name), all in a single line definition! > > > > However it is a practice I can be divorced from if is the democratic > > will! > > My experience from having to look at historical code base, is that > this is one of the biggest impediments to code life. The next person > has to not only understand and appreciate how the features of the > language are used, but also understand new abstractions that sometimes > obfuscate the original intent; > > For example: > > SAVE_INTERRUPT_STATE; > > and > > int mode; > > mode = getInterruptState() > > say quite different things. The latter can be understood by anyone > with just the language semantics, but to understand the former, one > has to include the mind set of the original programmer to discover how > is the save achieved, where is it saved, and how does one restore the > saved state, what happens when there are more than one saved state, etc. > > I advocate the philosophy that one uses as much of what is there > rather than creating new abstractions, and that a strong case be made > each time a new abstraction is contemplated. > > Programs express precisely what we cannot easily do as prose. Making > program look like prose usually works against KISS rules. > It is not fair to apply good practice rules of database and business rules programming (such as forms and reports programming) to hardware and embedded programmers. Business rules programmers uses highly abstracted tools that hide the horribly complex APIs. At some point abstraction breaks down, it has to, the real world is not an abstract entity. In this case it helps to know what functions are performing direct hardware tasks as opposed to functions which are deliberately abstractive. For my own programming if a function performing hardware tasks need to be used by an abstract set of functions then I use a function pointer, as macros are unsitable at this level. Function pointers are not used by database and business rules programmers. I don't think it is worth making a fuss about, I will probably accede because I have better things to do than have questions raised by theorists over how functions are named and to provide ammunition for backroom gossip and amusement. There can't be much wrong in the IT world if abstract naming is a central preoccupation! > > > > I prefer to avoid having to name registers explicitly so as not to > > > impose additional constraints on register optimisation. > > > > I only named one register, r3, and specified it was clobbered. Since > > the register cannot be attached to an input or output variable and > > since I did not to troll through the horrific GAS assembler > > documentation to see if there was a qualifier to specify working > > registers r0-r3 or r12 only, I took the easy way out. > > You are right in that there is no way to allocate a register that is > not attached. However I thought the method I originally proposed that > does exactly the same overcomes this limitation. > > > Inline code CANNOT get rid of the call and return bx instructions > > (bxl for Thumb also) as these instructions are the mode change > > instructions. Inline code expands TOTAL code size but does have the > > advantage of not refilling the fetch/decode/execute pipeline. > > Not true. The compiler is able to optimise prolog/epilog when it > instantiates functions inline. Have look at my original example > carefully. Please provide a link or message number. You are not providing a complete picture. In my example the only epilogue was BX and there was no prologue. BX just does more than return, it also changes back to the Thumb state. While a large prologue and epilogue can be reduced (if not eliminated) and more optimisation can be performed if the code is inlined, if the same function is inlined many times then the overall code size is increased. People use Thumb to reduce code size. Even if ARM code was inlined between Thumb code, the BX instruction is required to enter ARM state. Since BX is a branch instruction it will probably automatically refill the fetch/decode/execute pipeline (can be tested by BX to inline ARM/ARM or Thumb/Thumb) and will need to discard the current pipeline anyway due to how the current pipeline has been interpreted and has the wrong size of information. I have reviewed the RealView assembler guide and discovered there are Thumb instructions for changing the interrupt state. They are CPSID and CPSIE. They cannot be used to change to ARM state inline and so avoid a branch penalty. However the instructions mean interrupts can be disabled and enabled without entering ARM state through interworking. However the principle of my example remains, which is how to allow inline ARM code to be used by Thumb code. The fact that the code was interrupt related code was irrelevant. it just happened to be 'on hand' and regrettably has drawn me into a debate I don't want to be a part of and started anoter debate I don't want to be a part of (abstract naming). I am grateful for useful information when it is provided and am keen to provide useful information in return. John Heenan
> > Regards, > > Jaya >
2006-04-16 by jayasooriah
Robert, given we are digressing, I hope you dont mind the my change of the thread title. --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > >The second (probably more insidious) is that the distinction between > >of user and system modes appear to have been lost in the process. > > Is this distinction actually useful? If user mode actually provided memory > protection or I/O protection mechanisms I could see a use. As it is the > only real use I see for the mode distinctions is the register > saving/shadowing on interrupts. The inability to manipulate the interrupt > flags appears to just be an annoyance/relic held over from ARM's larger > general purpose computer roots. One can ignore (and not enter) user mode to avoid the annoyance as you put it. If however one makes the distinction between user and kernel (or system) modes there are benefits. Off the top of my head: 1/ The designer is forced to make the distinction between infrastructure (kernel) from application specific (user) components. Infrastructure code is generic to multiple systems. Application code does the particular task the system is designed to do. 2/ Application code can be run at a lower privilege level so as to avoid having to resort to extreme debugging measures when there is interference. A new programmer joining the team does not need to start with expensive JTAG and/or other in-system emulation and debugging systems. [By expensive, I mean to not only (just) price, but also time and effort.] For example they could start developing an application on the target using techniques as simple as printf() equivalents. [Programmers who start with such methods exhibit more skills in probing a system at the right places using techniques that do not alter the system's operational behaviour.] 3/ The different privilege modes supports the decomposition of embedded systems into a set independent and cooperating concurrent tasks. This usually means there is a simple (almost always better) way to describe system in terms of its constituents and how these constituents interact. I accept (although I do not know of one) that the distinction between kernel and user mode may not be appropriate in every case. However, in removing this distinction in the LPC family just makes it less usable that it could otherwise be. Bear in mind implementors have the option of gating any operation with privilege mode bits available in the ARM core. Jaya
2006-04-16 by jayasooriah
--- In lpc2000@yahoogroups.com, "John Heenan" <l10@...> wrote: > Like many I find vague and unsubstantiated accusatory information > irritating, not because I find the people irritating but because I > find having my time wasted by unnecessary drama irritating. This is the clearest indication that my attempts to improve the solution you proposed in preference to putting up yet another solution is not working. I look forward to seeing your solution is all done and ready. If I feel I am able to extract your requirements, I will append to or provide an alternative replacement solution as appropriate. Jaya
2006-04-16 by Robert Adsett
At 03:29 AM 4/16/06 +0000, jayasooriah wrote: >Robert, given we are digressing, I hope you dont mind the my change of >the thread title. I should have thought of it myself. I'll trim it a little further :) >--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > > >The second (probably more insidious) is that the distinction between > > >of user and system modes appear to have been lost in the process. > > > > Is this distinction actually useful? If user mode actually provided >memory > > protection or I/O protection mechanisms I could see a use. As it is >the > > only real use I see for the mode distinctions is the register > > saving/shadowing on interrupts. The inability to manipulate the >interrupt > > flags appears to just be an annoyance/relic held over from ARM's larger > > general purpose computer roots. > >One can ignore (and not enter) user mode to avoid the annoyance as you >put it. I realize that. >If however one makes the distinction between user and kernel (or >system) modes there are benefits. Off the top of my head: > >1/ The designer is forced to make the distinction between >infrastructure (kernel) from application specific (user) components. > >Infrastructure code is generic to multiple systems. Application code >does the particular task the system is designed to do. Well, yes but that's independent of user/system mode. I can see system mode being useful in large systems especially when you are loading an application in RAM and using a flash image as the OS/kernel. SWI then acts as an indirect jump table to the underlying kernel functions. But with the small micros, especially those w/o an external bus, programs can as easily be built with a static link and avoid the extra overhead of the SWI. Both the simple timing overhead and the need to build a gateway library that provides the prototypes and parameter conversion from standard C type call to an SWI based call. >2/ Application code can be run at a lower privilege level so as to >avoid having to resort to extreme debugging measures when there is >interference. Well, yes but that was the real point of my question. Other than the ability to affect the interrupt state there doesn't appear to be a privilege level difference between system and user modes. >For example they could start developing an application on the target >using techniques as simple as printf() equivalents. You can do that anyway. You can do a lot of debugging with simple serial I/O and a few pins to toggle. Indeed there is a lot of useful , especially timing, information that is difficult or impossible to get other than through I/O pins and an oscilloscope and/or logic analyzer. There are other times when the only real recourse is multi-megabyte trace and good trigger and more than a little persistence. A problem I had on another processor with a commercial kernel comes to mind. >3/ The different privilege modes supports the decomposition of >embedded systems into a set independent and cooperating concurrent tasks. > >This usually means there is a simple (almost always better) way to >describe system in terms of its constituents and how these >constituents interact. > >I accept (although I do not know of one) that the distinction between >kernel and user mode may not be appropriate in every case. I suspect there is a legion of them. However let me give you a simple one. Linear actuator motor control. Two, possibly three inputs (forward, reverse and optionally a deadman) Outputs H bridge control of the motor and a brake release coil. Add in ramping, deceleration tracking overload protection etc. You can argue that an ARM is overkill and for the simplest variant of this it surely is, but with the price and them getting as low as they are it can make a lot of sense to use them in very similar applications in the same way it made sense to replace discrete logic with microcontrollers to begin with. >However, in removing this distinction in the LPC family just makes it >less usable that it could otherwise be. Bear in mind implementors >have the option of gating any operation with privilege mode bits >available in the ARM core. Well, if they had I could see an argument. I am not aware of any who do. Certainly the four I am most familiar with (Philips, ST, Atmel and Analog) do not. I've yet to use a micro that had that support. Again this was sort of the point of the question. Since that support is not there is there any real advantage to the use of user mode? If the micro provided I/O protection or memory protection I could see gating I/O operation to/from user mode to gain a little more protection from inadvertent manipulation of I/O. A lot of the time inadvertently flipping a bit at the wrong time is more dangerous than changing the interrupt state, it's also a lot easier to do. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-17 by jayasooriah
--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
> SWI then acts
> as an indirect jump table to the underlying kernel functions. But
with the
> small micros, especially those w/o an external bus, programs can as
easily
> be built with a static link and avoid the extra overhead of the SWI.
Both
> the simple timing overhead and the need to build a gateway library that
> provides the prototypes and parameter conversion from standard C
type call
> to an SWI based call.
I know of many who think along the lines you have expressed. They
associate "kernel" with what is found in general purpose operating
systems.
Allow me to challenge your perceptions relating to timing overheads
and gateway library requirements for SWI in embedded ARM context. I
will use the watchdog feed example that got me involved in the earlier
thread.
Here is the interface
> static inline void
> atomicFeed(volatile int *feed, int arg1, int arg2)
> {
> register volatile int *param1 asm ("r1") = feed;
> register int param2 asm ("r2") = arg1;
> register int param3 asm ("r3") = arg2;
> register int vector asm ("r0");
>
> asm volatile
> (
> "ldr\t%0, =atomicFeed" "\n\t"
> "swi\t0"
> : "=r" (vector)
> : "r" (param1), "r" (param2), "r" (param3)
> );
>
> } // atomicFeed()
and the implementation
> __attribute__((naked))
> void
> _atomicFeed(void)
> {
> asm volatile
> (
> PROLOG (atomicFeed)
> "msr\tcpsr_c, #0xd3" "\n\t"
> "str\tr2, [r1]" "\n\t"
> "str\tr3, [r1]" "\n\t"
> EPILOG ()
> );
>
> } // _atomicFeed()
The application includes the header file and invokes atomic feed:
> atomicFeed(&_WD.feed, 0xaa, 0x55);
The code generated for the application in 16-bit mode is:
> ldr r1, =[address]
> mov r2, #170
> mov r3, #85
> ldr r0, =atomicFeed
> swi 0
The SWI 'vector' at 0x00000008 is always coded as
> mov pc, r0
And generated code for the "kernel" handler in 16- and 32-bit modes
> .code 32
> .global atomicFeed
> atomicFeed:
> msr cpsr_c, #0xd3
> str r2, [r1]
> str r3, [r1]
> movs pc, lr
The beauty of this method is that it supports both 16- and 32-bit
compilation (with no conditionals I must add), and it works when
invoked from both user and kernel modes.
Have a go and see how much you can trim off this implementation in
terms of timing and gateway library interface overheads by using
procedure calls and consider what you would stand to lose.
Incidentally, the "vectored SWI" approach I use allows any team member
who are play with custom "system mode" kernel calls.
Jaya
PS: E&OE applies here too :) If you spot mistakes, please do not
hesitate to point it out.2006-04-18 by Robert Adsett
At 12:20 PM 4/17/2006 +0000, jayasooriah wrote:
>--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
> > SWI then acts
> > as an indirect jump table to the underlying kernel functions. But
>with the
> > small micros, especially those w/o an external bus, programs can as
>easily
> > be built with a static link and avoid the extra overhead of the SWI.
> Both
> > the simple timing overhead and the need to build a gateway library that
> > provides the prototypes and parameter conversion from standard C
>type call
> > to an SWI based call.
>
>I know of many who think along the lines you have expressed. They
>associate "kernel" with what is found in general purpose operating
>systems.
Actually I was thinking more along the lines of a real time
kernel, threads, semaphores etc.. I can see the term being extended a bit
beyond that but at the risk of its losing its meaning.
>Allow me to challenge your perceptions relating to timing overheads
>and gateway library requirements for SWI in embedded ARM context. I
>will use the watchdog feed example that got me involved in the earlier
>thread.
I was referring to more than just timing overhead, although that's in there
too.
>Here is the interface
<snip>
>and the implementation
<snip>
You appear to have left out the cracker function. Unless you are planning
a one function kernal?
>Have a go and see how much you can trim off this implementation in
>terms of timing and gateway library interface overheads by using
>procedure calls and consider what you would stand to lose.
In this case somewhere between 50 and 80% since all you are left with is
the implementation function. That's not really fair though I would expect
a real kernal to use somewhat heavier functions. I wouldn't pass the WD as
an address to the function like that, it just confuses the interface. Also
something I wouldn't do inline but we've been through that ;)
However the bigger issue hasn't been addressed which is the rest of the
overhead. The rather simple to maintain simple function interface has been
replaced by two functions separated by an interrupt. Across this interrupt
you have lost the type checking and other interface protection C normally
provides.
You also have not addressed the issue of what this approach actually
achieves. Since there appears to be no extra protection added by being in
user mode all that appears to have happened is that you've replaced one
function call with two calls plus an interrupt (one call to setup the
registers for the interrupt, one call from the interrupt cracker to the
actual function). The calls maybe inlineable but conceptually they are
still there and what they do still needs to be done. In return for this
the net gain is the user mode app can't manipulate the interrupt bits. I
don't see the point.
I also don't see anything being lost by using a library that links directly
rather than through a SWI. Quite the reverse actually.
I can see three cases where this approach could be useful
1- A large system where the kernal is loaded separately from the
application. Possibly with the application in RAM
2- A multi-language app with the kernal and application having
incompatible calling conventions.
3- An appliance application where the kernal and chip are shipped
as a unit.
Only for the external bus versions does 1 make much sense. The memory
available on the 2100's. and non external bus micros from Atmel, AD and ST
just isn't that large.
In case two, well that's what assembly language is for :). Or just a
better tool set.
Case 3, well that's rather specialized. Personally I have no desired to
handcuff my chip source to my kernal supplier.
>Incidentally, the "vectored SWI" approach I use allows any team member
>who are play with custom "system mode" kernel calls.
"to play with" maybe?
Which is different from a linked library in what fashion?
>PS: E&OE applies here too :) If you spot mistakes, please do not
>hesitate to point it out.
E&OE?
Robert
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-18 by jayasooriah
--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > Actually I was thinking more along the lines of a real time > kernel, threads, semaphores etc.. I can see the term being extended a bit > beyond that but at the risk of its losing its meaning. My aim was to challenge that assumption that kernel must be large, general purpose, and is only worth if there are many primitives. The atomicFeed() example shows the benefits of making even just a single procedure call a kernel primitive. I have boot loaders that run with as little as three of four kernel primitives. > In this case somewhere between 50 and 80% since all you are left with is > the implementation function. I dont understand what you mean. Are you suggesting changing the kernel call to procedure call will be smaller -- 50 to 80%. I like to see how. You have to try it to discover the tradeoffs. > That's not really fair though I would expect > a real kernal to use somewhat heavier functions. This is contrary to the KISS rule -- the simpler the functions are, the less likely they will fail, the easier they are to manage, and the more useful they would tend to be. There are OSes (as different from kernel feature) that seek to accommodate a variety of paradigms. They are big for this reason. > I wouldn't pass the WD as > an address to the function like that, it just confuses the interface. Also > something I wouldn't do inline but we've been through that ;) This is more a "style" or "preference" issue than programming paradigm. Maing it a parameter avoids having to provide separate primitives for WD, PLL, and so on. > However the bigger issue hasn't been addressed which is the rest of the > overhead. The rather simple to maintain simple function interface has been > replaced by two functions separated by an interrupt. Across this interrupt > you have lost the type checking and other interface protection C normally > provides. If you do not use kernel calls then you cannot reap the benefits. I went through at great lengths to preserve type checking. Hennce the use of inline functions rather than macros. Why do you say type checking is lost? > You also have not addressed the issue of what this approach actually > achieves. Since there appears to be no extra protection added by being in > user mode all that appears to have happened is that you've replaced one > function call with two calls plus an interrupt (one call to setup the > registers for the interrupt, one call from the interrupt cracker to the > actual function). Two that I like to point out most: 1) implementation does not know (and does not rely on knowing) if the caller is in 16- or 32-bit mode; and 2) implementation does not know (and does not rely on knowing) if the caller is in user or system mode; This means that there is no need to maintain multiple version libraries for the four permutations of the two modes. > I also don't see anything being lost by using a library that links directly > rather than through a SWI. Quite the reverse actually. Library linked code is strewn all over the code space. Kernel method allows it to be managed much more efficiently. Supppose a system locked up because interrupts ended up turned off. It would be trivial (or near trivial) to identify the culprit with the kernel approach without having to even rebuild a single application code. I cannot think of any other method that is as simple and efficient. > I can see three cases where this approach could be useful > 1- A large system where the kernal is loaded separately from the > application. Possibly with the application in RAM I would advocate against this. > 2- A multi-language app with the kernal and application having > incompatible calling conventions. This is not my intention here. > 3- An appliance application where the kernal and chip are shipped > as a unit. Yes, it would have been much more efficient to provide primitives in this manner that avoids the programmer having to discover one limitation after another the painful way because the interface is a procedure call but with the complex implementation idiosyncrasies hidden from the user's view. > >Incidentally, the "vectored SWI" approach I use allows any team member > >who are play with custom "system mode" kernel calls. > > "to play with" maybe? > > Which is different from a linked library in what fashion? Actually this "play with" comment comes from my training background. I like the programmers to get experience in working across interfaces by working on both sides and this method allows them to. Where the abstraction is useful to many programmers, it makes its way into the common pool of kernel functions, and becomes part of the tool set that new programmers can assume already exists and not re-invent the wheel. > >PS: E&OE applies here too :) If you spot mistakes, please do not > >hesitate to point it out. > > E&OE? Errors and Omissions Excepted (or something like it). It is meant to say that I have not put through the code through compile or debugger. My justification is simply that if I put the fully operational code, there are things in there that will distract one form the purpose of the example. However it takes time for me to make the changes, then compile to make sure there are no typo or silly errors. So I get lazy and just add E&OE! It just helps me provide examples more liberally than I can otherwise do. Jaya
2006-04-18 by Robert Adsett
At 04:20 AM 4/18/2006 +0000, jayasooriah wrote:
>--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
> > Actually I was thinking more along the lines of a real time
> > kernel, threads, semaphores etc.. I can see the term being
>extended a bit
> > beyond that but at the risk of its losing its meaning.
>
>My aim was to challenge that assumption that kernel must be large,
>general purpose, and is only worth if there are many primitives.
>
>The atomicFeed() example shows the benefits of making even just a
>single procedure call a kernel primitive. I have boot loaders that
>run with as little as three of four kernel primitives.
I don't yet see a benefit in using SWI over a function call. Only
disadvantages. That is the question here; not the size of whatever we
refer to as the kernal, since presumably that's why we are using user mode
rather than system mode.
> > In this case somewhere between 50 and 80% since all you are left
>with is
> > the implementation function.
>
>I dont understand what you mean. Are you suggesting changing the
>kernel call to procedure call will be smaller -- 50 to 80%. I like to
>see how. You have to try it to discover the tradeoffs.
Let's see
function call -> SWI -> Irq cracker -> function call
vs
function call
As I said earlier I don't consider this an important point. Remember I'm
one of those who think inline code is a bad idea, I'm not going to quibble
about the extra execution time of a SWI unless maybe you are calling it in
a small time critical loop. "Premature optimization is the root of all
evil" Knuth (I think)
> > That's not really fair though I would expect
> > a real kernal to use somewhat heavier functions.
>
>This is contrary to the KISS rule -- the simpler the functions are,
>the less likely they will fail, the easier they are to manage, and the
>more useful they would tend to be.
> > I wouldn't pass the WD as
> > an address to the function like that, it just confuses the
>interface. Also
> > something I wouldn't do inline but we've been through that ;)
>
>This is more a "style" or "preference" issue than programming
>paradigm. Maing it a parameter avoids having to provide separate
>primitives for WD, PLL, and so on.
One line functions tend to lead to a proliferation of functions. Also
violating the KISS principle. There is a golden mean somewhere. This
particular case I would have gone the other way and provided two functions
one for the watchdog and one for the PLL since they are the only items that
make use of that particular mechanism. The functions would also provide
some additional functionality. Each function providing a complete
functional unit in keeping with the KISS principle.
> > However the bigger issue hasn't been addressed which is the rest of the
> > overhead. The rather simple to maintain simple function interface
>has been
> > replaced by two functions separated by an interrupt. Across this
>interrupt
> > you have lost the type checking and other interface protection C
>normally
> > provides.
>
>If you do not use kernel calls then you cannot reap the benefits.
True, but the question of whether to use a kernal or other set of support
functions is separate from what benefit user mode may have. I ask again
what benefits does user mode have?
>I went through at great lengths to preserve type checking. Hennce the
>use of inline functions rather than macros. Why do you say type
>checking is lost?
If your compiler can type check a SWI it's a sight better than any I've
ever seen.
> > You also have not addressed the issue of what this approach actually
> > achieves. Since there appears to be no extra protection added by
>being in
> > user mode all that appears to have happened is that you've replaced one
> > function call with two calls plus an interrupt (one call to setup the
> > registers for the interrupt, one call from the interrupt cracker to the
> > actual function).
>
>Two that I like to point out most:
>
>1) implementation does not know (and does not rely on knowing) if the
>caller is in 16- or 32-bit mode; and
?? How is that an issue? We've been talking about user/system
mode. Compiling libraries for ARM/Thumb is a simple exercise. Trivial if
your 2 or 3 assembly routines are written to accommodate both.
>2) implementation does not know (and does not rely on knowing) if the
>caller is in user or system mode;
This gets us back to the question I've been asking from the
beginning. What is the benefit of running in user mode?
If SWI is available in both that eliminates it as an a benefit of user mode
even if there is an advantage to SWI.
>This means that there is no need to maintain multiple version
>libraries for the four permutations of the two modes.
I can see maintaining ARM/Thumb but why maintain system and user versions?
Your solution also needs to maintain both. You still need a library
> > I also don't see anything being lost by using a library that links
>directly
> > rather than through a SWI. Quite the reverse actually.
>
>Library linked code is strewn all over the code space. Kernel method
>allows it to be managed much more efficiently.
Good Lord, you have got to be kidding.
>Supppose a system locked up because interrupts ended up turned off.
>It would be trivial (or near trivial) to identify the culprit with the
>kernel approach without having to even rebuild a single application
>code. I cannot think of any other method that is as simple and efficient.
Two points.
- What do either of these have to do with user/system modes?
- How does implementing a kernal help you narrow that region
down? The only way I can see it is you restrict interrupt setting to the
kernal but even that only narrows it down if you insist that interrupts
always be on when exiting the kernal. That's not unreasonable in my
opinion but it's got nothing to do with user/system modes. It also does
absolutely nothing to protect against the far bigger dangers of memory
access outside of the bounds.
> > I can see three cases where this approach could be useful
> > 1- A large system where the kernal is loaded separately
>from the
> > application. Possibly with the application in RAM
>
>I would advocate against this.
I wouldn't use it either but then I don't build embedded systems that
large. AFAIK nearly all large embedded systems use this technique. For
that matter a fair number of them use hard disks.
> > 3- An appliance application where the kernal and chip are
>shipped
> > as a unit.
>
>Yes, it would have been much more efficient to provide primitives in
>this manner that avoids the programmer having to discover one
>limitation after another the painful way because the interface is a
>procedure call but with the complex implementation idiosyncrasies
>hidden from the user's view.
huh?
Idiosyncratic is idiosyncratic whether in a SWI or a function
call. Whether in user mode or system mode.
> > >Incidentally, the "vectored SWI" approach I use allows any team member
> > >who are play with custom "system mode" kernel calls.
> >
> > "to play with" maybe?
> >
> > Which is different from a linked library in what fashion?
>
>Actually this "play with" comment comes from my training background.
>I like the programmers to get experience in working across interfaces
>by working on both sides and this method allows them to.
I was verifying that I understood your grammar here. I wasn't clear that I
understood it. It appears I did. And again how is this different from a
linked library?
>Where the abstraction is useful to many programmers, it makes its way
>into the common pool of kernel functions, and becomes part of the tool
>set that new programmers can assume already exists and not re-invent
>the wheel.
Indeed, but this is a separate question from system versus user mode
benefits.
I do use kernals of support, after all why keep rewriting the same thing
over and over, but so far I see no benefit to using user mode. I was
hoping you would provide one but we seem to have veered off into a
discussion of SWI, which is somewhat related but doesn't provide an answer
unless there is a benefit to using a SWI over using a function call. And
for the size of system we appear to be talking about I fail to see any
benefit in a SWI.
> > >PS: E&OE applies here too :) If you spot mistakes, please do not
> > >hesitate to point it out.
> >
> > E&OE?
>
>Errors and Omissions Excepted (or something like it). It is meant to
>say that I have not put through the code through compile or debugger.
Ah, I've just not seen that used before.
Robert
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-19 by jayasooriah
Allow me to get back to the thread proper using top down. I will start with the list of advantages I have already pointed out as arising from making the distinction between user and system modes of operation as follows: 1/ allows codes of different maturity level (system vs user, operational vs experimental, infrastructure vs application) to coexist in the (embedded) system in a way that failure of (user) code does not result in failure of the entire system; 2/ provides isolation between caller and callee in providing the kernel primitives that will work under variety of conditions, including that not anticipated by the provider; and 3/ renders the resulting system friendly in relation to probing by hooking onto kernel primitives without the need to touch user code. [This helps track down problems of the type that go away when you add code to the application to watch what happens.] The tools I listed as useful in achieving the above goals, without making the system complicated, large or inefficient are: 1/ Inline functions: These behave exactly like a function that does not have this attribute (for type checking and so on), but at the same time makes the implementation visible to the compiler (and user). 2/ Inline assembler: This allows target code to generate the appropriate binary instance of the same source code depending on how it is compiled (16- or 32-bit mode, interworking paradigm, and so on) to accommodate style and preference requirements of the application programmer. In the context of this, I shall respond to your post by way of annotation. --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > >The atomicFeed() example shows the benefits of making even just a > >single procedure call a kernel primitive. I have boot loaders that > >run with as little as three of four kernel primitives. > > I don't yet see a benefit in using SWI over a function call. Only > disadvantages. That is the question here; not the size of whatever we > refer to as the kernal, since presumably that's why we are using user mode > rather than system mode. If the advantages I listed above does not apply to your scenario, then I can accept this statement. I cannot see why the do not though. > Let's see > > function call -> SWI -> Irq cracker -> function call > > vs > > function call > > As I said earlier I don't consider this an important point. Remember I'm > one of those who think inline code is a bad idea, I'm not going to quibble > about the extra execution time of a SWI unless maybe you are calling it in > a small time critical loop. "Premature optimization is the root of all > evil" Knuth (I think) Even taking into account the, I cannot see how to make it more efficient :) Probably because I do not like assembler too much! > One line functions tend to lead to a proliferation of functions. The fact that a feature or technique can also be misused is (to me) not sufficient justification to barr its use. > True, but the question of whether to use a kernal or other set of support > functions is separate from what benefit user mode may have. I ask again > what benefits does user mode have? See above. > >Two that I like to point out most: > > > >1) implementation does not know (and does not rely on knowing) if the > >caller is in 16- or 32-bit mode; and > > ?? How is that an issue? We've been talking about user/system > mode. Compiling libraries for ARM/Thumb is a simple exercise. Trivial if > your 2 or 3 assembly routines are written to accommodate both. I think you do not appreciate the fact that there is only one instance of the kernel binary, not multiple variants depending on what mode the application was compiled in. I use the ARM primitives designed just for this purpose. Doing it otherwise would be more expensive in terms of code and space. > >2) implementation does not know (and does not rely on knowing) if the > >caller is in user or system mode; > > This gets us back to the question I've been asking from the > beginning. What is the benefit of running in user mode? See above. > >This means that there is no need to maintain multiple version > >libraries for the four permutations of the two modes. > > I can see maintaining ARM/Thumb but why maintain system and user versions? If you use ARM/THUMB, you have to maintain two version. In my method, you do not need to. If you do not distinguish system vs user mode, then it does not apply. If you however chose to, then this comes at no cost in my approach. > Your solution also needs to maintain both. You still need a library This is where I think you have not understood the code snippet that I hoped will speak for itself. The kernel is compiled with the interface header and in 32-bit mode. There is only one instance of the kernel in memory. The user code is compiled in 16- or 32-bit mode, and only one version of its binary is in the system. You can have one application compiled in 16-bit mode, and another in 32-bit mode, coexist in the same system, and use the same calls, with only one copy of the binary of each of these applications. > Good Lord, you have got to be kidding. If I had a penny every time I heard that, I would be rich! :) > >Supppose a system locked up because interrupts ended up turned off. > >It would be trivial (or near trivial) to identify the culprit with the > >kernel approach without having to even rebuild a single application > >code. I cannot think of any other method that is as simple and efficient. > > Two points. > - What do either of these have to do with user/system modes? See benefits listed above. > - How does implementing a kernal help you narrow that region > down? Because the kernel handles all interrupt enable and disable operations, this is where one starts looking for problems relating interrupts disabled but not enabled thereafter. > The only way I can see it is you restrict interrupt setting to the > kernal but even that only narrows it down if you insist that interrupts > always be on when exiting the kernal. No. I provide the disableInt() and restoreInt() primitives to any function, whether or not it is running in user or system mode. There is no restriction that you leave the kernel mode with interrupt disabled. > That's not unreasonable in my > opinion but it's got nothing to do with user/system modes. It also does > absolutely nothing to protect against the far bigger dangers of memory > access outside of the bounds. This is where I ask people to include memory protection in their selection of targets for their application. [soap box] My biggest gripe with LPC family is not so much that it has no concept of memory protection, but its flash operations are not protected unlike any other system I have seen or have been told about. The absence of CDP gives rise to software causing the hardware to be unusable in the case of LPC. [end of soap box] Jaya
2006-04-19 by Robert Adsett
At 02:25 AM 4/19/2006 +0000, jayasooriah wrote: >I will start with the list of advantages I have already pointed out as >arising from making the distinction between user and system modes of >operation as follows: > >1/ allows codes of different maturity level (system vs user, >operational vs experimental, infrastructure vs application) to coexist >in the (embedded) system in a way that failure of (user) code does not >result in failure of the entire system; Nonsense. If the user application hangs up the fact that the user code is in user mode but the kernal in system mode won't make recovery easier or harder. If the user application sets the output to short a 200A hour battery through a FET capable of handling a 10A surge the placement of the kernal will affect things not one whit. There is zero extra protection available by placing the kernal in system mode and the application in user mode. >2/ provides isolation between caller and callee in providing the >kernel primitives that will work under variety of conditions, >including that not anticipated by the provider; and Like what? The closest example you have provided is ARM vs Thumb. I don't buy that as significant. If you cannot recompile your library you shouldn't be in this field. >3/ renders the resulting system friendly in relation to probing by >hooking onto kernel primitives without the need to touch user code. > >[This helps track down problems of the type that go away when you add >code to the application to watch what happens.] How is that different from a linked library similarly equipped and more to the point how does the user/system mode deal with it in a way that's different from not using user mode. >The tools I listed as useful in achieving the above goals, without >making the system complicated, large or inefficient are: > >1/ Inline functions: These behave exactly like a function that does >not have this attribute (for type checking and so on), but at the same >time makes the implementation visible to the compiler (and user). Have they become standard with C99? If so I'll probably consider them as a replacement for some macros when C99 support becomes more widespread. >2/ Inline assembler: This allows target code to generate the >appropriate binary instance of the same source code depending on how >it is compiled (16- or 32-bit mode, interworking paradigm, and so on) >to accommodate style and preference requirements of the application >programmer. We've already disagreed on this point, no point in going over it again. >--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > > >The atomicFeed() example shows the benefits of making even just a > > >single procedure call a kernel primitive. I have boot loaders that > > >run with as little as three of four kernel primitives. > > > > I don't yet see a benefit in using SWI over a function call. Only > > disadvantages. That is the question here; not the size of whatever we > > refer to as the kernal, since presumably that's why we are using >user mode > > rather than system mode. > >If the advantages I listed above does not apply to your scenario, then >I can accept this statement. I cannot see why the do not though. The advantages listed above seem to everything to do with using a standard kernal/support library and nothing to do with system/user mode. There is nothing I see there that has to do with CPU mode. > > Let's see > > > > function call -> SWI -> Irq cracker -> function call > > > > vs > > > > function call > > > > As I said earlier I don't consider this an important point. >Remember I'm > > one of those who think inline code is a bad idea, I'm not going to >quibble > > about the extra execution time of a SWI unless maybe you are calling >it in > > a small time critical loop. "Premature optimization is the root of all > > evil" Knuth (I think) > >Even taking into account the, I cannot see how to make it more >efficient :) Probably because I do not like assembler too much! Taking into account the what? And who said anything about assembler? > > One line functions tend to lead to a proliferation of functions. > >The fact that a feature or technique can also be misused is (to me) >not sufficient justification to barr its use. My point exactly. Just because you can turn something into a function doesn't mean you should, I've gone down the road you suggested with AtomicFeed and come to the conclusion it offered no useful increase in abstraction, it just obscured the intent of the code. You've obviously come to a different conclusion. > > >1) implementation does not know (and does not rely on knowing) if the > > >caller is in 16- or 32-bit mode; and > > > > ?? How is that an issue? We've been talking about user/system > > mode. Compiling libraries for ARM/Thumb is a simple exercise. >Trivial if > > your 2 or 3 assembly routines are written to accommodate both. > >I think you do not appreciate the fact that there is only one instance >of the kernel binary, not multiple variants depending on what mode the >application was compiled in. You're right I don't. I generally don't switch modes on a regular basis. On the LPC2000 family I don't see a reason to use thumb unless there is a space issue. I would be surprised to find projects that did switch application modes often enough for this to be an issue. I'd also be very worried about their quality. >I use the ARM primitives designed just for this purpose. Doing it >otherwise would be more expensive in terms of code and space. A compile switch is expensive? Dammed if I can see how a SWI take less space/time than a call. Or how switching modes reduces code space. > > >This means that there is no need to maintain multiple version > > >libraries for the four permutations of the two modes. > > > > I can see maintaining ARM/Thumb but why maintain system and user >versions? > >If you use ARM/THUMB, you have to maintain two version. In my method, >you do not need to. Well I see no need to ever design a system where one day I use ARM and the next day Thumb. And it is quite possible to have one application require an ARM kernal for performance reasons and another to require a Thumb kernal for space reasons. The same reasons you would need to choose between the two in the linked library case. If you need to maintain two variants for one case you are likely to need to for the other. Ah, maybe I see where the difference is. Maybe you are working in an environment where you are supporting a multitude of simultaneous projects. I and I suspect most others here work a little more serially. Any one project is only going to use a single mode. The time spent to compile the support library appropriately is insignificant in this context. Each project must have it's own support library/kernal carried with it since upgrading it will require retesting the application. > > Your solution also needs to maintain both. You still need a library > >This is where I think you have not understood the code snippet that I >hoped will speak for itself. > >The kernel is compiled with the interface header and in 32-bit mode. >There is only one instance of the kernel in memory. Of course >The user code is compiled in 16- or 32-bit mode, and only one version >of its binary is in the system. You can have one application compiled >in 16-bit mode, and another in 32-bit mode, coexist in the same >system, and use the same calls, with only one copy of the binary of >each of these applications. OK, now we are getting somewhere. You are talking about the large system similar to the RAM loaded case I was talking about in an earlier post. Different world entirely. This would be possible to do with a jump table but that's the same thing in less convenient clothing. Here I see an advantage and a big one. It also explains why you'd want a unified image for the kernal. All the applications I need to deal with run a single application. Multiple threads sometimes but a single application. > > - How does implementing a kernal help you narrow that region > > down? > >Because the kernel handles all interrupt enable and disable >operations, this is where one starts looking for problems relating >interrupts disabled but not enabled thereafter. OK, I can see what you are getting at, You can instrument the function/SWI calls. That's how I would normally implement a disable/restore pair in any case. That still leaves the issue of finding the mismatched pair. An appropriate trigger on a trace could narrow it down in a hurry though. I just normally refer to my support library as a support library and reserve kernal for when I bring in task switching/threads whether cooperative or preemptive. Different word choices. >This is where I ask people to include memory protection in their >selection of targets for their application. I'd like to have memory protection, but I've yet to see a small inexpensive microcontroller with memory protection. Actually I've yet to see a microcontroller (IE only internal memory) with memory protection but I freely admit there are many micros I've not perused. Generally I/O is my first consideration. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-19 by jayasooriah
Robert, Given my aim is to present an alternative view, but not to impose this on anyone who does not appreciate its merits, I like pointing out only what I believe has been grossly mistated or incorrect: --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> > Nonsense. If the user application hangs up the fact that the user code is > in user mode but the kernal in system mode won't make recovery easier or > harder. [example deleted] If this were true, the notion of privilege or levels of privilage in operating systems would meaningless. > There is zero extra protection available by placing the kernal in system > mode and the application in user mode. You may not see them, but I do and we just have to agree to disagree. [I tend to work towards clients requirements and not redefine them. When they say they want to do this, I just show them how to.] Cheers, Jaya
2006-04-19 by brendanmurphy37
Jaya, Robert is not incorrect. The fact the LPC2k has different operating modes does not mean it has the capability of implementing a privileged mode operating system. Hence your comment "If this were true, the notion of privilege or levels of privilege in operating systems would meaningless" is itself meaningless. The purpose of such operating systems is to have fortress-like walls around the operating system/kernel facilities, memory and I/O space. These walls are built using privileged processor modes and some form of memory protection. The memory protection bit is absent on the LPC2k. The purpose of mechanisms like software interrupts is to provide a controlled gateway through these walls. If these walls don't exist (and they don't on the LPC2k, as it has no memory protection mechanism), any application can simply bypass the gateway and wreck havoc with the system. In other words, your carefully constructed gateway has no functional use whatsoever (as Robert has pointed out). The software interrupt mechanism has no protection in itself: it is simply a mechanism to gain access through a protected barrier. You are of course quite free to implement whatever modes and features you want. However, if you think that by implementing software interrupts and making use of user mode somehow offers you any degree of protection, you are deluding yourself (and from what you say, your clients). It simply isn't the case. If I've stated anything factually incorrect above, I'm happy to correct it. Hopefully though, this will clarify matters, and prevent yet another interminable discussion. Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > Robert, > > Given my aim is to present an alternative view, but not to impose this > on anyone who does not appreciate its merits, I like pointing out only > what I believe has been grossly mistated or incorrect: > > --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@> > > Nonsense. If the user application hangs up the fact that the user > code is > > in user mode but the kernal in system mode won't make recovery > easier or > > harder. > > [example deleted] > > If this were true, the notion of privilege or levels of privilage in > operating systems would meaningless. > > > There is zero extra protection available by placing the kernal in > system > > mode and the application in user mode. > > You may not see them, but I do and we just have to agree to disagree.
> > [I tend to work towards clients requirements and not redefine them. > When they say they want to do this, I just show them how to.] > > Cheers, > > Jaya >
2006-04-19 by jayasooriah
--- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendanmurphy37@...> wrote: > Jaya, ... > If I've stated anything factually incorrect above, I'm happy to > correct it. Oh no! Not again! Did I not tell you not address me Brendan? Try it. It is not hard to do. Thanks for understanding. Jaya
2006-04-19 by brendanmurphy37
I wasn't addressing you: I was posting a message on an open forum to correct some misinformation you posted on that same open forum. As a matter of courtesy, I put your name at the top of the post to clarify the exact message I was responding to: I'm happy to stop doing this if it upsets you. Best wishes Brendan --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote: > > --- In lpc2000@yahoogroups.com, "brendanmurphy37" > <brendanmurphy37@> wrote: > > > Jaya, > ... > > If I've stated anything factually incorrect above, I'm happy to > > correct it. > > Oh no! Not again! > > Did I not tell you not address me Brendan? Try it. It is not hard to do.
> > Thanks for understanding. > > Jaya >
2006-04-19 by Robert Adsett
At 04:29 AM 4/19/2006 +0000, jayasooriah wrote: >--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> > >Nonsense. If the user application hangs up the fact that the user >code is > > in user mode but the kernal in system mode won't make recovery >easier or > > harder. > >[example deleted] > >If this were true, the notion of privilege or levels of privilage in >operating systems would meaningless. In those systems the privilege levels are supported by HW which restricts access. Sometimes as 'simple' as a MMU but often with restrictions on I/O access as well. Sometimes with restrictions on the way pointers to memory can be passed between privilege levels. W/O this hardware support, which is not present on the ARM microcontrollers we are talking about, there is indeed no protection offered. Indeed there were Unix variants for the PC before the protection features of the '286 and they did suffer from this flaw. User programs could bring the system down so that a hard reset was required (system programs sometimes caused similar problems but since most of them had been tested on systems with MMU that would core dump in such an event most such bugs had been stamped out) uCLinux will have the same issue. That doesn't mean that in an environment with multiple applications on the same processor there isn't any benefit in having a common 'shared' library or kernal. That just isn't the case we've been talking about, at least I haven't, but rather the more typical microcontroller case of a single application on a microprocessor. >[I tend to work towards clients requirements and not redefine them. >When they say they want to do this, I just show them how to.] I work towards customer requirements as well but I do warn them when they suggest something that's physically impossible. And without hardware support you cannot prevent an application bug from bringing down a microcontroller. There is one exception to this HW requirement and that is when all of the programs access and I/O is mediated by SW by running in an interpreter. Essentially in that case the necessary HW is simulated. With good design, appropriate tools and reviews you can avoid getting the bug there in the first place but user/system mode on a LPC2000 isn't going to get you any closer than a well designed library. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-20 by jayasooriah
Robert, I think you are mixing privilege with protection. I refer to privilege as a policy without reference to mechanisms to enforce this policy. Whether or not you need protection to enforce a particular policy depends on requirements: * In the context of general purpose operating systems (like that on a desktop), the requirement is that policy be enforced assuming the tasks are hostile. * In the context of embedded systems, the OS (or kernel) assumes that the tasks are cooperative -- that they are making a kernel call not because they do not have the means to do this on their own. Just because a task can do anything it does not follow that having a task do whatever it can do without reference to other tasks (current and in the future) is a good idea. For the above reason I do not find your argument relevant to the original proposition: to recognise that even in embedded systems, the notion of user vs system can be exploited to make the system easier to describe and manage. Jaya --- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > > At 04:29 AM 4/19/2006 +0000, jayasooriah wrote: > >--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@> > > >If this were true, the notion of privilege or levels of privilage in > >operating systems would meaningless. > > In those systems the privilege levels are supported by HW which restricts > access. Sometimes as 'simple' as a MMU but often with restrictions on I/O > access as well. Sometimes with restrictions on the way pointers to memory
> can be passed between privilege levels. > > W/O this hardware support, which is not present on the ARM > microcontrollers we are talking about, there is indeed no protection > offered.
2006-04-20 by Robert Adsett
At 12:13 AM 4/20/2006 +0000, jayasooriah wrote:
>* In the context of embedded systems, the OS (or kernel) assumes that
>the tasks are cooperative -- that they are making a kernel call not
>because they do not have the means to do this on their own.
>
>Just because a task can do anything it does not follow that having a
>task do whatever it can do without reference to other tasks (current
>and in the future) is a good idea.
Where on earth did you get the idea I thought otherwise?
Yet again, this has nothing to do with system/user mode. It just describes
a well designed library/kernal. I agree, have always agreed, that a well
designed kernal with behaving tasks is a good idea.
>For the above reason I do not find your argument relevant to the
>original proposition: to recognise that even in embedded systems, the
>notion of user vs system can be exploited to make the system easier to
>describe and manage.
You are arguing against a position I haven't taken. A division of
responsibilities is a good thing, A random sprinkling of I/O and control
code would, I agree, be a bad thing. Limiting control to specific areas is
just good design.
The question is: what extra advantage running in user mode and making calls
to a system mode kernal provides over an application running in system mode
making calls to a system mode kernal?
I see no advantage just from having two different modes w/o any distinction
between them.
If you use SWI as the link mechanism, you can in either case but it's a
natural fit with the user/system case, then I see the following breakdown.
SWI advantages
decouples the calling routines from the implementing
routines. This shows as an advantage in systems that have multiple
applications loaded or have applications loaded into memory at runtime
since they can share a common kernal implementation.
Most natural implementations naturally provide the library as a
single block of memory. An advantage if you are loading multiple
applications. perhaps but otherwise..? Could be done straightforwardly
enough with the linker if it was really desired, I've done a similar thing
on a system with a fragmented memory map.
SWI disadvantages:
decouples the calling routines from the implementing
routines. The normal type checking is broken across the SWI/IRQ
barrier. Presumably a well written implementation of the stub library on
the caller side will substitute but it is still quite easy to change either
the caller stub or the implementing routine independently and break the
interface. The same can happen with a linked library of course but you do
have that extra level of type checking in the interface.
In either case a well designed application will usually segregate I/O
functionality from processing functionality and base support routines will
be separate again. Much of the base support is reusable on multiple
systems, some of the I/O functionality may be.
For a system with multiple applications I'd definitely consider SWI. If I
used SWI theres a good chance I'd run the app in user mode as it's a
natural fit. For a standard single application system though there is no
advantage(1).
My original question was prompted by the suggestion that I thought I saw in
tour post that user mode provided some significant protection. If all it
is turns out to be that it fits naturally with SWI that's fine. I just
don't see that being an advantage for your typical single application
microcontroller embedded system.
(1) There is a single application type I thought of while writing this that
would benefit from using SWI as a jump table. That's the case where a
single application runs on multiple HW platforms and relies on the HW
platforms kernal to provide functionality that may be implemented
differently on each one. Not the type of application I was thinking of though.
Robert
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-20 by 42Bastian Schick
Robert Adsett schrieb: I jump in late, so sorry if I repeat an arguement: > The question is: what extra advantage running in user mode and making calls > to a system mode kernal provides over an application running in system mode > making calls to a system mode kernal? Even if there is no MMU/MPU which restricts access to memory, one vital resource can be restricted: Interrupts. In USR mode, you cannot modify the interrupt-bits whereas in SYS mode you can. Means, running tasks in USR mode lets the OS control the disabling of interrupts. -- 42Bastian
2006-04-20 by jayasooriah
--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > For a system with multiple applications I'd definitely consider SWI. If I > used SWI theres a good chance I'd run the app in user mode as it's a > natural fit. Although I do not know what you mean by "application" I do not disagree with the above. > For a standard single application system though there is no > advantage(1). What you mean by "single application system" is important. I prefer to look the "application" running on an embedded system as a set of independent and cooperating tasks, where a task in an entity that has a own state (stack), and which it returns to when it is suspended (for any reason) and then resumed. If by "single application system" you mean the system comprises of only one task, then any monolithic system approach would do, and there is little value in separating the things that the task does into different baskets. I did not think that any of the things that participants here are doing with the LPC falls in the latter category. This is why I started with the SWI approach to my simple example atomic feed of watchdog timer. It does not matter to me what term is used to describe what happens on the two sides of the SWI fence. It could well be public vs private, system vs user, kernel vs user, or infrastructure vs application. Jaya
2006-04-20 by jayasooriah
--- In lpc2000@yahoogroups.com, 42Bastian Schick <bastian42@...> wrote: > > The question is: what extra advantage running in user mode and making calls > > to a system mode kernal provides over an application running in system mode > > making calls to a system mode kernal? > > Even if there is no MMU/MPU which restricts access to memory, one vital > resource can be restricted: Interrupts. > > In USR mode, you cannot modify the interrupt-bits whereas in SYS mode > you can. > > Means, running tasks in USR mode lets the OS control the disabling of > interrupts. Thanks Bastian for pointing out Robert's questions I missed in my most recent response. My understanding of Robert's position (apologies if I misunderstood) is that because there are other ways a rogue task running in user mode can compromise the system why bother running any in user mode at all. Given if one uses the SWI interface, it comes at no cost, I prefer to question why not. I can see why some chose to run all tasks in user mode to harness not only the direct privilege differences you point out, but also ripple down effects onto other things for control for coordination purposes. Accepting embedded ARM users in general have different requirements, my personal experience has been that that LPC users appear to have somewhat different requirements compared to users of other variants. Especially on on matters related to security, protection, and maybe even watchdog requirements. Jaya
2006-04-20 by Robert Adsett
At 11:47 AM 4/20/06 +0200, 42Bastian Schick wrote: >Robert Adsett schrieb: > >I jump in late, so sorry if I repeat an arguement: Just as Jaya and I were winding down to a conclusion :) > > The question is: what extra advantage running in user mode and making > calls > > to a system mode kernal provides over an application running in system > mode > > making calls to a system mode kernal? > >Even if there is no MMU/MPU which restricts access to memory, one vital >resource can be restricted: Interrupts. > >In USR mode, you cannot modify the interrupt-bits whereas in SYS mode >you can. > >Means, running tasks in USR mode lets the OS control the disabling of >interrupts. I suggested that once as a possible advantage. Jaya assured me that the interrupt disable/restore was exposed as a function across the barrier in his implementation. That would rather negate the advantage. I can see that (restricting the ability to disable interrupts) as an advantage, especially for larger systems. When I asked the question originally it hadn't occurred to me to only disable interrupts in system mode. For most of the stuff I do I don't see it being worth the extra trouble but that does make the distinction useful for a wider variety of projects. Of course once you had it set up like that for one project it would be easy to carry across to smaller projects at little or no cost. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-20 by Robert Adsett
At 12:03 PM 4/20/06 +0000, jayasooriah wrote: >Given if one uses the SWI interface, it comes at no cost, I prefer to >question why not. AHA! Why didn't you say so ;) I was under the impression the drive was the other way around. You had decided on user/system mode because of some protection that user mode provided and that led you to use SWI. If you are using SWI then yes it makes a lot of sense to do it from user mode. I was trying to figure out what that protection was. That suggestion I made a few days back of reserving interrupt disabled code just to the kernal is intriguing. I'll have to noodle around with that a bit. >Accepting embedded ARM users in general have different requirements, >my personal experience has been that that LPC users appear to have >somewhat different requirements compared to users of other variants. >Especially on on matters related to security, protection, and maybe >even watchdog requirements. There's a lot of people here from small micros. Particularly the MSP430 for some reason. Robert " 'Freedom' has no meaning of itself. There are always restrictions, be they legal, genetic, or physical. If you don't believe me, try to chew a radio signal. " -- Kelvin Throop, III http://www.aeolusdevelopment.com/
2006-04-21 by Robert Adsett
At 09:49 AM 4/20/06 +0000, jayasooriah wrote:
>--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
> > For a standard single application system though there is no
> > advantage(1).
>
>What you mean by "single application system" is important.
>
>I prefer to look the "application" running on an embedded system as a
>set of independent and cooperating tasks, where a task in an entity
>that has a own state (stack), and which it returns to when it is
>suspended (for any reason) and then resumed.
Much the same as I do. A single application would be a single loadable
entity. It could be one or more tasks. But the threads of execution are
closely related. There is a bit of a grey area between a single and
multiple applications, more so than there used to be. Tasking if present
could be co-operative or pre-emptive.
The key differences are
In a single application the threads are usually fairly tightly
coupled. In a multiple application environment they are more loosely
coupled. Not very precise, I know.
In a single application the code for the tasks/threads are loaded
into the flash as a single unit. In a multiple applications the pieces can
be loaded separately. The latter case practically requires some sort of
BIOS/Kernal communicated with in some indirect fashion like SWI.
Indeed I have not seen a real time kernal (as opposed to a heavier real
time OS) that wasn't supplied as a linkable library. Even ecos which is a
relative heavyweight is, I think, a linkable library. OS/Kernal is a
distinction I maintain but the distinction seems to have lost much of it's
meaning over the years with items like uCOS etc. referring to themselves as
RTOS's
As I said though, I am intrigued by the thought of restricting interrupt
off periods to a user mode protected kernal. I don't find leaving
interrupts off to have been a big problem in my development but I am in
favour of anything that will protect me from myself, especially if it's
free. I just have to figure out what exactly the benefits of restricting
that access will be compared to the cognitive cost of a decoupled interface
and loss of type checking across the SWI barrier.
>I did not think that any of the things that participants here are
>doing with the LPC falls in the latter category. This is why I
>started with the SWI approach to my simple example atomic feed of
>watchdog timer.
A monolithic single application. I suspect there are. I've used the LPC
to quickly prototype a monolithic app. It was overkill for it but for a
prototype it allowed a rather quick assembly of components. There was a
time people used DOS for single monolithic embedded applications. Actually
I suspect some people still do. I would be surprised if the LPC family
wasn't being used in the same fashion.
>It does not matter to me what term is used to describe what happens on
>the two sides of the SWI fence. It could well be public vs private,
>system vs user, kernel vs user, or infrastructure vs application.
>
>Jaya
>
>
>
>
>
>
>Yahoo! Groups Links
>
>
>
>
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-21 by Robert Adsett
At 12:03 PM 4/20/06 +0000, jayasooriah wrote:
>Accepting embedded ARM users in general have different requirements,
>my personal experience has been that that LPC users appear to have
>somewhat different requirements compared to users of other variants.
>Especially on on matters related to security, protection, and maybe
>even watchdog requirements.
Just as a matter of information. It may give some insight into some
portion of the membership here. I doubt I'm unique in any of these
viewpoints although I may well be in a minority.
Security - Don't need it. To copy my SW they also have to
(generally ) copy the HW. It's a lot easier to tell when they've done
that. For many products it's as easy to redesign as it is to copy. Others
have different requirements although I suspect that in general people
overestimate the value of their SW. Hey it's their sweat equity they have
every right to value it.
Protection - I'll take whatever I can get for a reasonable
price. Reasonable depends on the project. Ideally I'd like to restrict I/O
and memory access ranges to specific process for no extra memory or dollar
cost. :) Likewise ESD and EMI/EMC protection, Oscillator watchdogs etc..
Watchdog - Depends on the project but for most I want a
watchdog. It's not there as a normal guard against program bugs and such
but as a last attempt to get back to a safe starting point. It might catch
items the ESD discharges that make it through the hole the customer put
into the enclosure with a forklift and changed the short timing loop into
an infinite loop;) It certainly should never be part of normal operation
and it's one of the very last pieces put into place.
Robert
" 'Freedom' has no meaning of itself. There are always restrictions, be
they legal, genetic, or physical. If you don't believe me, try to chew a
radio signal. " -- Kelvin Throop, III
http://www.aeolusdevelopment.com/2006-04-22 by jayasooriah
--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote: > > At 12:03 PM 4/20/06 +0000, jayasooriah wrote: > >Given if one uses the SWI interface, it comes at no cost, I prefer to > >question why not. > > AHA! Why didn't you say so ;) I think I did but not using these words. I wish I had made this clearer. So as not to risk keeping a thread going well beyond its use by date, I will take up your follow on points as a separate thread. Hope you do not mind. I will follow the "was" protocol to link the threads, and you (or anyone else) responding can then strip the "was" component :) Jaya PS: Bit snowed under at the moment, but wont be long.