da ich mich wunderte, warum Bascom bei den paar Codezeilen 966 Byte verbraucht, habe ich den Bascom-Code mal 1:1 in Avr-gcc umgeschrieben:
Trotz Compiler-Direktive "OPTIMIZE = -O2" beträgt die Codelänge in C erstaunliche 912Byte (gegenüber 966Byte in Bascom).Code:#include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> // wg. char-print // interner RC-Oszillator #define F_CPU 8.0E6 //'Timeraufruf alle 178µs (10 Samples = 1 Bit = 1,778ms) #define INTERRUPT_PRELOADER 78 #define UART_BAUD_RATE 9600 // die gewünschte Baudrate #define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16L)-1) //UART ----------------------------------------------------------- char myCharBuffer[10]; char *myCharPtr; void UART_init(void){ UBRRL |= (uint8_t) UART_BAUD_SELECT; UCSRB = (1<<RXEN)|(1<<TXEN); //Sender & Empfänger aktivieren UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //Asynchron 8N1 } void UART_transmit(uint8_t c){ while(!(UCSRA & (1<<UDRE))); UDR = c; } void UART_transmit_string(uint8_t *string){ while(!(UCSRA & (1<<UDRE))); while( *string){ UART_transmit (*string++); } } void UART_transmit_byte(uint8_t b){ myCharPtr = myCharBuffer; myCharPtr = itoa( b,myCharPtr,10); UART_transmit_string(myCharBuffer); } //Timing für 10 Samples Per Bit = 1,778ms #define Samples_early 8 //Flanke Frühestens Nach 8 Samples #define Samples_late 12 //Flanke Spätestens Nach 12 Samples #define Samples_min 3 //Flanke Vor 3 Samples - > Paket Verwerfen //Variablen der ISR volatile uint8_t Sample; //eigentlich Bit volatile uint8_t Ir_lastsample; //zuletzt gelesenes Sample volatile uint8_t Ir_bittimer; //zählt die Aufrufe von Timer_IRQ volatile uint16_t Ir_data_tmp; //Bitstream volatile uint8_t Ir_bitcount; //Anzahl gelesener Bits //Rückgabewerte der ISR volatile uint8_t Address_rc5; volatile uint8_t Command_rc5; volatile uint8_t Rc5_flag; //eigentlich Bit // Initialisierung der Hardware void ioinit() { // Initialisiert Timer0 TCCR0 |= (1<<CS01); //Prescale=8 // TCNT0 = INTERRUPT_PRELOADER; //Counter TIMSK |= (1<<TOIE0); //Timer Overflow Interrupt } // Das Hauptprogramm int main() { // Peripherie initialisieren ioinit(); UART_init(); //Pin für TSOP1736 DDRB &= ~(1<<DDB0); // Eingang eh vorhanden // Interrupts aktivieren sei(); // Eine Endlosschleife. while (1) { if (Rc5_flag == 1) { Rc5_flag = 0; UART_transmit_string("\r\ntoggle:"); UART_transmit_byte((Command_rc5 & (1<<7))>>7); //clear the toggle bit Command_rc5 &= 0b01111111; UART_transmit_string(" Adresse:"); UART_transmit_byte(Address_rc5); UART_transmit_string(" Code:"); UART_transmit_byte(Command_rc5); } } } // Die Interrupt Service Routine (ISR) SIGNAL(SIG_OVERFLOW0) { TCNT0 = INTERRUPT_PRELOADER; Sample = !(PINB & (1<<PINB0)); //'bittimer erhöhen (bleibt bei 255 stehen) if (Ir_bittimer < 255) Ir_bittimer += 1; //flankenwechsel erkennen if (Ir_lastsample != Sample) { if (Ir_bittimer <= Samples_min) { //flanke kommt zu früh: paket verwerfen Ir_bitcount = 0; } else { //nur Flankenwechsel in Bit-Mitte berücksichtigen if (Ir_bittimer >= Samples_early) { if (Ir_bittimer <= Samples_late) { //Bit speichern Ir_data_tmp = (Ir_data_tmp << 1); Ir_data_tmp = Ir_data_tmp + Sample; Ir_bitcount +=1; } else { //Flankenwechsel zu spät: Neuanfang mit gemessener Flanke Ir_bitcount = 1; Ir_data_tmp = Sample; } //bittimer zurücksetzen wenn Timer > Samples_early Ir_bittimer = 0; } } //Kontrolle des Startbits auf 1 if (Ir_bitcount == 1) Ir_bitcount = Ir_data_tmp & 1; //Bit 0 //Alle 14 Bits gelesen? if (Ir_bitcount >= 14) { Command_rc5 = Ir_data_tmp & 0x3F ; //Bit 6 und 7 siehe unten Ir_data_tmp = (Ir_data_tmp >> 6); Address_rc5 = Ir_data_tmp & 0b00011111; //For extended RC5 code, the extended bit is bit 6 of the command. if ((Ir_data_tmp & (1<<6))==0) Command_rc5 |= (1<<6); //The toggle bit is stored in bit 7 of the command Command_rc5 |= ( (Ir_data_tmp & (1<<5)) <<2 ); //Paket erfolgreich gelesen Rc5_flag=1; //paket zurücksetzen Ir_bitcount = 0; } } //sample im samplepuffer ablegen Ir_lastsample = Sample; }
Fazit: Bascom macht hier keine schlechte Figur. Das Hauptproblem von Bascom ist das fehlende Registerrechnen. Ständig wird alles vom RAM hin- und hergeschaufelt. Da in GCC die Variablen für die ISR mit Volatile definiert werden müssen, kommt diese WINAVR-Optimierung nicht zum Zuge. (Volatile erfordert ca. 82 Byte zusätzlichen Code).
Markant ist in AVR-gcc die fehlende Push-Pop Orgie in der ISR:
bekanntlich langt hier Bascom ordentlich zuCode:¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ISR SIG_OVERFLOW0 in AVR-GCC ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ROM:00BD push r1 ROM:00BE push r0 ROM:00BF in r0, SREG ROM:00C0 push r0 ROM:00C1 clr r1 ROM:00C2 push r18 ROM:00C3 push r24 ROM:00C4 push r25 ... ROM:016D pop r25 ROM:016E pop r24 ROM:016F pop r18 ROM:0170 pop r0 ROM:0171 out SREG, r0 ROM:0172 pop r0 ROM:0173 pop r1 ROM:0174 reti
Code:¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ISR Timer0 in Bascom ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ROM:008F push r0 ROM:0090 push r1 ROM:0091 push r2 ROM:0092 push r3 ROM:0093 push r4 ROM:0094 push r5 ROM:0095 push r7 ROM:0096 push r10 ROM:0097 push r11 ROM:0098 push r16 ROM:0099 push r17 ROM:009A push r18 ROM:009B push r19 ROM:009C push r20 ROM:009D push r21 ROM:009E push r22 ROM:009F push r23 ROM:00A0 push r24 ROM:00A1 push r25 ROM:00A2 push r26 ROM:00A3 push r27 ROM:00A4 push r28 ROM:00A5 push r29 ROM:00A6 push r30 ROM:00A7 push r31 ROM:00A8 in r24, SREG ROM:00A9 push r24 ... ROM:0154 pop r24 ROM:0155 out SREG, r24 ROM:0156 pop r31 ROM:0157 pop r30 ROM:0158 pop r29 ROM:0159 pop r28 ROM:015A pop r27 ROM:015B pop r26 ROM:015C pop r25 ROM:015D pop r24 ROM:015E pop r23 ROM:015F pop r22 ROM:0160 pop r21 ROM:0161 pop r20 ROM:0162 pop r19 ROM:0163 pop r18 ROM:0164 pop r17 ROM:0165 pop r16 ROM:0166 pop r11 ROM:0167 pop r10 ROM:0168 pop r7 ROM:0169 pop r5 ROM:016A pop r4 ROM:016B pop r3 ROM:016C pop r2 ROM:016D pop r1 ROM:016E pop r0 ROM:016F reti







Zitieren

Lesezeichen