I have significant experience with AVR assembler (using AVR Studio 4) and almost zero with C language. I'm working on project that will measure some curves and need to output them on graphic display. I have enough working code pieces to put together measurement completely in assembler but no library for graphic displays.
I already modified mcufriend display special to my Mega128 board pinout and his examples are working on my board.
I need to decide what will be easiest way - tray to include my asm file in Arduino IDE or tray to transfer graphic library to AVR Studio 4 if it's possible. I will not not if possible go to newer AVR Studio because my programming tools are not supported there.
You can mix inline assembler, assembler and C/C++ in the same sketch.
To include an assembler program, in addition to a (or several) C/C++ Library inside your sketch folder, create a .S file by clicking in the upper right arrow in your IDE window, name it as you like (e.g. foo.S) and inside the .ino sketch, declare all your assembler functions with extern "C".
Here is a basic sketch :
The .ino sketch
char array[] =" Hello World\n";
extern "C"
void Print_Hello();
void setup() {}
void loop() {
Print_Hello();
delay(500);
}
The .S file
#include "avr/io.h"
.global Print_Hello
.set size_of_array, 14
Print_Hello:
; Setting baud rate 9600
clr r0
sts UCSR0A, r0
ldi r24, 1<<RXEN0 | 1 << TXEN0 ; enable Rx & Tx
sts UCSR0B, r24
ldi r24, 1 << UCSZ00 | 1 << UCSZ01 ; asynchronous, no parity, 1 stop, 8 bits
sts UBRR0H, r0
ldi r24, 103
sts UBRR0L, r24
; loading address and size of array
ldi XL, lo8(array) ; r26
ldi XH, hi8(array) ; r27
ld r16, X ; Load charactere pointed by X registers (r26/r27)
ldi r24, size_of_array
Loop:
lds r17, UCSR0A
sbrs r17, UDRE0 ; test the data buffer if data can be transmitted
rjmp Loop
sts UDR0, r16 ; send data contained in r16
dec r24
ld r16, X+ ; point to the next charactere
brne Loop
ret
/******************************************************/
wait:
ldi R17, 0x53
LOOP0: ldi R18, 0xFB
LOOP1: ldi R19, 0xFF
LOOP2: dec R19
brne LOOP2
dec R18
brne LOOP1
dec R17
brne LOOP0
ret
Charlyf:
I have significant experience with AVR assembler (using AVR Studio 4) and almost zero with C language.
You'll learn quickly, as you see stuff you do all the time in ASM manifested in the language.
Already find out that assembler in arduino IDE has different syntax from AVR studio, .byte or .string instead db, hi8,lo8 instead HIGH,LOW and need of pm if you refer to program memory, but I can not find out how to multiply address by two:
ldi r31,hi8(pm(array*2))
ldi r31,hi8(pm(array<<1))
are both giving error,
but ldi r31,hi8(pm(array)) loads pointer to 1/2 needed address.
Sorry needed to say that I found a solution myself
ldi r31,hi8(array)
ldi r30,lo8(array)
...
lpm r16,Z+
works correctly, what I don't understand is what purpose pm has...
BTW without pm arithmetic inside braces is working!
pm along with pm_lo8/pm_hi8 are used for addresses located in Flash/Program memory (documentation found here). These are not macros, but rather builtin assembler functions. Note that pm (for program memory) returns a byte address suitable for use by the LPM instruction, whereas lo8/hi8 return word addresses.
Specific to your situation, unlike the Atmel's assembler, the GNU assembler doesn't know the address which is determined at link time, therefore it can’t perform math upon it.
ldi r31,pm_hi8(array)
ldi r30,pm_lo8(array)
and
ldi r31,hi8(pm(array))
ldi r30,lo8(pm(array))
give the same 1/2 value of correct address for LPM command
ldi r31,hi8(array)
ldi r30,lo8(array)
give correct address.
Possibly there is some bug in current compiler version , copy/paste from another processor
that has two separate commands for low and high half of program memory.