Progrsmming arduino with assembly

Hi,

Recently I learned AVR assembly language and now I would like to implement in my arduino board.But,I was using Arduino software to write and upload my sketch which supports arduino C only. I also saw a glance on Inline assembler for arduino,but that seems to have lot of rules and it doesn't seems to be flexible.I have Atmel studio,to make and verify file which basically generates a .hex file after build.Is there any way to upload that .hex file to my arduino uno board?

I think your title should be changed to "How to upload a hex file to an Arduino". You can change the title if you edit your Original Post.

It is possible. The Arduino IDE uses a program called AVRDUDE to do that.

Nick Gammon has a page about it here

...R

You don't need to use inline, you can add standard assembly files (using the .S file extension) to your sketch in Arduino IDE.

Here's something I just cobbled together. It's the only time I've messed with assembly so I'm sure there's a better way to do this but it does work:

blink.ino:

extern "C" {
  // function prototypes
  void start();
  void blink();
}

void setup() {
  start();
}

void loop() {
  blink();
}

blink.S:

; Blink LED on PB5(Arduino Uno pin 13)
; http://forum.arduino.cc/index.php?topic=159572#msg1194604

#define __SFR_OFFSET 0
  
#include "avr/io.h"

.global start
.global blink

start:
  sbi   DDRB,5  ; Set PB5 as output
  ret

blink: 
  ldi   r20,250 ; Set the delay duration in ms. Maximum value is 255.
  call  delay_n_ms
  sbi   PORTB,5 ; Set PB5 HIGH
  ldi   r20,250
  call  delay_n_ms
  cbi   PORTB,5 ; Set PB5 LOW
  ret

delay_n_ms:
  ; Delay about r20*1ms. Destroys r20, r30, and r31.
  ; One millisecond is about 16000 cycles at 16MHz.
  ; The basic loop takes about 5 cycles, so we need about 3000 loops.
  ldi   31, 3000>>8 ; high(3000)
  ldi   30, 3000&255  ; low(3000)
delaylp:
  sbiw    r30, 1
  brne    delaylp
  subi    r20, 1
  brne    delay_n_ms
  ret

I seem to remember there was some work done on this in the last year or two so I'd recommend using a recent version of the Arduino IDE.

Thanks @pert. I have bookmarked that.

...R

Thank you @ pete. Can you please tell me the step by step procedure to write in assembly that you mentioned in that post

  1. Start Arduino IDE.
  2. Select File > New from the Arduino IDE menus.
  3. Paste the code titled blink.ino into the IDE editor panel.
  4. Click the upside down triangle button at the right of the editor toolbar.
  5. Select "New Tab" from the menu.
  6. In the "Name for new file:" field, type blink.S
    You can give the file any name you like as long as it has the .S extension.
    :exclamation: The file extension must be an uppercase S.
  7. Paste the code titled blink.S into the IDE editor panel window in the "blink.S" tab.
  8. Upload the sketch to your board as usual.

You should see the LED connected to pin 13 start blinking.

You can also use assembly files in libraries with the Arduino IDE in the same way. You would put the prototypes for the functions defined in the assembly files in a header file and then include that header file in your sketch.

2 Likes

I kept a copy too. Thanks pert.

I'm glad if it can be of use to some people. I've been wanting to try an assembly blink just for fun ever since I learned that the IDE supported it. I'm not very interested in learning assembly but I'm glad the IDE has this capability. It's really cool that the Arduino IDE is so beginner friendly but also has support for doing advanced things.

Hi pete

Sorry for the long delay.I still get some error in the program from the blink.S while compiling.

Error message:

blink.S.ino:5:1: error: expected unqualified-id before '.' token
blink.S.ino:20:27: error: expected constructor, destructor, or type conversion before '(' token
blink.S.ino:21:26: error: expected constructor, destructor, or type conversion before '(' token
expected unqualified-id before '.' token

Is there any solution for these error pete. I am using the latest Arduino IDE.

Aadarsh:
blink.S.ino

That's your problem. The assembly file needs to be named blink.S, not blink.S.ino. You'll need to rename that file.

Hi pete,

I changed the file to .S extension and it automatically changed it icon as asm ,where I already have atmel studio. That's fine. But now ,when I try to reopen the sketch (blink.S) ,arduino IDE shows an error message that ,it can't open this extension

The sketch folder should have this structure:

blink/
├── blink.S
└── blink.ino

When you open blink.ino with Arduino IDE it will automatically load blink.S in an editor tab along with blink.ino.

Hi pete,

Yes,as you told it works.But sorry to interrupt you with this last doubt.I get a small error.You gave me the code for ATmega328p,in which CALL instruction works.In my case I use Atmega8a,so I changed as RCALL. That's okay.Still I get an error.This shows "error compilation for Arduino NG or Older"

"C:\Users\acer\AppData\Local\Temp\build9c7c7e558bc8fbc32ec51c7294aac46d.tmp/core\core.a(main.cpp.o): In function `main':

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:46: undefined reference to `loop'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino NG or older."

How to get rid of this error?

I got "blink.S:20: Error: illegal opcode jmp for mcu avr4" after I change the CALL instructions to RCALL. I guessed that I should change JMP to RJMP and after that it compiles fine for Arduino NG or older, ATmega8 using Arduino IDE 1.6.9 and 1.6.10.

pert ... Thank you VERY much !!!

Your post #2 above is what I have been trying to accomplish for a long time ... almost! It seems to me that once "start" is called, it never returns to the ".ino" file code. Doesn't it just drop down into the "blink" code in the ".S" file? How would I get the code to return to the ".ino" file so that I am just using the ".S" code as a library type function? I want to do some things in the IDE "C" code and some time-critical things in assember.

Thank you for your gracious assistance with this question.

Blessings in abundance, all the best, & ENJOY!
Art in Carlisle, PA USA

webtest:
It seems to me that once "start" is called, it never returns to the ".ino" file code. Doesn't it just drop down into the "blink" code in the ".S" file?

Good point! I really don't know anything about assembly. I just blindly copied that assembly code from the forum post in the comment without closely looking at it, figured out how to call the functions from the .ino file, verified that it blinked, and called it good.

webtest:
How would I get the code to return to the ".ino" file so that I am just using the ".S" code as a library type function?

I fixed it by adding a ret to the start function, which fixes the issue of the blink() call in the sketch doing nothing. I also made blink() return so that the sketch is a closer analog to the standard Arduino "Blink" example.

webtest:
I want to do some things in the IDE "C" code and some time-critical things in assember.

You probably already understand this, and it may not be relevant to your application, but I'm going to say it anyway. The blink function in the code I posted above is not a good example for that purpose because, just like the standard Blink example, it is blocking. This is fine for creating a very simple example that's easy to understand but almost never useful for any more advanced application.