more avr-gcc inline assembler goodies: constraints

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While I now agree it's better to avoid the inline assembler, I thought it's faster to debug it as it is now.

The error I made was the following:

#define SOMECONSTANT 12
[...]
   "lds   r30, %[_SOMECONSTANT] \n\t"
[...]
   :
   : [_SOMECONSTANT] "M" (SOMECONSTANT)

OK, stupid typo, should've been ldi rather than lds. Nevertheless, the compiler did not complain and produced assemblable code.

Is this OK? I don't think "M" should be a valid constraint for the right-hand lds parameter...

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

12 fits fits the 'M' constraint, so the compiler is happy. 'lds r30,12' is a valid instruction, so the assembler is happy. Happy compilers and assemblers do not correct code always make (Confucius saying).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I guess, I have an incorrect notion on what exactly the constraints are supposed to mean.

Anyway, the Cookbook says, constraints for *lds*' parameters are *r,label*. Nothing more is said about *label*. I guess I also have unrealistic expectations towards the inline assembler... ;-)

Thanks for the explanation.

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that the inline assembly generator does
not enforce the constraints on individual instructions.
It doesn't know the instruction set and it
believes what you tell it the constraints are.
If you tell it too big a whopper,
the assembler will either complain
or produce code you don't want.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, it sounds like that.

Pity. I just made the same error again... :-( Time to go home to kids and wife.

Thanks,

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The C compiler doesn't check any line of your assembler code. But it is able to check the constraint against your C expression. However, if you specify the wrong constraints, then the compiler may silently pass wrong code to the assembler. And, of course, the assembler will fail with some cryptic output or internal errors.
'label' is just an address, me thinks. So anything that can be described with an address, is a 'label' (like a label, or a global variable, or the address of a function). There is also an "i" constraint that is M's big brother (16bit). Its not in the documentation, but I found it somewhere- reading the source code or possibly seeing libc examples, or somewhere.

If you want to see the (little) mother of all combined c/inline asm (in the middle of my slow transformation)-
http://www.mtcnet.net/~henryvm/A...

It slowly transformed from all C, to all asm-
http://www.mtcnet.net/~henryvm/A...

A 'few' lines is my inline asm limit, anything over 256 words is my asm limit. As Microsoft proves daily, there is no limit to higher level languages (check the size of their latest .net update).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Anyway, the Cookbook says, constraints for *lds*' parameters are *r,label*.

It's slightly wrong on that. If you look into the AVR Instruction Reference,
the syntax is

LDS Rd, k

Rd is the destination register, and k is a constant 16-bit address. For the
convenience of the user, the assembler allows for the constant to be a
label (where the actual value will be inserted by the linker), but of course,
a literal constant is always acceptable as well -- so neither the compiler
nor the assembler have any reasons to complain.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
If you want to see the (little) mother of all combined c/inline asm (in the middle of my slow transformation)-
http://www.mtcnet.net/~henryvm/A...

It slowly transformed from all C, to all asm-
http://www.mtcnet.net/~henryvm/A...

I know which one I find easier to read. On the other hand it may be something to do with your original choice of colour scheme.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:

If you want to see the (little) mother of all combined c/inline asm (in the middle of my slow transformation)-
http://www.mtcnet.net/~henryvm/A...

I want to know how long it took you do the "ascii art text" headers. ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Neither one is easy to read (you can click on the file links, which will show 'plain text').

C is 'best', but I needed (wanted) to fit in 256 words, so I started using inline asm to save 'some' code space. More inline asm = more code space = more features = less code space = more inline asm. Repeat. But getting that mixed up contraption to compile under 256 words with different compiler versions was a problem. So I went 'all the way' to asm. I get to keep the preprocessor, all versions assemble to the same size. I'm happy. I don't want to do it again.

Ascii art? Doesn't take long-
http://www.network-science.de/as...
(I surely couldn't do that on my own)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
There is also an "i" constraint that is M's big brother (16bit). Its not in the documentation, but I found it somewhere- reading the source code or possibly seeing libc examples, or somewhere.

This is because the Cookbook appears to list only the constraints specific to AVR, and omits the "standard" constraints.

curtvm wrote:
A 'few' lines is my inline asm limit, anything over 256 words is my asm limit. As Microsoft proves daily, there is no limit to higher level languages (check the size of their latest .net update).

I leave that for those who program big machines. As long as I am paid for programming microcontrollers, I do my best to fit within whatever constraints it means, memory- and cycle-size, and asm is just an another tool to achieve it.

I freely admit I would have hard time to build a behemoth on a PC. It's just not my side of the playground.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I've just been slapped onto my face for trying to be too smart:

avr-gcc wrote:
error: more than 30 operands in 'asm'

Start laughing, now.

JW

PS. Any quick suggestions, except to port it to not-inline version? Please... :-(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there some reason you cannot split what you are doing into several smaller asm("") statements then?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes: there are too many labels scattered throughout it. I see it's still doable by cutting it up and encapsulating to naked C functions and use those labels for jumping up and down, but that'd be rather ugly.

For now, I simply replaced 3 constants (port bit names) by their numerical values, by which I cut down the number of operands to exactly 30; but I am not quite happy with this, as I am supposed to port this to a different device in a few weeks and then provide it also as a source library for other adopters, and I though it to be a good idea not to have to tweak it manually for each future device...

Time is pressing so most probably I will leave it as it is now, and get back to it later when needed.

Thanks to all for ideas. One sometime needs to be kicked a bit...

Jan Waclawek

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Is there some reason you cannot split what you are doing into several smaller asm("") statements then?
If they're consecutive, that wouldn't necessarily be less complicated.

Also, if different pieces need the same operands,
splitting might make it more complicated.

That said, different pieces of inline
assembly can refer to each other.
It's possible that doing so might reduce the amount needed.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The more I think about it... it's an ISR branching 3 ways... definitively split-able, if some of the code will be replicated (e.g. the "lead-out") ... just ugly ;-)

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

If they're consecutive, that wouldn't necessarily be less complicated.

Why?

(remember the error to be fixed was "more than 30 operands in 'asm' ")

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

If they're consecutive, that wouldn't necessarily be less complicated.

Why?

(remember the error to be fixed was "more than 30 operands in 'asm' ")

If the measure of complexity of a piece is
strictly superlinear in the number of operands,
then probably splitting it would make the aggregate less complex.
If connecting the pieces requires more operands,
even if fewer operands per piece,
then the complexity might increase.

That said, if one can fit debugging statements between the pieces,
that might be more important than the precise measure of complexity.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> it's an ISR branching 3 ways

This heavily smells to me as if it were most likely /much/ simpler to
completely write that within a separate assembly code file.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
> it's an ISR branching 3 ways

This heavily smells to me as if it were most likely /much/ simpler to
completely write that within a separate assembly code file.


By now, I am quite convinced it is. Not *much* simpler, but simpler. It involves added complexity for the prospective user, though; as it would not be a simple object plus a header to be linked to his application. Maybe I should learn more also about libraries.

However, the pressure of time does not allow me to go through all of it (learning + porting) at the moment. I am still busy killing all the bugs I carefully planted to the code in the writing phase :-(

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

as it would not be a simple object plus a header to be linked to his application. Maybe I should learn more also about libraries.

There's nothing to it. You'll already have a .S file being assembled to produce a .o - at this stage it's not really much different than if the .o had started life as a .c file

You now just use:

avr-ar rcs libmine.a code.o

as described here:

http://www.gnu.org/savannah-chec...

You now just give them libmine.a and the .h that documents its interface and instruct them to add -lmine to their link. Job done.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hummm. Thanks a lot. Okay, one thing less to find out. That makes ONLY 999 remaining ;-)

Back to hunt down the ugly bug...

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just for the record: the problem with max.30 parameters per inline asm command sort of solved itself...

After adding more and more features to the interrupts (which is a timer interrupt, more precisely an output compare interrupt) it hit the ceiling - the latency caused by cumulative effect of all concurrent interrupts plus the complex n-way branching in the said interrupt until the compare register got re-calculated, from time to time caused the compare register to be updated too late and the next interrupt occured after a full cycle of the timer. Imagine how fun was to find out this. OK, I am guilty of not counting all the cycles - but, honestly, who's ready to throw a stone...? ;-)

So I split the whole thing into two interspersed timers (still written in that terrible inline assembler - I sort of got used to in during the last few days), which simultaneously solved also the problem with too many parameters and also reduced complexity of changing timing... OK, at this point, one may say, I am guilty of not going for the optimum solution from the very beginning... ;-)

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jan,

I have no idea of what you are trying to do, but at a guess you have a regular timer IRQ and you perform multiple services in the ISR.

It is likely that most services are only done on the 10th or 100th IRQ. A few services are v.important and are done on every IRQ.

The less frequent jobs are the longer ones. Then you could always stagger them e.g. the every 10 group are serviced on IRQ #2, #12 etc and the every 1000 group on IRQ #3, #1003 etc.

You could also do a scheduling scheme to even out the workload.

I would be very surprised to find you running out of time in an ISR. It does not take long to check a few bits and flags, load or read hardware registers and be on your way.

The algorithm rather than the language is the key.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David,

David wrote:
It does not take long to[...]

Well, this sort of depends on your definition of "long time"... :-)

