Cortex M0+ Assembly Language using GNU

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

Hi,
    I'm currently converting AMR-WB onto a SAMD21G18A development board and have come up against a problem I have not been able to solve. I have a .H file that includes all of the hardware equates but it doesn't always work.

I define in the normal assembly language format:

<name of address or mask> = <value>
 

SYSCTRL = $40000800

SC_OSC8M_PRESC_MASK = $FFFFFFFC

SC_OSC8M = 32

But when I use the equates...
 

ldr r2,SYSCTRL

ldr r3,[r2,SC_OSC8M]

ldr r1,SC_OSC8M_PRESC_MASK

ands r3,r1

str r3,[r2,SC_OSC8M]

The use of SC_OSC8M_PRESC_MASK results in an 'invalid offset, value too big 0xFFFFFFFC' but the rest work! Adding a = before the label doesn't work and using #define doesn't work. Is this a ME error or some GNU error?

Many thanks for your time.

 

-Not all men (and especially the wisest) share the opinion that it is bad for women to be educated. But it is very true that many foolish men have claimed this because it displeased them that women knew more than they did.-

Last Edited: Wed. Mar 28, 2018 - 02:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Cortex m0/+ has no 32 bit immediate. You have to use what is called a ‘literal pool’ where you store the address using a dc.w (or whatever the gcc syntax is) nearby to your function and then load it into a register via pc relative addressing. Examine the compiler generated code to see how it does it. Then again, the compiler will most likely generate optimal code anyways, so no need for asm.

Last Edited: Thu. Mar 29, 2018 - 04:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The gnu assembler syntax for using LDR on a literal pool constant is

 

ldr r1, =REG_PORT_DIRSET // address of port

 

 

You might want to look at https://github.com/WestfW/Minima... and nearby pages.

 

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

I found this thread via web search because I had the same problem.

 

To actually answer it, for the next poor sap who stumbles onto it:

 

* the syntax is "LDR REG, =SOMETHING

 

If that SOMETHING is >16 bits, the assembler remembers the constant and replaces the whole statement with a PC-relative load to something that's less than 0x400 bytes off.

You then say

 

.ltoff

 

someplace convenient (e.g. right behind a "bx lr" or "pop {pc}") to direct the assembler to place these constants *here*.