Arduino Due blink example in assembly

Good evening everyone I'm trying to understand the arm processor by using the Arduino Due and it could be a real help if someone could give me the blink example in assembly for the Arduino Due.I've searched the web but there isn't much on the subject.Thank you.

blackcoursar:
Good evening everyone I'm trying to understand the arm processor by using the Arduino Due and it could be a real help if someone could give me the blink example in assembly for the Arduino Due.I've searched the web but there isn't much on the subject.Thank you.

Sadly the arduino ide doesn't support .s files. But you can use inline assembly.

I've searched the web but there isn't much on the subject.

I'm not surprised, no-one in their right mind would use assembly these days unless there is a VERY good reason.

To start from scratch with no C would be a nightmare, but to use inline ASM in your C sketch would be ok so search for examples of inline assembly, get the SAM instruction set docs and start experimenting using some other code as a base.

Good luck, is there a particular reason you want to know the ARM at this level? Very few people need that knowledge.


Rob

Graynomad:

I've searched the web but there isn't much on the subject.

I'm not surprised, no-one in their right mind would use assembly these days unless there is a VERY good reason.

To start from scratch with no C would be a nightmare, but to use inline ASM in your C sketch would be ok so search for examples of inline assembly, get the SAM instruction set docs and start experimenting using some other code as a base.

Good luck, is there a particular reason you want to know the ARM at this level? Very few people need that knowledge.


Rob

ARM is not very complex. But it would be much easier if you could use real .s files instead of inline assembly.

it would be much easier if you could use real .s files instead of inline assembly.

Reckon, inline ASM is a nightmare.


Rob

Graynomad:

I've searched the web but there isn't much on the subject.

I'm not surprised, no-one in their right mind would use assembly these days unless there is a VERY good reason.

To start from scratch with no C would be a nightmare, but to use inline ASM in your C sketch would be ok so search for examples of inline assembly, get the SAM instruction set docs and start experimenting using some other code as a base.

Good luck, is there a particular reason you want to know the ARM at this level? Very few people need that knowledge.


Rob

Yes , sadly i need it for a project in the university, i understand that it's a difficult subject because the arduino's purpose is exactly that, to not get involved with assembly but at the time I really need some help with the subject.
Thank you for the response.

Graynomad:
ARM is not very complex. But it would be much easier if you could use real .s files instead of inline assembly.

Yes, I know, I already have a basic assembly knowledge and it would be great if I could upload the code directly to arduino due with the various addresses and registers but there isn't much of a documentation out there.
Thanks for the response.

I've found this example but as i found out it's for arduino uno I've managed to find the addresses for the Due but it still doesn't work. Any help would be much appreciated .

void setup() {
  asm volatile (
    "sbi %0, %1 \n\t"           //pinMode(13, OUTPUT);
    :: "I" (_SFR_IO_ADDR(DDRB)), "I" (DDB5)
  );
}
 
void loop() {
  asm volatile (
     "sbi %0, %1 \n\t"          //LED on
     "call OneSecondDelay \n\t" //delay
     "cbi %0, %1 \n\t"          //LED off
     "call OneSecondDelay \n\t" //delay
     "rjmp 4f \n\t"             //exit
 
  "OneSecondDelay: \n\t"
     "ldi r18, 0 \n\t"          //delay 1 second
     "ldi r20, 0 \n\t"
     "ldi r21, 0 \n\t"
 
  "1: ldi r24, lo8(400) \n\t"
     "ldi r25, hi8(400) \n\t"
  "2: sbiw r24, 1 \n\t"         //10x around this loop = 1ms
     "brne 2b \n\t"
     "inc r18 \n\t"
     "cpi r18, 10 \n\t"
     "brne 1b \n\t"
 
     "subi r20, 0xff \n\t"      //1000 x 1ms = 1 second
     "sbci r21, 0xff \n\t"
     "ldi r24, hi8(1000) \n\t"
     "cpi r20, lo8(1000) \n\t"
     "cpc r21, r24 \n\t"
     "breq 3f \n\t"
 
     "ldi r18, 0 \n\t"
     "rjmp 1b \n\t"
 
  "3: \n\t"
     "ret \n\t"
 
  "4: \n\t"                     //exit
 
     :: "I" (_SFR_IO_ADDR(PORTB)), "I" (PORTB5)
     : "r18", "r20", "r21", "r24", "r25"
  );
}

