Assmber code in C project

Go To Last Post
59 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello All,

 

I would like to include a function written in assembler into my AVR Studio C project (yes it really does need to be in assembler, honestly, let's not debate this).

 

void HardwareInterface(unsigned char) __attribute__((naked));

 

void HardwareInterface(unsigned char DataForStuff)

{    cli();              // disable interrupts until all LEDs updated

       asm volatile

       ("     LDI R18, 0x00          // Useful comment

          label:

              OUT DDRB, R18         // Useful comment

                   //Blah blah blah lots of lovely assembler >>>>

             OUT PORTC, R18         // Useful comment

      ");

      sei();            // Update complete > re-enable_interrupts

      return ;   

}

 

This doesn't work (clearly, as I am posting :P ). I can make it compile by putting every single Mnemonic in a wrapper >

 

asm volatile (" LDI R18, 0x00");

asm volatile (" LDI R18, 0x00");

asm volatile (" LDI R18, 0x00");

 

But that seems very inefficient and also how do I add a label?

 

Can someone please help and give me a good example?

 

All the Best

 

Dren

 

 

 

 

 

This topic has a solution.

<º))))><

I am only one lab accident away from becoming a super villain.

Last Edited: Thu. Aug 30, 2018 - 02:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Atmel studio has no problem with mixed-language projects.

 

So the easiest way is to:

  1. write the function "outline" in 'C'
  2. let the compiler convert that to assembler
  3. throw away the original 'C', and just work with the assembler - which is bound to comply with 'C' naming & calling conventions, because the compiler did that for you.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why "naked"? That means there won't be a RET ?? Are you aiming for __attribute__((always_inline)) by any chance?

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

If you really need "lots of lovely assembler" then I would just write the function(s) in assembler, not bother with that (really ugly and distracting to my eyes) asm volatile stuff.  As mentioned, you can get the compiler to generate a function shell that you can use as a starting point.  You'll need to study up on which registers take arguments and return results, and which registers can be used without saving, vs which registers must be saved and restored if used.

 

Here's a C-callable asm function I wrote some years ago to give you one example.

 

https://www.embeddedrelated.com/...

 

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

kk6gm wrote:
You'll need to study up on which registers take arguments and return results

The beauty of getting the compiler to create the initial outline is that you don't have to worry about that; the compiler will do it for you - and is bound to get it right!

 

I guess you still need to pay attention to which registers can be used without saving, vs which registers must be saved and restored if used

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I change your code into something that would actually build:

#include<avr/io.h>
#include <avr/interrupt.h>

void HardwareInterface(unsigned char) __attribute__((naked));

void HardwareInterface(unsigned char DataForStuff)

{    cli();              // disable interrupts until all LEDs updated
       asm volatile
       ("     LDI R18, 0x00\n"          // Useful comment
          "label:\n"
              "OUT 0x04, R18\n"         // Useful comment
                   //Blah blah blah lots of lovely assembler >>>>
             "OUT 0x0A, R18\n"         // Useful comment
      );

      sei();            // Update complete > re-enable_interrupts
      return ;
}

int main () {
    HardwareInterface(0x55);
    HardwareInterface(0xAA);
}

and got:

00000022 <HardwareInterface>:

void HardwareInterface(unsigned char) __attribute__((naked));

void HardwareInterface(unsigned char DataForStuff)

{    cli();              // disable interrupts until all LEDs updated
  22:   f8 94           cli
       asm volatile
  24:   20 e0           ldi     r18, 0x00       ; 0

00000026 <label>:
  26:   24 b9           out     0x04, r18       ; 4
  28:   2a b9           out     0x0a, r18       ; 10
              "OUT 0x04, R18\n"         // Useful comment
                   //Blah blah blah lots of lovely assembler >>>>
             "OUT 0x0A, R18\n"         // Useful comment
      );

      sei();            // Update complete > re-enable_interrupts
  2a:   78 94           sei

0000002c <main>:
      return ;
}

int main () {
    HardwareInterface(0x55);
  2c:   85 e5           ldi     r24, 0x55       ; 85
  2e:   f9 df           rcall   .-14            ; 0x22 <HardwareInterface>
    HardwareInterface(0xAA);
  30:   8a ea           ldi     r24, 0xAA       ; 170
  32:   f7 df           rcall   .-18            ; 0x22 <HardwareInterface>
}
  34:   80 e0           ldi     r24, 0x00       ; 0
  36:   90 e0           ldi     r25, 0x00       ; 0
  38:   08 95           ret

