I want to have an ISR for the watchdog timer. I've got working code that has been running in an assembly project for some time and I now want to use the same code within the Arduino environment.
Now of course I can use asm("") but the function is about 150 lines long so that would be a pain plus very difficult to maintain/modify.
There's asm volatile () but that's not much better.
If I was in my normal AVR environment I would figure out how to link the object file or whatever.
But is there a clean way to do this in Arduino. For example
ISR (WDT_vect) { #include "my_asm_file.s"
}
would be about perfect if my_asm_file was straight assembly code.
Why not just rewite in C? I don't think that's an option because I need to have direct access to registers and the stack, but maybe.
For now if I can do it in ASM I would prefer that.
I can't help with embedding the assembly or linking to the assembled object file but...
Why not just rewite in C? I don't think that's an option because I need to have direct access to registers and the stack, but maybe.
GCC-AVR (and C in general) does a nice job of providing direct access to those things. For example, the stack pointer can be accessed with "SP". If you decide to try the C route, I can't promise you'll like the journey but I will try to help get you to your destination.
Truth is I only really wanted SP access because that's where some regs are stored in the ASM version. In C nobody cares about registers (this is a monitor program) so maybe that doesn't matter.
But is there a clean way to do this in Arduino. For example
ISR (WDT_vect) { #include "my_asm_file.s"
}
Thinking out loud.
You can include a .h file in any project as a local file. So maybe a rename to the my_asm_file.h could do the trick? such as below? Only thing you need is a small script to convert the .s file into an appropiate .h file.
void setup() {}
void loop()
{
#include "asm.h"
}
asm.h contains:
// do nothing;
asm("nop");
comments in the asm.h file could contain C code as sort of reference - a bit like: ...\avr-objdump -D -S file.cpp.elf | more
I already tried something similar and a couple of variations, it does seem to work but you still have to put all the lines inside an asm("") or you get compiler errors.
import sys, os
def asm2include(infile, outfile):
line = ""
with open(infile, 'r') as IN:
for line in IN:
line = line.strip(' ')
if (line != ""):
line = line.replace(' ',' ')
OUT = open(outfile, "a")
if (line.startswith("//") == False):
OUT.write("asm(\"")
OUT.write(line[:-1])
OUT.write("\");\n")
else:
OUT.write(line)
OUT.write("\n")
OUT.close()
print '.',
""" --------------------------------------------------------------
MAIN APPLICATION
"""
print "ASM2include 0.1"
asm2include(sys.argv[1], sys.argv[2])
print "Done"
is not. In AVR assembler the // is valid for a comment.
No #defines or .equs work so I've had to replace everything with hex numbers.
Macros cause an EOF error so I've put the code in line.
In short the code now looks like a dog's breakfast and it will be totally unmaintainable, but is is running, although not correctly. It looks like the chip is constanly resetting so I'd say the WD is not being reset or something.
The C option looks better all the time.
@Rob
I just noticed you've edited the last post. How do I run that python script?
I think current IDE will assemble .S files. That leaves merging C's treatment of the vector table with the ASM code.
You ought to be able to do something like:
Thanks westfw, using ISR_NAKED fixed my resetting problem with the #included file in the ISR. Presumably because I did my own reti the stack crashed after a while because the postamble never got executed.
Now how do I get the IDE to link in the .S file? The only thing I can see is Sketch>Add file which appears to do nothing.
I created a text file named asm2include.py (.py being the python extention) with the contents shown before (and slightly adapted)
I copied your asm code to test.asm
I open a command window; changed dir to my python directory; and called:
new version of asm2include.py, still in beta^2 but a small step made
added - #defines are handled
added - empty lines are removed
Python code:
import sys
def asm2include(infile, outfile):
line = ""
# empty dictonary for defines
defines = {}
OUT = open(outfile, "a")
with open(infile, 'r') as IN:
for line in IN:
line = line.strip(' ') # strip leading and trailing spaces
if (len(line) > 1):
line = line.replace(' ',' ')
# put all defines in a dictionary
if (line.startswith("#define")):
x = line.split()
defines[x[1]] = x[2]
continue # goto next line
if (line.startswith("//") == False):
# iterate through dictionary to replace #defines
for k in defines.keys():
line = line.replace( k, defines[k] )
OUT.write("asm(\"")
OUT.write(line[:-1])
OUT.write("\");\n")
else:
OUT.write(line)
print '.',
OUT.close()
# --------------------------------------------------------------
# MAIN APPLICATION
print "ASM2include 0.1.1"
asm2include(sys.argv[1], sys.argv[2])
print "Done"
I use a .h file so the IDE doesn't complain, it's a bit of a hack. You seem to have to use an absolute path to .include, and you have to remember to save it in the IDE each time you change it before compiling.
asm("#define SREG 0x3f\n");
asm(" in r16,SREG\n"); // fails with "Error: constant value required"
asm(" in r16,0x3f\n"); // works
@CB
I tried with and without \n, no difference. I often wondered about the \n in these assembler examples, it's the sort of thing you do when generating HTML code that has to be read by a human but you wouldn't expect it to be required here.
@Rob
I did the same with the small exception that I don't have python installed :), I'll go and get it.
at com.oroinc.text.regex.Perl5Matcher._match(Perl5Matcher.java)
errors.
However I noticed your .equ syntax is different
asm(".equ SREG,0x3f\n");
asm(" in r16,SREG\n"); // this works
but
asm(".equ r_temp1,r16\n");
asm(" push r_temp\n"); // this doesn't work, Error: register name or number from 0 to 31 required
asm(" in r_temp,SREG\n"); // same error
Is this the ASM equivelant of "lvalue required"?
Anyway that's where I left it at 2AM last night. I'm back on deck now so will continue with this.
I don't know if you can properly use .equ or = to rename registers.
But it just happens to work under certain circumstances. In particular, don't make the first letter of the symbol 'r' and omit the 'r' from the register. ie:
I'll have to check the mechanics of having assembler included in your sketch when I'm at home with the source code.
I thought you could add a .S tab to your sketch just the way you can add .h, .c, or .cpp modules. It may have to be capitalized...
Huh. It looks like the "Compiler" part of the IDE understands .S files, but the editor refuses to add such files to the sketch, or pass them to the compiler. Hmmph.