Cortex M0 inline assembly help

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

I'm working on an NMI handler for the SamD20 part and it's really time critical to complete the tasks I need to in that routine.  The assembly listing from the GCC tools looks pretty good, but I need to make it more compact.

 

I'm simply needing to get the states of (2) GPIO pins in my routine, both pins are defined as inputs and they are both on portA.  the clock is on PA19 and the data on PA21.

 

In "C" code I can access to the individual pin using

#define MDCVAL ((((Port *)PORT)->Group[0].IN.reg)&(0x01U << GPIO_PIN(MDC)))

#define PORTA   PORT->Group[0].IN.reg

 

In my NMI handler, I've tried accessing the pin in assembly and nothing seems to work. 

 

In my asm routing I put in the address of the PORTA, but I can't seem to put in the PORTA but I've seen lots of examples where that can be done.  In fact most of the examples I've seen, don't seem to work.

asm(

      "ldr  r2,=0x41004420\n\t"

  );

 

Ideally what I'd like to do in assembly is a set of instructions that does this;

while(!((((Port *)PORT)->Group[0].IN.reg)&(0x01U << GPIO_PIN(MDC))));

 

I'm thinking the steps I need to do this are to;

1. Get the 32bit value of the PORT->Group[0].IN.reg and store it one of the "r" registers

2. Use one of the "r" registers to store 1<<19 or 1<<22 depending on the pin that needs to be tested

3. Do a bit test and repeat or branch depending on the state

 

I'm hoping someone has done something like this and can assist with what I'm trying to do. 

 

Last Edited: Mon. Dec 11, 2017 - 07:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Write what you want in C. Compile with -save-temps. Study the .s file. See if you can come up with something better than the compiler.

 

As you posted in an AVR forum I'll move this (though the advice would be the same for both). 

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

asm(

      "ldr  r2,=0x41004420\n\t"

  );

So, that should put the address of PORTA  into R2.

To get the actual data from PORTA, you need an additional  "ldr r0, [r2]" or similar.  See, perhaps, https://github.com/WestfW/Minima... (which I believe uses CM3 instructions not present on CM0.  Alas.)

Consider using the (poorly documented) IOBUS at address 0x60004420 instead of 0x41...; it'll shave a couple of cycles off.

 

The ARM lacks any particularly clever instructions for doing IO Space reads or bit tests; I doubt whether you'll be able to do better than the compiler.

 

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

I found something interesting that I hadn't seen before , the "__attribute__((naked))"  attribute which is really helpful for streamlining assembly commands.  Using this actually shaved off a few commands and it's giving me more ideas on how to approach this. 

 

I also found some websites that explained that inline assembler instruction set is limited, and I'm trying to find a resource for which commands are still available.   

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

You cant load an immediate 32bit value into a register on the m0. You store the value you want as a constant then load the reg indirectly via the pc with offset. The compiler does it this way.

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

Thanks for response, I'm learning more about M0 assembly instructions as I go.  I'm finding very little documentation on the inline assembly instructions examples.

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

The ARM doc on the asm instructions takes a little getting used to. With the differences between M0,M3 and so on, you need to look carefully. The term I forgot the other day was 'literal pool' - this is what is required for the M0. Your literals (ie constants) get stored in a block within the code and accessed via pc relative access. With your C example, I would expect the compiler to generate near optimal code. Show us the asm the compiler generates

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

'literal pool' - this is what is required for the M0.

I don't think that any of the ARM chips support a 32bit "immediate" load into a register.   The M3 and higher have 16bit values, and some interesting options for shifting and permuting  an 8bit constant into a useful 32 result, but those are "32bit Thumb2 instructions" not present on the M0.

 

The relevant document for detailed info on the instructions is http://infocenter.arm.com/help/i... ("The ARMv6-M Architecture Reference Manual.)  (This covers the instruction set.  There are additional complexities to using the (complex) gcc syntax for inline assembly arguments..)