Trying to Write ToggleLED for MPC860 using GCC inline assembly

Jul 03, 2003 9 Replies

Hello, I have never used inline assemblly before so i don't know the calls or the structure. i have read other posts but am still pretty confused how to do it. I have come up with the following code to do a toggleled



#define LED_RED 0x01 /* Red Ethernet LED on the Freakin Board */ #define ETHLED 0xFA400000 /*BCSR0*/ void main (void) { int count; while (1) { count = 0; toggleled(LED_RED); while(count < 50*5000) /* (MHZ)*(Number of nanosecs) */ { ++count; } } }



void toggleled(unsigned char ledMask) { // insert inline assembly }



I am trying to write a small inline assembly program that just writes a "01" value into a register of address FA400000. Can anyone help me figure out the syntax/commands for this operation? I have no idea what so ever.



Thank you much.



Fahd


First off, why are you wanting to do this with inline assembly? Inline assembly is useful for two things - writing highly optomised code for absolutely critical code sections, and for the occasional bit of low-level access that can't be done directly in C. The first reason does not apply here (unless you are very fluent in the cpu's assembly, and fully understand Knuth's rules of optomisation). The second reason applies for things like disabling interrupts, entering sleep modes, and the like - and on many toolchains these are covered by library functions.

The code you are really looking for is:

void main(void) { volatile int count; // The "volatile" qualifier is critical !

while (1) { *((unsigned char*) ETHLED) = LED_RED; for (count = 0; count < 50*5000; count++);

*((unsigned char*) ETHLED) = 0x00; for (count = 0; count < 50*5000; count++); }; }

No inline assembly is necessary.

You need to tell us which compiler you are using, since inline assembly syntax varies among compilers.

Otherwise, I wonder why you would do this in assembly?

Michael N. Moran (h) 770 516 7918 5009 Old Field Ct. (c) 678 521 5460 Kennesaw, GA 30144 "... abstractions save us time working, but they don't save us time learning." Joel Spolsky, The Law of Leaky Abstractions The Beatles were wrong: 1 & 1 & 1 is 1

To avoid later problems, I'd suggest accesses to hardware also with volatile: *((volatile unsigned char *)ETHLED) = LED_RED;

This mainly for status-bits.

Note: Look into the sources of the ppc-boot or linux. They even map structS directly over hardware. => no assembly

42Bastian

critical !

You are entirely correct here - hardware access should in general be done with volatiles. I suppose that's particularly important on a chip like the ppc, which could re-order reads or writes otherwise.

I think mapping structs to the hardware is an elegant way to do it, although people have different opinions on that (and especially on the use of bit-fields in these structs). Constructs like "*((volatile unsigned char

*)ETHLED) = LED_RED" are a mess, and should really be avoided - or at least, buried deep within low-level routines or macro definitions. But at least it should get the O/P started - it's nice to get your LED blinking first !

Actually, the powerpc knows nothing about whether an access (load/store) is to a volatile location or not. If you need to ensure that the processor does not reorder loads and stores, you need to use a processor specific barrier instruction. In the case of the powerpc this is the eieio instruction.

IOW, volatile only prevents the compiler from reordering accesses, not the processor.

To be even more picky, volatile is only required for hardware registers if the value can change without being changed by the hardware, or the act of reading or writing the location has other side effects, such as clearing other status or beginning the execution of a command.

Michael N. Moran (h) 770 516 7918 5009 Old Field Ct. (c) 678 521 5460 Kennesaw, GA 30144 "... abstractions save us time working, but they don't save us time learning." Joel Spolsky, The Law of Leaky Abstractions The Beatles were wrong: 1 & 1 & 1 is 1

Wrong. The semantics of the volatile qualifier, as defined by the ruling standard document, quite explicitly state that its effect must be that *no* reordering happens in the behaviour of the actual running code, compared to the order of operations expressed in the source code (the execution order of the so-called "abstract machine" on which all the defintion of C's semantics is based). This definition doesn't care at all whether the reordering is done by the compiler or the CPU

--- it's the net effect of both combined that is restricted.

I.e. if you write a compiler for this kind of CPU that may reorder accesses behind the machine code's back, then the compiler *must* apply counter-measures to avoid that for volatile-qualified accesses. At the very least, it has to run flow analysis to be able to decide that reordering, even if it happens, cannot have any unwanted effect. If that analysis fails, the compiler will have to output guard instructions to protect those volatile-critical sections. If it doesn't, it's not worth whatever you paid for it --- even it came for free.

I think you got that one wrong, too. It's needed if the value can change without being changed by the *software*. Typically because it *was* changed by the hardware itself.

Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) Even if all the snow were burnt, ashes would remain.

I think ther eis little discussion about bitfields. They are highly unportable and should be avoided.

Wolfgang Denk

Software Engineering: Embedded and Realtime Systems, Embedded Linux Phone: (+49)-8142-4596-87 Fax: (+49)-8142-4596-88 Web: www.denx.de The software required `Windows 95 or better', so I installed Linux.

Wolfgang Denk wrote in news: snipped-for-privacy@denx.muc.de:

Agreed, but within a given CPU and compiler they can add greatly to driver debugging when the debugger can "crack" bit-fields well.

- Mark -> --

Having done some driver development on the PPC I feel I should add my 2 cents too.

I've never seen GCC adding any synchronisation instructions (eieio, sync, isync) to the code. When dealing with hardware registers you have to declare them volatile to prevent the compiler from reordering or optimizing away your code. To prevent the CPU core from reordering hardware accesses or making speculative accesses to them, you have to mark the memory area "guarded". No synchronisation instructions are required then.

BTW. Hans I don't think GCC or PPC are broken. This is just the way PPC works. And it works well that way. If one does not understand these concepts he better sticks to Windows programming and lets the experts do the Embedded stuff :-)

Cheers

- Rene

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required