This shows why "naked" was wrong - the invocations in main() call (actually rcall) to 0x0022 but the code there has no RET. I imagine you meant:

void HardwareInterface(unsigned char) __attribute__((always_inline));

in which case the result is:

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-gcc -mmcu=attiny13 -Os -save-temps -g avr.c -o avr.elf
avr.c:6:6: warning: always_inline function might not be inlinable [-Wattributes]
 void HardwareInterface(unsigned char DataForStuff)
      ^
avr.s: Assembler messages:
avr.s:65: Error: symbol `label' is already defined
avr.s:88: Error: symbol `label' is already defined

which is a shame :-(

 

Those errors being:

main:
.LFB1:
	.loc 1 21 0
	.cfi_startproc
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
.LVL1:
.LBB6:
.LBB7:
	.loc 1 8 0
/* #APP */
 ;  8 "avr.c" 1
	cli
 ;  0 "" 2
	.loc 1 9 0
 ;  9 "avr.c" 1
	     LDI R18, 0x00
label:
OUT 0x04, R18
OUT 0x0A, R18

 ;  0 "" 2
	.loc 1 17 0
 ;  17 "avr.c" 1
	sei
 ;  0 "" 2
.LVL2:
/* #NOAPP */
.LBE7:
.LBE6:
.LBB8:
.LBB9:
	.loc 1 8 0
/* #APP */
 ;  8 "avr.c" 1
	cli
 ;  0 "" 2
	.loc 1 9 0
 ;  9 "avr.c" 1
	     LDI R18, 0x00
label:
OUT 0x04, R18
OUT 0x0A, R18

 ;  0 "" 2
	.loc 1 17 0
 ;  17 "avr.c" 1
	sei
 ;  0 "" 2
.LVL3:
/* #NOAPP */
.LBE9:
.LBE8:
	.loc 1 24 0
	ldi r24,0
	ldi r25,0
	ret

 

Last Edited: Fri. Aug 10, 2018 - 03:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

WOW Clawson, top marks for effort here, thank you.

 

Yes you are right 'naked' means that that the 'return' will have no address to jump back too.

 

Maybe it doesn't even need to be 'always_inline'? I will play around with this now that you have shown me how to format the assembler and labels.

 

Thank you everyone else for your suggestions

 

Doing it this way I can use R18-R27, R30 and R31, without screwing up C. TBH I only need 2 registers and access to some global variables.

 

I would prefer this way of adding the mnemonic code as it is still part of the existing project structure, 'Doxygen' will pick up the tags, etc 

 

BTW I am currently working Essex, designing medical equipment. OK, OK, it's something that will eventually go up someone bottom! Still it makes a nice change from military contracts.

<º))))><

I am only one lab accident away from becoming a super villain.

Last Edited: Fri. Aug 10, 2018 - 05:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dren wrote:
I would prefer this way of adding the mnemonic code as it is still part of the project structure

As opposed to what? How would other approaches not be "part of the project structure"?

 

'Doxygen' will pick up the tags, etc 

Again, what would prevent that?

 

 it's something that will eventually go up someone bottom!

So, if you get fed up with this contract, you really can tell them where to stick it!

 

laugh

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You probably want to read the "inline assembly cookbook" for AVR's.

From what I know the text within the asm volatile(" ") is just copied to the asm output intermediate file of the compiler, and "\n" translates to a newline to make the assembler happy.

In the "inline assembly cookbook" parameter passing between C and asm routines is also explained.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

Dren wrote:

<SNIP>yes it really does need to be in assembler, honestly, let's not debate this<SNIP>

 

I am not wanting to debate this.  I am also a fan of ASM and often have a need to use it.

 

I do like to hear other peoples reasons for using it if you don't mind.

 

(My reasons are usually for the fun of making AVRs do thing people think should not be possible)

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

To follow up on #6 and #9, here is a beautified version of the Inline Assembler Cookbook: https://www.microchip.com/webdoc...

 

Going directly to the source is less intuitive, the text is more dry, but sometimes you have to:

https://gcc.gnu.org/onlinedocs/g...

https://sourceware.org/binutils/...

https://sourceware.org/binutils/...

 

 

Ok, for the inline code to work, you need to use local labels, or else the label is repeated and gives an error. Also, I informed in the "clobbers" section that r18 is changed, the compiler needs to know.

For illustration, I also used __zero_reg__, a register which is always zero, and you should change it back to zero if you use it.

