PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [gelöst]Software UART (AVR305) als inline ASM in GCC



vklaffehn
21.01.2009, 13:23
Moin!
Ich habe hier ein Phänomen, meine tapfere SW-UART Routine funktioniert 'plötzlich' nicht mehr. Ich habe mal alles rausgeschmissen und nur die senderoutine mit einer Schleife dringelassen, aber irgendwie klappt das alles nicht mehr. -zum Hintergrund muß ich sagen, daß ich vor kurzem auf WinAVR-20080610 und das aktuelle AVR Studio aktualisiert habe, der Code selbst ist unverändert.
Hier mal mein Programm :


#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

void txd(uint8_t value)
{
uint8_t bitcnt;
uint8_t delay;

__asm__ __volatile__(
"cli\n\t"
"ldi %0,0x0a\n\t" //;1+8+sb (sb is # of stop bits)
"com %2\n\t" //;Inverte everything
"sec\n\t" //;Start bit

"0:brcc 1f\n\t" //;If carry set
"sbi 0x15,5\n\t" //;send a '0'
"rjmp 2f\n\t" //;else

"1:cbi 0x15,5\n\t" //;send a '1'
"nop\n\t"

"2:rcall 3f\n\t" //;One bit delay
"rcall 3f\n\t"

"lsr %2\n\t" //;Get next bit
"dec %0\n\t" //;If not all bit sent
"brne 0b\n\t" //;send next
"sei\n\t" //;else
"ret\n\t" //; return

"3:ldi %1,19\n\t"
"4:dec %1\n\t"
"brne 4b\n\t"
"ret\n\t"


:"=r"(bitcnt),"=r"(delay),"=r"(value):"2"(value));

}
/*
BaudRate Cycles required b-value Error %
2400 6667 (2) 1107 0
4800 3333 (2) 552 0
9600 1667 (2) 274 0
14400 1111 181 0,2
19200 833 135 0
28800 556 89 0,3
57600 278 42 1
115200 139 19 1,4
*/





int main(void)

{
unsigned char cnt;

DDRC = (1<<PC5);

for (cnt=0;cnt<100;cnt++) txd(10);

return 0;
}


Der Fehler war, daß das Programm immer eine 0 sendete und dann nichts mehr. Als ich dann bei den Operanden am Ende das '):"2"(value)' ergänzte, bekam ich immerhin das korrekte Zeichen, aber nur einmal. Auch mit der Schleife bekomme ich jetzt nur einmal eine 10, danach bleibt das Programm stehen bzw. es kommt ncihts mehr. Bei der Verwendung in meinem ursprünglichen Programm, wo ich den Inhalt eines Arrays senden will, bleibt das Programm zwar nicht stehen, aber der Controller scheint einen Reset zu machen ö.ä., da ich statt des Arrays immer nur den ersten Wert des Arrays bekomme und danach das Programm neu startet, daher vermute ich, daß irgendwas mit den Registern nicht passt, aber ich komm leider einfach nicht dahinter. Vielleicht kann mir einer einen Tipp geben, wieso das jetzt 'auf einmal' nicht mehr funktioniert??
Vielen Dank schonmal!!

MfG Volker

Besserwessi
22.01.2009, 18:22
Ich kann die Delayroutine zu rcall 3f nicht finden. Das sollte wenigstens eine warnung geben-

vklaffehn
22.01.2009, 20:22
Moin!
Na das ist die ab dem '3:' :-)
Das ganze hat sich aber gerade sowieso erledigt:

einmal meine softuart.c


#include "softuart.h"

void txd (unsigned char value)
{
uint8_t bitcnt = 1+8+STOP_BITS;
uint8_t delay = bvalue; //see softuart.h

value = ~value;

cli();

__asm__ __volatile__(
" sec ; Start bit " CR_TAB

"0: brcc 1f ; If carry set " CR_TAB
" sbi %[port],%[pad] ; send a '0' " CR_TAB
" rjmp 2f ; else " CR_TAB

"1: cbi %[port],%[pad] ; send a '1' " CR_TAB
" nop" CR_TAB

"2: %~call bit_delay_%= ; One bit delay " CR_TAB
" %~call bit_delay_%=" CR_TAB

" lsr %[value] ; Get next bit " CR_TAB
" dec %[bitcnt] ; If not all bit sent " CR_TAB
" brne 0b ; send next " CR_TAB
" rjmp 5f ; else: done " CR_TAB
CR_TAB
"bit_delay_%=:" CR_TAB
" mov __zero_reg__, %[delay]" CR_TAB
"4: dec __zero_reg__" CR_TAB
" brne 4b" CR_TAB
" ret" CR_TAB
"5:" CR_TAB

: [bitcnt] "=r" (bitcnt), [value] "=r" (value)
: "1" (value), "0" (bitcnt), [delay] "r" (delay), [port] "M" (_SFR_IO_ADDR(SWUART_PORT)), [pad] "M" (SWUART_PIN)
);

sei();
}

und dazu meine softuart.h


#include <avr/io.h>
#include <avr/interrupt.h>

#define CR_TAB "\n\t"
#define STOP_BITS 1

#define bvalue 19 //115200 Baud
#define SWUART_PORT PORTC //TX Port
#define SWUART_PIN 5 //TX Pin

/*
b-values for 16 MHz

BaudRate Cycles required b-value Error %
2400 6667 (2) 1107 0
4800 3333 (2) 552 0
9600 1667 (2) 274 0
14400 1111 181 0,2
19200 833 135 0
28800 556 89 0,3
57600 278 42 1
115200 139 19 1,4
*/


void txd (unsigned char value) ;

Bei anderen Frequenzen in der AppNote AVR305 nachschauen...
Dieser Software-UART braucht nichts außer einem freien Pin, praktisch zum debuggen z.B..
Falls das noch jemand braucht, einfach in der softuart.h Port und Pin sowie Verzögerung für die Baudrate lt. Liste anpassen und los gehts.

Trotzdem danke!!