Graynomad:

I've searched the web but there isn't much on the subject.

I'm not surprised, no-one in their right mind would use assembly these days unless there is a VERY good reason.

I think you misunderstand the difference between a general purpose computer and
a microcontroller, the latter has to deal with hard timing constraints and often you
need to know cycle counts and take the processor to its limit without jumping
through hoops to get persuade a compiler to do just what you want.

Certainly assembly is much less productive in programmer time, but sometimes you
need that real-time performance. So yes embedded programming can involve snippets
of assembly language without any departure from sanity being involved.

All engineering decisions are a trade off.

blackcoursar:
I've found this example but as i found out it's for arduino uno I've managed to find the addresses for the Due but it still doesn't work. Any help would be much appreciated .

void setup() {

asm volatile (
    "sbi %0, %1 \n\t"           //pinMode(13, OUTPUT);
    :: "I" (_SFR_IO_ADDR(DDRB)), "I" (DDB5)
  );
}

void loop() {
  asm volatile (
     "sbi %0, %1 \n\t"          //LED on
     "call OneSecondDelay \n\t" //delay
     "cbi %0, %1 \n\t"          //LED off
     "call OneSecondDelay \n\t" //delay
     "rjmp 4f \n\t"             //exit

"OneSecondDelay: \n\t"
     "ldi r18, 0 \n\t"          //delay 1 second
     "ldi r20, 0 \n\t"
     "ldi r21, 0 \n\t"

"1: ldi r24, lo8(400) \n\t"
     "ldi r25, hi8(400) \n\t"
  "2: sbiw r24, 1 \n\t"         //10x around this loop = 1ms
     "brne 2b \n\t"
     "inc r18 \n\t"
     "cpi r18, 10 \n\t"
     "brne 1b \n\t"

"subi r20, 0xff \n\t"      //1000 x 1ms = 1 second
     "sbci r21, 0xff \n\t"
     "ldi r24, hi8(1000) \n\t"
     "cpi r20, lo8(1000) \n\t"
     "cpc r21, r24 \n\t"
     "breq 3f \n\t"

"ldi r18, 0 \n\t"
     "rjmp 1b \n\t"

"3: \n\t"
     "ret \n\t"

"4: \n\t"                     //exit

:: "I" (_SFR_IO_ADDR(PORTB)), "I" (PORTB5)
     : "r18", "r20", "r21", "r24", "r25"
  );
}

This is avr assembly. You need arm assembly. As for the registers, yes, it's irritating that it lacks a lot of documentation.

When I first got into LPC processors I tried some assembly just for the heck of it. Quite simple and with the LPCXpresso IDE you can use .S files.

If you just want to learn the ARM then that might be a better option, after all the chip vendor just adds peripherals and that have almost nothing to do with the ARM core.


Rob

I found this in another part of the forum, the only thing that isn't really clear is the masking process do I really need to do that
or using an inline assembly code would be the same?

/*
    Raw blink sketch for DUE revealing SAM3X8E registers used
    Turns on an LED on for one second, then off for one second, repeatedly.
 */

// Pin 13 mask
uint32_t led = (1u << 27); 

void setup()
{                  
  // Output Enable Register
  REG_PIOB_OER = led; 
}

// the loop routine runs over and over again forever: 
void loop()
{
    REG_PIOB_SODR = led; // Set Output Data Register, turns LED on 
    delay(1000);         // wait for a second    
    REG_PIOB_CODR = led; // Clear Output Data Register, turns LED off 
    delay(1000);         // wait for a second    
}