edit: changed the code to show how to get an input from the function arguments. Any variable in scope can be used.

#include<avr/io.h>
#include <avr/interrupt.h>

void HardwareInterface(unsigned char) __attribute__((always_inline));

void HardwareInterface(unsigned char DataForStuff){
	cli();              // disable interrupts until all LEDs updated
	asm volatile (
		"	MOV R18, %0		\n"	// %0 is the first (and only in this case) argument
		"1:				\n"
		"	OUT 0x04, R18		\n"	// Useful comment

		// Blah blah blah lots of lovely assembler >>>>

		"	OUT 0x0A, __zero_reg__	\n"	// C keeps and expects __zero_reg__ (r1) to be zero
		:		                	// No outputs
		: "r" (DataForStuff)			// Input from C, "r" means it fits in a register
		: "r18"					// We are clobbering r18, and should inform the compiler
	);

	sei();            // Update complete > re-enable_interrupts
	return ;
}

int main () {
	HardwareInterface(0x55);
	HardwareInterface(0xAA);
}

 

The code generated for main() is:

00000080 <main>:
  80:   f8 94           cli
  82:   85 e5           ldi     r24, 0x55       ; 85
  84:   28 2f           mov     r18, r24
  86:   24 b9           out     0x04, r18       ; 4
  88:   1a b8           out     0x0a, r1        ; 10
  8a:   78 94           sei
  8c:   f8 94           cli
  8e:   8a ea           ldi     r24, 0xAA       ; 170
  90:   28 2f           mov     r18, r24
  92:   24 b9           out     0x04, r18       ; 4
  94:   1a b8           out     0x0a, r1        ; 10
  96:   78 94           sei
  98:   80 e0           ldi     r24, 0x00       ; 0
  9a:   90 e0           ldi     r25, 0x00       ; 0
  9c:   08 95           ret

 

Last Edited: Sun. Aug 12, 2018 - 11:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Awneil: As opposed to what? How would other approaches not be "part of the project structure"?

 

Well you could create a block of code (somewhere else), import the data and jump to the start of it. Perhaps a more accurate phrase would be "part of the project format."

 

'Doxygen' will pick up the tags, etc  > Again, what would prevent that?

 

I do not know if you have used Doxygen much? While it is excellent for a free program, sometimes its formatting is a bit bizarre.

 

So, if you get fed up with this contract, you really can tell them where to stick it!

 

Haha, that is part of the contract :)

 

Paulvhd: Thank you for the information, I will look that up.

 

andrewm1973: I am also a fan of ASM and often have a need to use it. I do like to hear other peoples reasons for using it if you don't mind.

 

I have noticed that as soon as you say you are writing in ASM these days, some people pop up and tell you how good compilers are, you are mad for using it etc. I need to control some WS2812Bs and a video sync circuit, to within a +/-150nS(ish) (about 2-3 clocks @16MHz). By writing in ASM I can ensure that all the timings are met, and that these do not change as the code is recompiled.

 

(My reasons are usually for the fun of making AVRs do thing people think should not be possible)

 

Excellent! I completely agree with this! Sometimes people argue with me and insist that something CANNOT be done. Sadly one time I did not win a contract because of this when the company refused to believe that what I was proposing was possible and assumed that I did not know what I was talking about. Oh well...

 

El Tangas: Wow! Thank you for all your work on this, that is really useful. it is always great to have an example.

 

Thank you everyone for all your effort on this. As a professional engineer naturally I have meetings most of the rest of the week! I'll post back and let you know the results.

 

All the best

 

Dren

 

 

 

 

 

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

Last Edited: Wed. Aug 15, 2018 - 01:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dren wrote:
I need to control some WS2812Bs
That and video generation seem to be the main, popular reasons for using Asm with AVR in fact. I guess you already researched this but there's quite a number of WS2182B libraries out there in AVR Asm. Even for the dreaded Arudino - but because the Asm basically has to operate "stand alone" it can easily be extricated.

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

Dren wrote:

Awneil: As opposed to what? How would other approaches not be "part of the project structure"?

 

Well you could create a block of code (somewhere else), import the data and jump to the start of it. Perhaps a more accurate phrase would be "part of the project format."

Eh?

 

You said:

I would prefer this way of adding the mnemonic code as it is still part of the project structure

I was asking why any other method would be any less "part of the project format" ?

 

And also why you feel that one method will work better than another as far as Doxygen is concerned.

 

 

