Set pointer to array address with inline ASM in naked ISR

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

I want to execute the following instructions (from avr-objdump) with inline ASM in an ISR:

    tx_at = tx_buf;
 14a:   8a e0           ldi     r24, 0x0A       ; 10
 14c:   93 e0           ldi     r25, 0x03       ; 3
 14e:   90 93 03 01     sts     0x0103, r25     ; 0x800103 <tx_at+0x1>
 152:   80 93 02 01     sts     0x0102, r24     ; 0x800102 <tx_at>

where the variables are declared as:

volatile static uint8_t *tx_at;
volatile uint8_t tx_buf[514];

However I can't find the right constraints for the ASM input parameters in order to somehow arrive at the 0x0A and 0x03 values. I already figured that they must be the memory address of the array, but I have no clue how to get that address into the ASM code. So how can I do that?

This topic has a solution.
Last Edited: Mon. Dec 2, 2019 - 11:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why with inline assembler?

 

Why not just do the ISR in assembler?

 

EDIT

 

Or, in fact, why not just do it in 'C' - as you're only copying the compiler's output anyhow?!

 

EDIT 2

 

sEE: https://www.avrfreaks.net/commen...

 

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: Mon. Dec 2, 2019 - 06:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, no inline asm now. Moved my code that I have so far to a separate .S file and "imported" the variables I need with ".extern ..." works fine so far. C is not an option, because I do some timing related changes to the C compilers output but leave the rest as is. However I don't know where to get that 0x0A and 0x03 from now.

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

aquaatic wrote:
I don't know where to get that 0x0A and 0x03 from now.

What do you mean by that?

 

They're just immediate constants, surely?

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

No, they represent in some way the address of the array "tx_buf" (high and low bytes I guess) and that address is stored into tx_at (see the C line before the ASM statement).

Last Edited: Mon. Dec 2, 2019 - 08:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't shown enough context but, presumably, the compiler knows that at compile time - so it can just insert it as a literal constant.

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...
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

aquaatic wrote:

Okay, no inline asm now. (...)  However I don't know where to get that 0x0A and 0x03 from now.

 

Read this, it will probably help: https://sourceware.org/binutils/...

 

edit: more explicitly, you can do this to get the address of tx_buf into the registers:

	ldi	r24, lo8(tx_buf)
	ldi	r25, hi8(tx_buf)

 

Last Edited: Mon. Dec 2, 2019 - 10:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

aquaatic wrote:
Moved my code that I have so far to a separate .S file and "imported" the variables I need with ".extern ..."

So now you need to look at how the 'C' compiler accesses an extern varaible.

 

It looks like the variable was local in your original - hence the compiler "knew" its address as a compile-time constant ?

 

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

El Tangas wrote:
edit: more explicitly, you can do this to get the address of tx_buf into the registers:

Thank you, that was it.

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

I am assuming that OP is using assembly for efficiency.

Any register used in the ISR will need to be pushed and popped.

The address to be stored need not be in registers all at once.

If all the ISR needs to to do is store an address,

PUSH, LDI, STS, LDI, STS, POP should be sufficient.

 

A problem with a separate assembly file is that it

requires formerly static variables to be external.

To do it with inline assembly, I think it needs the "i" constraint:

"i"(tx_buf) and possibly "i"(&tx_at) .

"i" is not specific to AVRs and is not in the AVR inline assembly cookbook.

 

From OP's listing, the compiler seems to have preserved the name tx_at, but not tx_buf.

In that case, "i"(&tx_at) is not necessary.

tx_at and tx_at+1 can be STS targets.

If the name tx_buf is also preserved,

lo8(tx_buf) and hi8(tx_buf) can be LDI operands.

No constraints are necessary.

 

If OP already has a working .S file,

changing to inline assembly might not be worth the effort.

In the .c file, a comment to the effect that tx_buf and tx_at

are only shared with the .S file would be useful.

Let the reader know that they are pseudo-static.

Iluvatar is the better part of Valar.