compiling error using an assembly macro

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

Hi,

I wrote a program that should create an square wave using an assembly macro, with the asm keyword in C. I am using 64 "NOPs" with a MCU running at 16MHz.
It works just fine, but if I call several times the same macro I get the following error:

/tmp/ccQo9mux.o: In function `main':
/home/luis/project.c:103: relocation truncated to fit: R_AVR_7_PCREL against `no symbol'
make: *** [project.hex] Error 1

What is this happening? And how can I fix this?

This is the code I am using:

	     PORTB &= ~(1<<PB3); //Sets pin PB3 LOW
		   asm("Delay4");
		   asm("Delay4");
		   asm("Delay4");
		   asm("Delay4");
		   asm("Delay4");
		   asm("Delay4");
		   PORTB |= (1<<PB3); //Sets pin PB3 HIGH
		   asm("Delay4");
		   asm("Delay4");
		   asm("Delay4");
		   PORTB &= ~(1<<PB3); //LOW

The Delay4 macro are just 64 NOPs...

asm(".MACRO Delay4\n\t"
"NOP\n\t ; NO Operation"
...
//64 NOPs
".ENDM\n\t");

This code works just fine, but if I call the macro more times, I get that error.

Thank you

NOTE: Please accept my apologizes for double posting the same question. But someone was spamming my other thread, and it suddenly got off-topic. The other thread is probably going to be deleted soon.

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

You need to read the documentation for declaring and invoking macros.

In the process you may discover the .REPT directive.

If you are the same person who takes no notice of any advice, please ignore this as well.

David.

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

Hello!
Thanks for the reply.

I read through the macros documentation, the rept directive is very helpful. Thank you!!
I replaced my macros with the rept directive, but I keep getting the same error.. In the macros documentation I don't see any other thing I could be missing.

This is my code now:

asm(".MACRO Delay4\n\t\n\t"
".rept 64\n\t"
"NOP\n\t"
".endr\n\t"
".ENDM");

asm(".MACRO Delay8\n\t\n\t"
".rept 128\n\t"
"NOP\n\t"
".endr\n\t"
".ENDM");

Quote:
If you are the same person who takes no notice of any advice, please ignore this as well.

I don't know what you mean by that. That's why I am asking here on the forums, to hear other's advices :p

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

Try reading the documentation.

Your first step is to understand what a macro is.

You can have an assembly language .MACRO
Or a C pre-processor #define macro

Is English your first language?
You should find ASM textbooks and C textbooks are printed in every language known to man.

If you do not understand something, just ask. If you say your preferred language, someone may be able to recommend a specific book or website in your language.

David.

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

lcruz007:
Many people looking for help ignore the advice given beause it wasn't the the answer they wanted, i.e. spoon fed on a silver platter. Then they continue to ask the same question in another thread hoping for the custom written code they really wanted. They either learn to try the given advice or they tend to be ignored.

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

I really thank you for the advice David. But with all due respect, I know exactly the definition of a macro, and I don't think I need to go over again its explanation.
Actually I have worked with them in the past with the assembly language. Not with AVR hardware though.

Now, I am not saying I completely understand everything regarding macros in asm, and I will take the time to read when it is necessary.
However, I cannot find a text that points out to a problem in my current code (working only with a few calls to my macro), everything should be fine. Because my code works once, but when editing it, I get that rare error that not even experts (like you guys) in the topic knows!

I don't want to sound mean or anything, actually I am glad I can receive advices from others. But no one has answered my question yet. And I think telling someone to read the basic part of the topic again, is not a solution for my CURRENT problem.

I am not asking the same questions several times in different threads, this is a different topic. Not video generation, if that's what you're thinking.

I would appreciate if someone could help me with my problem.

Thanks in advance.

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

Quote:
I get that dang error

Not exactly English, but you do not mention any other language.

You can create delays with a fixed # cycles by just using the macros (interrupts disabled).

I would sooner top myself than use inline assembly in avr-gcc. However I will assume that you can declare an assembly macro at one point in a C file and invoke it elsewhere.

You cannot normally make multiple declarations of any macro. You normally use local labels in any macro expansion.

Trying to combine inline assembly with C is inevitably going to cause the odd relocation difficulty. Why not look at the generated assembly?

If you want to generate video signals, search out the several AVR implementations. See how other people do it. Yes you can write foreground code in C. Yes you can synchronise horizontal scans.

No you cannot afford to do a lot of time wasting.

Hint. Avr-as is nice and pleasant to use. Write ASM code in ASM rather than the avr-gcc contortions.

David.

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

david.prentice wrote:
Quote:
I get that dang error

Not exactly English, but you do not mention any other language.

I am sorry, I did not want to swear on the forums. :p
Spanish is my native language.

OK, thanks for the info. :)
BTW, I have seen that using asm delays is much precise than the normal delays macro from . That's why I wanted to use this.

Not video generation this time. I did follow your advice. I am now using a timer CTC overflow that wakes my MCU from a short nap to keep the Hsync more stable.

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

Either obeying NOP instructions or a SBIW / BRNE loop is still a predictable # of cycles.

You can see for yourself in the simulator.

But both methods will go wrong if interrupted. This is why God invented hardware timers.

Purists will argue that C is not predictable. However the macros ensure that it is.

David.

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

Inline assembler macros sometimes defeat the compiler.
For some things, e.g. figuring out whether an RJMP will work,
the compiler needs an estimate of the number of
object bytes produced by inline assembly code.
If the estimate is too low,
the answer will be yes when it should be no.
The compiler produces an RJMP too far
and the linker reports an error.
I'm not sure why the assembler doesn't notice.
The compiler doesn't understand inline assembler.
It uses the number of lines to produce the estimate.
Assembler macros defeat this process.

Edit: I don't know whether the above is in the FM.
I got it from an AVR-Freaks thread.

Using preprocessor macros will let the compiler get the estimate right.

#define m64(str) m16(str) m16(str) m16(str) m16(str)
#define m16(str)  m4(str)  m4(str)  m4(str)  m4(str)
#define  m4(str)     str      str      str      str

asm ( m64(" NOP\n") ::: );
asm ( m16(" RJMP .\n"
          " RJMP .\n") ::: );

A loop would be much more compact.

Iluvatar is the better part of Valar.

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

Thanks all for your replies. These answers certainly have helped me. I will let you know my progress.

Thank you