To me, those assertions appear to be non-sequiturs.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Aug 15, 2018 - 11:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was asking why any other method would be any less "part of the project format" ?

 

'ANY' other method, well there are loads of other methods available. For example, I could get a book of Opcodes, a pencil and paper...

 

 

And also why you feel that one method will work better than another as far as Doxygen is concerned.

 

Why do I FEEL that? OFC some methods are going to be better than others for some things (and worse in other ways).

 

If I write it in the way El Tangas, Paulvdh or clawson suggest, and just add Doxygen tags, then I THINK that, given my past experience, it will work out the easiest for Doxygen to produce some consistent documentation. I am happy doing it this way

 

If you have a better way of mixing C and ASM, well let's not make it a big mystery, just tell me what you suggest. I have no ego here, if that sounds a better solution, I'll do it that way instead. Why make life difficult for yourself?

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

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

Dren wrote:
If you have a better way of mixing C and ASM, well let's not make it a big mystery, just tell me what you suggest

See #2 and #5.

 

EDIT

 

Also #13 - and example of assembler code being called from HLLs

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Aug 15, 2018 - 11:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess the issue with Doxygen and .S is covered by:

 

http://www.stack.nl/~dimitri/dox...

 

So if you used .S I think you'd need something that post-processed the .S into a form that the Doxygen scanner could understand. So if Doxygen is important I guess there is a fairly strong argument for putting the Asm into .c/.cpp files?

 

(in our organisation we mandate that the majority of the Doxygen goes into .h not .c/.cpp - that would work for .S too - if the functions that are implemented in .S have their public interface exposed in .h then you would put the Doxygen there and it would be found and processed OK without needing to worry about the actual .S implementation).

Last Edited: Wed. Aug 15, 2018 - 12:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I think you'd need something that post-processed the .S into a form that the Doxygen scanner could understand.

I had been under the impression that Doxygen was language-agnostic.

 

sad

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Aug 15, 2018 - 01:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil:

 

Thank you for your suggestions. I do appreciate the time you have taken to reply, but I do not think that they are the right way to go in this project.

 

clawson:

 

Thanks, it is a good idea so see what other people have already written on here. Why reinvent the sliced bread, or something like that?

 

We have Doxygen tags in BOTH .h and .c files :'(

 

While it may not all be that useful it does generate a LOT of documentation that clients can be swamped with!

 

Never mind the quality, just look at the quantity.

 

 

 

 

 

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

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

Given #18, if Doxygen is the key concern, then I now see what you mean about that!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, it was all going so well.... until...

#1

void HardwareInterface(unsigned char) __attribute__((always_inline));

 

Gets rejected "inlining failed in call to always_inline 'HardwareInterface': function body not available"

 

Also:

#2

asm volatile (" in     r22, SREG     \n" // Save Status register
 

Creates an error "undefined reference to `SREG'

 

SREG is definitely already defined, ideas?

 

AND just for an encore...

#3

I have some example code that reads from a buffer

; r26:27 (X) = data pointer

movw   r26, r24      ;r26:27 = X = p_buf

ld     r18,X+        ;get first data byte

Questions... 'X' isn't defined, is it just an inherently part of the compiler, if so how do I find this information?

'X+' ? 'X' is a 16 bit pointer so is this increment a 16 bit +1 or just 8 bits? If so how does this work?

 

Any ideas + advice greatly appreciated

 

All the best

 

Dren

<º))))><

I am only one lab accident away from becoming a super villain.

Last Edited: Thu. Aug 16, 2018 - 11:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dren wrote:
Gets rejected "inlining failed in call to always_inline 'HardwareInterface': function body not available"

You need a declaration AND a definiition.

SREG is definitely already defined, ideas?

You are misunderstanding what asm()  does it literally just says "take all this following text and paste it into the .s file before you assemble it". By the time you have reached .s all preprocessing is over and a macro like SREG will not be expanded. Instead the assembler expects SREG to be a symbol location.

Last Edited: Thu. Aug 16, 2018 - 11:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
You need a declaration AND a definiition.

as shown in #11

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow that was quick!

 

I thought that the attributes were already defined Studio, ah well, that would be too easy I guess.

 

I do not know why it has worked out like this but I usually write in assembler for PICs and this is the first time I have written assembler for an Atmel.

<º))))><

I am only one lab accident away from becoming a super villain.

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