the masking process do I really need to do that

You mean the (1u << 27), of course as that selects the bit in the port the action affects. You could I suppose just a constant of 0xFFFFFFFF and toggle all the bits on that port.

using an inline assembly code would be the same?

What do you mean here? Obviously the code would look nothing like this any more than the example you found back in reply #7 looks like normal Arduino C code. The REG_PIOB_xxx constants may be the same, that's about all.


Rob

What do you mean here? Obviously the code would look nothing like this any more than the example you found back in reply #7 looks like normal Arduino C code. The REG_PIOB_xxx constants may be the same, that's about all.

Yes of course, you are right.Thank you.

blackcoursar:
I found this in another part of the forum, the only thing that isn't really clear is the masking process do I really need to do that
or using an inline assembly code would be the same?

/*

Raw blink sketch for DUE revealing SAM3X8E registers used
    Turns on an LED on for one second, then off for one second, repeatedly.
*/

// Pin 13 mask
uint32_t led = (1u << 27);

void setup()
{                 
  // Output Enable Register
  REG_PIOB_OER = led;
}

// the loop routine runs over and over again forever:
void loop()
{
    REG_PIOB_SODR = led; // Set Output Data Register, turns LED on
    delay(1000);         // wait for a second   
    REG_PIOB_CODR = led; // Clear Output Data Register, turns LED off
    delay(1000);         // wait for a second   
}

Something like this:

void setup()
{
    asm volatile("mov r0, %[val]"::[val] "r" (&REG_PIOB_OER));
    asm volatile("mov r1, #1, lsl #27");
    asm volatile("str r1, [r0]");
}

void loop()
{
    asm volatile("mov r0, %[val]"::[val] "r" (&REG_PIOB_SODR));
    asm volatile("mov r1, #1, lsl #27");
    asm volatile("str r1, [r0]");
    asm volatile("ldr r0,=1000");
    asm volatile("bl delay");
    asm volatile("mov r0, %[val]"::[val] "r" (&REG_PIOB_CODR));
    asm volatile("mov r1, #1, lsl #27");
    asm volatile("str r1, [r0]");
    asm volatile("ldr r0,=1000");
    asm volatile("bl delay");
}

Now we see why inline assembly is such a nightmare :slight_smile:

Although you could wrap those two bits of code in single asm{} blocks to reduce typing a little.


Rob

void setup()
{
asm volatile("mov r0, %[val]"::[val] "r" (&REG_PIOB_OER));
asm volatile("mov r1, #1, lsl #27");
asm volatile("str r1, [r0]");
}

void loop()
{
asm volatile("mov r0, %[val]"::[val] "r" (&REG_PIOB_SODR));
asm volatile("mov r1, #1, lsl #27");
asm volatile("str r1, [r0]");
asm volatile("ldr r0,=1000");
asm volatile("bl delay");
asm volatile("mov r0, %[val]"::[val] "r" (&REG_PIOB_CODR));
asm volatile("mov r1, #1, lsl #27");
asm volatile("str r1, [r0]");
asm volatile("ldr r0,=1000");
asm volatile("bl delay");
}

Posted on: December 02, 2013, 05:18:21 pm
Posted by: blackcoursar

All i can say is that reading through arm assembly and inline assembly is a subject that really needs a lot of time.
Thank you for the help.

a subject that really needs a lot of time.

Yep, you would need a real good reason to do it.

Once upon a time assembly is all we had and you do get to the point where you have so many libraries etc that you can write code pretty fast. These days most of us have got a life and use C (if you can call that getting a life :))


Rob

Graynomad:

a subject that really needs a lot of time.

Yep, you would need a real good reason to do it.

Once upon a time assembly is all we had and you do get to the point where you have so many libraries etc that you can write code pretty fast. These days most of us have got a life and use C (if you can call that getting a life :))


Rob

But assembly is sometimes just more efficient. And for exact timing purposes.

True, especially for exact timing, like I said "you would need a real good reason to do it."


Rob