My budget in the tightest case was around 100 cycles.

The impact of "irregular" cases is, that you need to maintain state variable(s), update, and branch upon at the beginning of the ISR. Besides, I needed to have variable timing dependent on the branch being executed.

Add to this the impact of other ISRs to latency - clearlly, they need to be optimised down to the last cycle, too.

David wrote:
The algorithm rather than the language is the key.

Absolutely. This is why I stick to asm rather than struggle with C... ;-)

I discussed exactly this issue with my colleague last Friday. The algorithm evolved. Initially, I had a rather naive picture on it until I tried and found out the dead ends. I knew there would be issues and I also made a couple of stupid typos and copy-paste induced errors, but I see no reason why it wouldn't have issues and why I wouldn't make typos and copy-paste induced errors, would I write it in C.

While the timer interrupt in question is maybe 50 lines of asm, the startup code, headers, declarations - which are mostly C - etc.etc. double that; the framework needed for the testing just on that microcontroller (again in C) triples that; to be able to run anything on that microcontroller, code had to be written for another two microcontrollers - most of it in C; and code had to be written on PC, too - I prefer Pascal where I have choice. Test jigs had to be prepared, that means, solderwork, wiring, cabling. Acquired data had to be analysed. Errors occurred everywhere.

I mean maybe there are perfect people, maybe also engineers, that get things correct right away. I have one to meet, yet -certainly although, judging what people say on fora like this one, there are many out there. I am not that type. And, I am not shy to talk about my errors, which is maybe not the best thing to do...

JW