Dren wrote:
I thought that the attributes were already defined Studio, ah well, that would be too easy I guess.
What are you talking about? The GCC compiler supports a number of function and data attributes:

 

https://gcc.gnu.org/onlinedocs/g...

https://gcc.gnu.org/onlinedocs/g...

 

This is nothing to do with "Studio" (the Atmel/Mircochip) bit as such, this is part of the GCC compiler which comes form a completely different source.

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

clawson wrote:
You are misunderstanding what asm() does it literally just says "take all this following text and paste it into the .s file before you assemble it". By the time you have reached .s all preprocessing is over and a macro like SREG will not be expanded. Instead the assembler expects SREG to be a symbol location.

 

And because of that you have to somehow define the macros inside the inline assembly. I'm not sure if this works?

 

        asm volatile (
                "#include <xxx.h>               \n" // include whatever header defines SREG e.g. <avr/io.h>
                " in     r22, SREG              \n" // Save Status register
                ...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
asm volatile (" in     r22, __SREG__     \n" // Save Status register

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

This is why I suggest writing an actual assembler source module - rather than faffing with all these arcane details of inline assembler ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The usual idea is that you pass things like PORTB, TCNT1, etc in as parameters to the inline asm.

 

It's because of this kind of complication that personally I think a callable function in a .S file is 100 times easier. The only downside is the (R)CALL/RET overhead.

 

If you are going to persevere with inline Asm I think you really need to read:

 

https://www.nongnu.org/avr-libc/...

 

Even the first example on that page shows "PORTD" being passed in so it's accessible by the code

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

clawson wrote:
It's because of this kind of complication that personally I think a callable function in a .S file is 100 times easier.

Likewise.

 

The only downside is the (R)CALL/RET overhead.

so make the C/assembler partitioning at a suitable point that this is not a problem ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson, thank you for your super fast 'customer support'.

 

#1 I thought that I had declared the attribute and that a Studio project would have automatically set up every definition I could possibly want to do using GCC. I am such an optimist? Anyway it sounds like I've screwed up! TBH I have not done much with 'attributes'. In the past I tended to use 'pragmas' as they seems to work OK on different compilers, not that this is an issue this time. It looks like I have a bit of post lunch relaxing reading to do then :)  

 

#2 I didn't realise that 'SREG' was a macro I thought it was just the Status register (0x5f) possibly I am still thinking of PICs. I've just realised that it has been ~11 years since I've done any assembler programming. Such is the rise of high level languages and how fast time rushes by! Hey I am one of the lucky ones, I still manage to do 'some' real engineering in between meetings, paperwork, managing, budgets and planning.

 

All the best

 

Dren

 

 

 

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

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

Dren wrote:
a Studio project would have automatically set up every definition

How could it possibly do that?

 

The definition is the code of your function - how could an IDE possibly know what code you were going to write within your function?!

 

#2 I didn't realise that 'SREG' was a macro I thought it was just the Status register (0x5f)

That's right: as far as the code goes, "the status register" is just an address - 0x5F.

 

The macro - "SREG" - just give a human-meaningful name for that address.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clawson:

I think that we are talking about different things. I took an attribute to be defined as something like 'naked' 'inline' 'weak' etc So If I chuck an attribute into my code I expect GCC to know what to do. You are talking about the actual definition of the function itself. So no real problem :) back to the real problems...

 

With SREG I expected to be able to just drop that into the ASM and have it replaced by register 0x5f. Which JOEYMORIN has cracked, I just needed to type ' __SREG__ ' instead and everything in the world is suddenly sunnier :D Cheers!

 

You are misunderstanding what asm() does it literally just says "take all this following text and paste it into the .s file before you assemble it".

 

No that was exactly what I thought it would do. I initially hoped that I could just type

 asm volatile

       ("     

              // 'bog' standard assembler >>>

 

      ");

And the whole block just it gets dumped in. Ah the joy of being naïve?

 

I am really not too happy about this 4 colon GCC 'assembler' code... If that is the only way to make it work using the current method, then I think I am going to do this another way after all... Oh I am sure that will make awneil smile now :) 

 

Thanks so much everyone for all your help... I'll have to get back to this tomorrow/next week... I've just been called off to.... a meeting!

 

 

 

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

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

Dren wrote:
Oh I am sure that will make awneil smile now

OK, then:  laugh

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dren wrote:
#1 I thought that I had declared the attribute and that a Studio project would have automatically set up every definition I could possibly want to do using GCC.
Not sure I understand that point. If I have code:

int foo(int n) {
    return n + 1;
}

int bar(int n) {
    return n - 1;
}

and I later decide that I use foo so much that I don't want to pay the CALL/RET overhead each time it is used then I could simply:

int foo(int n) __attribute__((always_inline));
int foo(int n) {
    return n + 1;
}

int bar(int n) {
    return n - 1;
}

So that applies the attribute to that function so that when it is used it will be inlined. For completeness I probably really want:

static inline int foo(int n) __attribute__((always_inline));
static inline int foo(int n) {
    return n + 1;
}

int bar(int n) __attribute((noinline));
int bar(int n) {
    return n - 1;
}

Now I should find:

00000070 <main>:

int main(void) {
    while(1) {
        PORTB = foo(PORTB);
  70:   88 b3           in      r24, 0x18       ; 24
  72:   90 e0           ldi     r25, 0x00       ; 0
  74:   01 96           adiw    r24, 0x01       ; 1
  76:   88 bb           out     0x18, r24       ; 24
        PORTD = bar(PORTD);
  78:   82 b3           in      r24, 0x12       ; 18
  7a:   90 e0           ldi     r25, 0x00       ; 0
  7c:   0e 94 36 00     call    0x6c    ; 0x6c <bar>
  80:   82 bb           out     0x12, r24       ; 18

Where the code of foo() was inlined at the point of invocation but the code of bar() was not (I used "noinline" for that one which is effectively the opposite of "always_inline").

 

Personally I prefer the shortened syntax that combines the application of attributes into the definition:

__attribute__((always_inline)) static inline int foo(int n)  {
    return n + 1;
}

__attribute((noinline)) int bar(int n)  {
    return n - 1;
}

(and, yes folks, I know "int" was not efficient or appropriate but it's very easy to type!)

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

Dren wrote:
No that was exactly what I thought it would do. I initially hoped that I could just type
SREG is an exception (also __zero_reg__ and __tmp_reg__) but what you can't do in asm() is things like:

asm("out PORTD, R24");

When you do that this happens:

 

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type avr.c
#include <avr/io.h>

int main(void) {
    while(1) {
        asm("\tout PORTD, r24\n");
    }
}

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-gcc -c -save-temps -mmcu=atmega16 -Os avr.c -o avr.o

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type avr.s
        .file   "avr.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
        .section        .text.startup,"ax",@progbits
.global main
        .type   main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
.L2:
/* #APP */
 ;  5 "avr.c" 1
                out PORTD, r24

 ;  0 "" 2
/* #NOAPP */
        rjmp .L2
        .size   main, .-main
        .ident  "GCC: (AVR_8_bit_GNU_Toolchain_3.6.1_1752) 5.4.0"

This is the very source that will be passed to avr-as. When I let that happen this happens:

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-gcc -save-temps -mmcu=atmega16 -Os avr.c -o avr.elf
avr.o: In function `main':
avr.c:(.text.startup+0x0): undefined reference to `PORTD'
collect2.exe: error: ld returned 1 exit status

That's because "PORTD" has actually been entered into a file that will NOT be pre-processed. So there's no chance of that macro being expanded out (and even if it were it's defined as a C style dereference of a volatile uint8_t pointer which won't mean anything to the assembler either!). So you have to use:

asm("out %0, R24"::  "I" (_SFR_IO_ADDR(PORTD)) : "R24");

That then gives:

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type avr.c
#include <avr/io.h>

int main(void) {
    while(1) {
        asm("\tout %0, R24\n"::  "I" (_SFR_IO_ADDR(PORTD)) : "r24");
    }
}

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-gcc -save-temps -mmcu=atmega16 -Os avr.c -o avr.elf

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type avr.s
        .file   "avr.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
        .section        .text.startup,"ax",@progbits
.global main
        .type   main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
.L2:
/* #APP */
 ;  5 "avr.c" 1
        out 18, R24
 ;  0 "" 2
/* #NOAPP */
        rjmp .L2
        .size   main, .-main
        .ident  "GCC: (AVR_8_bit_GNU_Toolchain_3.6.1_1752) 5.4.0"

So all of that simply to get an "out 18, r24" built into the code!!

 

This is why I despise these mystic runes of inline asm and personally I would do:

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type asm.S
#define __SFR_OFFSET 0
#include <avr/io.h>

    .global foo

foo:
    out PORTB, r24
    ret
D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type avr.c
#include <avr/io.h>

void foo(void);

int main(void) {
    while(1) {
        foo();
    }
}

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-gcc -mmcu=atmega16 -Os avr.c asm.S -o avr.elf

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-objdump -S avr.elf

avr.elf:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 2a 00     jmp     0x54    ; 0x54 <__ctors_end>
   4:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
   8:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
   c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  10:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  14:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  18:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  1c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  20:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  24:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  28:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  2c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  30:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  34:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  38:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  3c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  40:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  44:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  48:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  4c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  50:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>

00000054 <__ctors_end>:
  54:   11 24           eor     r1, r1
  56:   1f be           out     0x3f, r1        ; 63
  58:   cf e5           ldi     r28, 0x5F       ; 95
  5a:   d4 e0           ldi     r29, 0x04       ; 4
  5c:   de bf           out     0x3e, r29       ; 62
  5e:   cd bf           out     0x3d, r28       ; 61
  60:   0e 94 38 00     call    0x70    ; 0x70 <main>
  64:   0c 94 3b 00     jmp     0x76    ; 0x76 <_exit>

00000068 <__bad_interrupt>:
  68:   0c 94 00 00     jmp     0       ; 0x0 <__vectors>

0000006c <foo>:
  6c:   88 bb           out     0x18, r24       ; 24
  6e:   08 95           ret

00000070 <main>:
  70:   0e 94 36 00     call    0x6c    ; 0x6c <foo>
  74:   fd cf           rjmp    .-6             ; 0x70 <main>

00000076 <_exit>:
  76:   f8 94           cli

00000078 <__stop_program>:
  78:   ff cf           rjmp    .-2             ; 0x78 <__stop_program>

But, like I say, for this you pay the price of a CALL (if I'd used -mrelax that would have been RCALL).

 

But in .S you get to write Asm that actually looks like Asm.

Last Edited: Thu. Aug 16, 2018 - 02:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
But in .S you get to write Asm that actually looks like Asm.

Indeed.

 

Plus, by having it a .S, it is clearly "something special".

 

If you ever need to port the application, you know immediately that this is something that is just going to have to be replaced - whereas, if it's buried in a 'C' file, that may not be so obvious.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I screwed up my runes in #36. The PORTD was supposed to be in the output list not the input list apparently. I did wonder what I got "18" and not "0x18" !!

 

Even now I'm not sure what the convoluted syntax was supposed to be - life (well my life) is too short to bother trying to learn GCCs inline asm syntax!

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

awneil wrote:

This is why I suggest writing an actual assembler source module - rather than faffing with all these arcane details of inline assembler ...

I'm certainly in agreement with this.  And since he's working with WS2812B LEDs, I offer my last post again, where he will find a working example of such code.

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

clawson, given that YOU were confused about the inline syntax #36, what chance does a newcomer have of getting it right?!?!

 

Plus, by having it a .S, it is clearly "something special".

I always wondered what the '.s' stood for :)

 

kk6gm, thank you for the code example I didn't mean to ignore it, BUT I am not at that stage yet, I am way back on square one trying to get an I/O pin waggling. I am sure it will be useful later on, (the MPU runs at 16MHz so I need to sprinkle it with 'nops').

 

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

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

Dren wrote:

kk6gm, thank you for the code example I didn't mean to ignore it, BUT I am not at that stage yet, I am way back on square one trying to get an I/O pin waggling. I am sure it will be useful later on, (the MPU runs at 16MHz so I need to sprinkle it with 'nops').

Understood.  Running at 16 MHz would offer opportunities to clean up the code nicely, as there would be enough clock cycles to remove some different paths through the code that were required at 8 MHz.  Maybe I'll poke around with that.

 

BTW, are you aware that there are multiple WS2812B timing specs?  The older chips ran slower than the newer ones.  It's kind of nuts that they kept the same part number, really.

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

Dren wrote:
I always wondered what the '.s' stood for

Ha ha - hadn't spotted that one!

 

yes

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm: I was NOT aware that the timing had changed, thanks for the heads up. You are right that IS nuts!

 

Although having the data sent as GREEN RED blue is also a bit 'special'

 

talking of which... Yes the .S is for 'something special' it's a bit having 'GTi' after your car name, 'cos it's just better! 

<º))))><

