I am trying to adopt a piece of code, where there is a declaration of a C routine; which mainly consists of an inline assembly code. However when I compile/link it, IN case i call the C-routine from main I get the assembly/linker error
> C:\Documents and Settings\ge\Skrivbord\LED strip\GITHUB code>avr-gcc -g -Os -mmcu=atmega8 -c ws2.c
C:\DOCUME~1\ge\LOKALA~1\Temp/ccVFmJez.s: Assembler messages:
C:\DOCUME~1\ge\LOKALA~1\Temp/ccVFmJez.s:136: Error: symbol `pr_byte' is already defined
C:\DOCUME~1\ge\LOKALA~1\Temp/ccVFmJez.s:146: Error: symbol `one_bit' is already defined
C:\DOCUME~1\ge\LOKALA~1\Temp/ccVFmJez.s:154: Error: symbol `both_low' is already defined
C:\DOCUME~1\ge\LOKALA~1\Temp/ccVFmJez.s:163: Error: symbol `nxt_byte' is already defined
C:\DOCUME~1\ge\LOKALA~1\Temp/ccVFmJez.s:169: Error: symbol `done' is already defined
where as if I comment out the call I do not get that error, code is as follows:
#include <avr/io.h>
#define F_CPU 8000000 // 8MHz
void update_line( const void *values, uint16_t array_size, uint8_t output_bit){
asm volatile(
" LD __tmp_reg__, %a[dataptr]+ \n"
" LDI %[bits], 8 \n" // load no of bits in byte count
"pr_byte: \n"
" LSL __tmp_reg__ \n" // Load next bit into carry flag.
" OUT %[portout], %[upreg] \n" // Go high, start of bit-symbol,
" BRCS one_bit \n" // bit value is in carry flag
" NOP \n"
" OUT %[portout], %[downreg] \n" // go low for 0-bit-symbol (3clc) (carry low)
" NOP \n"
" NOP \n"
" NOP \n"
" rjmp both_low \n" //
"one_bit: \n" //
" NOP \n"
" NOP \n"
" NOP \n"
" NOP \n"
" NOP \n"
" NOP \n"
" OUT %[portout], %[downreg] \n" // go low for the 1-bit-symbol
"both_low: \n" // both low; time to initiate next bit
" SUBI %[bits], 1 \n" // bit countdown for byte
" BREQ nxt_byte \n" //
" NOP \n" // 5nop still bits left to process
" NOP \n"
" NOP \n"
" NOP \n"
" NOP \n"
" rjmp pr_byte \n" // take next bit
// end of previous byte, pick new
"nxt_byte: \n" // 3used/10
" SBIW %[bytes], 1 \n" // byte countdown
" BREQ done \n"
" LD __tmp_reg__, %a[dataptr]+ \n" // Load next byte
" LDI %[bits], 7 \n" // load bit-in-byte count
// fill time before next bit-symbol, none left, kritical ?
"rjmp pr_byte \n" // take next
"done: NOP \n" // program should end in low note, som contents will be displayed
: /* no output */
: /* inputs */
[dataptr] "e" (values),
[upreg] "r" (set_obit_high),
[downreg] "r" (set_obit_low),
[bytes] "w" (size),
[bits] "d" (bitcount),
[portout] "I" (_SFR_IO_ADDR(WS2811_PORT))
);
} /* update_line() */
int main () {
uint8_t LED_rgb;
struct rgb LED_string[48]; // a continuous string of 3 bytes(rgb)
int LED_len = 48;
//update_line( LED_string, 48*3, 1); //<*************
} /*end main*/
`
so the interresting thing is there seem to have been generated labels for the "update_line" routine first when the routine is declared, and then ALSO when the routine is called ! so in some way it seems that the whole routine becomes "inline" (in the sense that its code is placed at the position of call itself). Im a bit at loss as both what is happening and as to what can be done (there seem to be possible to generate new labels using %= / but still why should the code be multiplied)
tnx Georg
%=
might actually be better (not sure what happens if main calls update_line twice). However, let me take a minute to pitch NOT using inline asm (see this). – David Wohlferd