Hi, looking for instruction how to use inline assembler within C++ code I found several examples for the Arduino 8 bit controllers. I want to use inline assembler on my Due for which there is a different compiler.
To the following example for an Atmega16u2 I have some questions:
There are reference to variables with %0 and %1, but according to the comments, e.g. %0 is referencing variable countlow and later variable off. I don't understand this.
Generally, can somebody recommend some literature about inline assembler on Due?
The operand references (%1 %0 etc) are defined after the assembly instructions. The documentation is a bit heavy reading, but after a while it is decipherable. Unfortunately most examples are for x86 code, but it is similar for other processors. For example https://avrdudes.github.io/avr-libc/avr-libc-user-manual-2.2.0/inline_asm.html
I read through the mentioned documents and tried a simple example. It is derived from an example in "Inline Assembler Cookbook" with assembler statements for the SAM3X which is the controller on the Due board.
uint32_t getData(uint8_t* ptdata, uint8_t* ptend) {
uint32_t st_value; // vom EPM3064 eingelesenes Ergebnis
do {
// wait for Flag:
REG_PIOC_SODR = 0x00800000; // set TICPIN
// do
// st_value = REG_PIOC_PDSR;
// while ((st_value & 0x000000200) == 0); // wait for Flag
asm volatile (
"PUSH R0, R1, R11 \n\t"
"MOV R0, #0 \n\t"
"MOV R11, %[PDSRPIOC] \n\t" // address of PIOC_PDSR
"1: \n\t"
"LDR R1, [R11, R0] \n\t" // input PORTC to R1
"LSLS R1, R1, #22" // Flag is bit 9 of register R1
"BPL 1f \n\t" // jump back to "1:" if Flag=0
:
: [PDSRPIOC] "I" (_SFR_IO_ADDR(PIOC_PDSR))
:
);
...
TICPIN is a special pin on the Due board which is set/reset by code to show operations in real time with an oscilloscope.
The three commented lines:
// do
// st_value = REG_PIOC_PDSR;
// while ((st_value & 0x000000200) == 0); // wait for Flag
shall be replaced by the following assembler statements.
Removing the commenting // and without assembler the code works fine.
The compiler is reporting errors:
error: 'PIOC_PDSR' was not declared in this scope
error: '_SFR_IO_ADDR' was not declared in this scope
My questions:
what includes are necessary in order to use the macro _SFR_IO_ADDR() which is copied from an example in "Inline Assembler Cookbook"?
where can I find the correct names for ports to be used in assembler, e.g. PIOC_PDSR?
It has been decades since I have done inline assembly and have never used a Due. I would start with the data sheet, particularly section 31. There are probably header files defined somewhere in the Atmel development system.
The assembler part shall load the address of register PIOC_PDSR to R11 and store it to the variable st_value.
Outside the assembler part st_value ist printed out as: st_value=0x0
The compiler accepts the assembler statement "STR R11, %0 \n\t"
which is the syntax of 8 bit AVR assembler (example from my research). But code descriptions of Dues SAM3XA assembler tell me that store statements need to look like STR Rd, [Rn, <offs>]
with e.g. #0.
This means register Rd will be stored to the address Rn+#0, i.e. I need the address of st_value.
In all the docs I read I couldn't find an example how to get the address of a variable. Has anybody an idea?