I am only one lab accident away from becoming a super villain.

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

I hope everyone had a great weekend... back to it>

 

I am using AVR studio so why couldn't I just use :

 

asm volatile (" LDI R18, 0x00");

asm volatile (" LDI R18, 0x00");

asm volatile (" LDI R18, 0x00");

 

Instead of the 'mystical' 4 ':' GCC inline assembler codes?

 

Well I am going to try it (after the obligatory meetings this morning) and I'll let you know what happens later (with the compiler not in the meetings OFC)

 

All the best

<º))))><

I am only one lab accident away from becoming a super villain.

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

You still haven't read the inline assembler cook book have you? As a minimum you need
.
asm volatile (" LDI R18, 0x00" :: "R18" );
.
As the compiler does not parse what's within asm("....") all it does is paste that text into the .s file. So it can't "see" that this code uses R18. So supposing in nearby code it was already preloading R18 with some value/result before asm() which it later on uses after the asm(). It cannot know that the stuff in asm code "clobbers" R18 so you have to add R18 to the clobber list to say "don't rely on R18 after this, either avoid using it or save/restore it if register pressure is high".
.
Believe me, doing this in separate .S, as long as it conforms to the ABI, is 100 times easier!

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

>You still haven't read the inline assembler cook book have you?

 

Does it show? I gave it a quick browse in between other things. I know, I know, I really need to sit down and look at this problem undisturbed for a few hours, ideally while listening to some 'Gary Numan'! 

 

I believe you are right that it is easier making it a separate '.S' file and I may have to go that route. Not that I've ever mixed ASM and C in an AVR studio project before, so that might spawn a whole host of other issues.

 

I have the luxury of some 'spare' time after lunch until 3pm, so I will give it a try then, thanks for your help I do appreciate it.

 

#My name is no one, no one is calling, My name is ruin, my name is heartbreak My name is loving, but sorrows and darkness, My name is ruin, my name is evil#

<º))))><

I am only one lab accident away from becoming a super villain.

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

The whole point of using inline assembly is to integrate better with the compiler, leaving it as many choice as possible to help optimization. For example:

int main () {
    uint8_t myvar = 0xF0;
    asm volatile (
    	"	SWAP %0					\n"
		: "+r" (myvar)					// Output (leading "+" means R/W)
  	);
  	return myvar;
}

 

This executes the swap assembly instruction, which has no direct equivalent in C. However, using a variable means the compiler gets to choose which register it wants to use as operand for swap.

In this case, the output is:

00000080 <main>:
  80:   80 ef           ldi     r24, 0xF0       ; 240
  82:   82 95           swap    r24
  84:   90 e0           ldi     r25, 0x00       ; 0
  86:   08 95           ret

So the compiler wisely chose r24, since the return value will be in r24:r25.

 

If you are just writing plain assembly where you don't leave any choices for the compiler, it's much simpler to use .s or .S files.

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

El Tangas: The whole point of using inline assembly is to integrate better with the compiler, leaving it as many choice as possible to help optimization.

 

Yes it would be nicer to do it that way and it also makes the documentation way easier for me. BUT I do not know GCC inline ASM so I'd need to get up to speed on it ASAP.

 

I'm sure that both 'clawson' and 'awneil' know more about this issue than I do, so I am trusting their advice and following their recommendations.

 

I will turn off the 'phone, put on the headphones and have a look into this after lunch.

 

Cheers Dren

 

 

<º))))><

I am only one lab accident away from becoming a super villain.

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

Dren wrote:

Not that I've ever mixed ASM and C in an AVR studio project before, so that might spawn a whole host of other issues.

Ah but the ABI is both documented and more importantly easy to read!!

 

https://gcc.gnu.org/wiki/avr-gcc

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

So many distractions... At last I am back on this project! No idea how long that will last, but until then....

 

clawson: I went the link that you provided, sadly I didn't find it addressed any of my questions. I am using Studio not a command line assembler. Do I really have to dig into the toolchain (wherever that is lurking) to mess around with the set up? This is not an unreasonable thing to expect the compiler to handle, or maybe I've just been spoilt with better tools in other places? More likely they have just been set up for me by previous engineers, ah luxury :D

 

I have added a Blahblah.S file containing assembler into the project, but it spawns a host of errors.... OK that is as far as I've reached in the '1/2 a CD' I've had focused on this problem. I knew that this was not going to be an easy option :P

 

If you have an example that you be really useful, otherwise I'll just get on with it and the rest of Numan's finest :)

 

Cheers

<º))))><

I am only one lab accident away from becoming a super villain.

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

Great mobile got NETWORK_INTERRUPTED and long post was lost. The basic point I was making was that I haven't a clue what you are talking about.

Pages