Hallo,
bin mittlerweile nahezu am verzweifeln und bräuchte bitte dringend ein
nicht vorbelastetes Auge, ich hoffe ihr könnt mir helfen.
Ich habe einen simplen Funktionsaufruf aus der main() in eine andere
Funktion in einer anderen Datei des Projekts.
Es handelt sich um die uart2_s_pro3(unsigned char), uart2_s_pro1 und
uart2_s_pro2 funktionieren tadellos.
Per Debugging habe ich festgestellt, dass die Funktion richtig
abgearbeitet wird (auch die Hardware reagiert richtig) aber anstatt beim
return an die richtige Adresse zurückzuspringen landet der uC im leeren
Speicherbereich.
main.c, Endlosschleife
1 | while(1)
|
2 | {
|
3 | wdt_reset();
|
4 |
|
5 | // Eingänge invertieren, Achtung: ~ nur für 8 Bit!!
|
6 | cod_switch = 0;
|
7 | cod_buffer = 0;
|
8 |
|
9 | cod_buffer = ~PINL;
|
10 | cod_switch |= (WORD)(cod_buffer);
|
11 |
|
12 | cod_buffer = (~(PIND)) & 0x03;
|
13 | cod_switch |= (WORD)((cod_buffer)<<8);
|
14 |
|
15 | DmxAddress = (uint16_t) cod_switch;
|
16 |
|
17 | // DMX READOUT
|
18 | DmxProtokoll = DmxRxField[0]; // Modus / Symbolnummer
|
19 |
|
20 | color_t.red = DmxRxField[1];
|
21 | color_t.green = DmxRxField[2];
|
22 | color_t.blue = DmxRxField[3];
|
23 |
|
24 | color_b.red = DmxRxField[4];
|
25 | color_b.green = DmxRxField[5];
|
26 | color_b.blue = DmxRxField[6];
|
27 |
|
28 | white_calc(&color_b);
|
29 | white_calc(&color_t); // Es werden RGB-Werte übermittelt, weiß herausgerechnet
|
30 |
|
31 | // Dimmen wegen Wärme, Einstellungen siehe global.h
|
32 | rgbw_dimm(&color_b);
|
33 | rgbw_dimm(&color_t);
|
34 |
|
35 |
|
36 | for(m=0;m<WORKING_DELAY;m++) // dem BUS ein bisschen erholzeit verschaffen
|
37 | for(n=0;n<WORKING_DELAY;n++);
|
38 |
|
39 | cli();
|
40 |
|
41 | if(DmxProtokoll == 1) // code nummer 1, fixfarbe
|
42 | {
|
43 | for(c_address = 1; c_address <= 7; c_address++)
|
44 | {
|
45 | uart2_s_pro1(c_address);
|
46 | for(c_pro2_delay = 0; c_pro2_delay < 200; c_pro2_delay++);
|
47 | }
|
48 | }
|
49 |
|
50 |
|
51 | else if(DmxProtokoll == 2) // code nummer 2, farbverlauf
|
52 | {
|
53 | for(c_address = 1; c_address <= 7; c_address++)
|
54 | {
|
55 | uart2_s_pro2(c_address);
|
56 | for(c_pro2_delay = 0; c_pro2_delay < 200; c_pro2_delay++);
|
57 | }
|
58 | }
|
59 |
|
60 | else if(DmxProtokoll > 2 && DmxProtokoll < 39) // Zeichen
|
61 | {
|
62 | uart2_s_pro3((BYTE)(DmxProtokoll-3));
|
63 | }
|
64 |
|
65 | else // Karomuster, 0 und alle nicht genutzten Werte
|
66 | {
|
67 | DmxAddress = DmxAddress; // für Breakpoint setzen
|
68 | uart2_s_pro3(0x00); // Symbol für Karomuster
|
69 | }
|
70 |
|
71 | sei();
|
72 | }
|
Erklärung: per Dmx werden Steuerbytes eingelesen und entsprechend
ovrgegangen. Protokoll 1 + 2 funktioniert tadellos, nur beim Protokoll 3
habe ich das Problem dass beim Return vom Stack offensichtlich alles
andere nur nicht die Rücksprungadresse gepoppt wird.
Sendefunktion
uart2.c
1 | char uart2_s_pro3(BYTE symbolnr)
|
2 | {
|
3 | volatile BYTE adr_count = 1;
|
4 | volatile WORD u2_count = 0;
|
5 |
|
6 | PORTB |= (1 << R_W_2); // Auf senden umstellen
|
7 |
|
8 | for(adr_count = 1; adr_count <= 7; adr_count++)
|
9 | {
|
10 | while (!(UCSR2A & (1<<UDRE2))) {}
|
11 | UDR2 = adr_count;
|
12 | u2_crc_c = adr_count; // Zieladresse
|
13 | while (!(UCSR2A & (1<<UDRE2))) {}
|
14 | UDR2 = 0x03;
|
15 | u2_crc_c ^= 0x03; // Protkollnummer
|
16 | while (!(UCSR2A & (1<<UDRE2))) {}
|
17 | UDR2 = color_t.red;
|
18 | u2_crc_c ^= color_t.red;
|
19 | while (!(UCSR2A & (1<<UDRE2))) {}
|
20 | UDR2 = color_t.green;
|
21 | u2_crc_c ^= color_t.green;
|
22 | while (!(UCSR2A & (1<<UDRE2))) {}
|
23 | UDR2 = color_t.blue;
|
24 | u2_crc_c ^= color_t.blue;
|
25 | while (!(UCSR2A & (1<<UDRE2))) {}
|
26 | UDR2 = color_t.white;
|
27 | u2_crc_c ^= color_t.white;
|
28 | while (!(UCSR2A & (1<<UDRE2))) {}
|
29 | UDR2 = color_b.red;
|
30 | u2_crc_c ^= color_b.red;
|
31 | while (!(UCSR2A & (1<<UDRE2))) {}
|
32 | UDR2 = color_b.green;
|
33 | u2_crc_c ^= color_b.green;
|
34 | while (!(UCSR2A & (1<<UDRE2))) {}
|
35 | UDR2 = color_b.blue;
|
36 | u2_crc_c ^= color_b.blue;
|
37 | while (!(UCSR2A & (1<<UDRE2))) {}
|
38 | UDR2 = color_b.white;
|
39 | u2_crc_c ^= color_b.white;
|
40 |
|
41 | while (!(UCSR2A & (1<<UDRE2))) {}
|
42 | UDR2 = (BYTE) (symbol[symbolnr][adr_count-1]);
|
43 | u2_crc_c ^= (BYTE) (symbol[symbolnr][adr_count-1]);
|
44 | while (!(UCSR2A & (1<<UDRE2))) {}
|
45 | UDR2 = (BYTE) (symbol[symbolnr][adr_count-1] >> 8);
|
46 | u2_crc_c ^= (BYTE) (symbol[symbolnr][adr_count-1] >> 8);
|
47 | while (!(UCSR2A & (1<<UDRE2))) {}
|
48 | UDR2 = (BYTE) (symbol[symbolnr][adr_count-1] >> 16);
|
49 | u2_crc_c ^= (BYTE) (symbol[symbolnr][adr_count-1] >> 16);
|
50 |
|
51 | while (!(UCSR2A & (1<<UDRE2))) {}
|
52 | UDR2 = u2_crc_c;
|
53 |
|
54 | for(u2_count = 0; u2_count<200; u2_count++); // wait 200u
|
55 | }
|
56 |
|
57 | return(0x02);
|
58 | }
|
Unterprogrammaufruf Disassemblerwindow:
1 | 289: DmxAddress = DmxAddress; // für Breakpoint setzen
|
2 | +0000062C: 91800614 LDS R24,0x0614 Load direct from data space
|
3 | +0000062E: 91900615 LDS R25,0x0615 Load direct from data space
|
4 | +00000630: 93900615 STS 0x0615,R25 Store direct to data space
|
5 | +00000632: 93800614 STS 0x0614,R24 Store direct to data space
|
6 | 290: uart2_s_pro3(0x00); // Symbol für Karomuster
|
7 | +00000634: E080 LDI R24,0x00 Load immediate
|
8 | +00000635: 940E01A4 CALL 0x000001A4 Call subroutine
|
9 | 293: sei();
|
10 |
|
11 | {
|
Start der Funktion uart2_s_pro3(BYTE). 10xpush
1 | +000001A4: 92AF PUSH R10 Push register on stack
|
2 | +000001A5: 92BF PUSH R11 Push register on stack
|
3 | +000001A6: 92CF PUSH R12 Push register on stack
|
4 | +000001A7: 92DF PUSH R13 Push register on stack
|
5 | +000001A8: 92EF PUSH R14 Push register on stack
|
6 | +000001A9: 92FF PUSH R15 Push register on stack
|
7 | +000001AA: 930F PUSH R16 Push register on stack
|
8 | +000001AB: 931F PUSH R17 Push register on stack
|
9 | +000001AC: 93DF PUSH R29 Push register on stack
|
10 | +000001AD: 93CF PUSH R28 Push register on stack
|
Im Disassemblerwindow sieht der Return-Teil so aus (13x pop?!)
1 | : for(adr_count = 1; adr_count <= 7; adr_count++)
|
2 | +000002DA: 8189 LDD R24,Y+1 Load indirect with displacement
|
3 | +000002DB: 5F8F SUBI R24,0xFF Subtract immediate
|
4 | +000002DC: 8389 STD Y+1,R24 Store indirect with displacement
|
5 | +000002DD: 8189 LDD R24,Y+1 Load indirect with displacement
|
6 | +000002DE: 3088 CPI R24,0x08 Compare with immediate
|
7 | +000002DF: F408 BRCC PC+0x02 Branch if carry cleared
|
8 | +000002E0: CEF4 RJMP PC-0x010B Relative jump
|
9 | 144: }
|
10 | +000002E1: E082 LDI R24,0x02 Load immediate
|
11 | +000002E2: 900F POP R0 Pop register from stack
|
12 | +000002E3: 900F POP R0 Pop register from stack
|
13 | +000002E4: 900F POP R0 Pop register from stack
|
14 | +000002E5: 91CF POP R28 Pop register from stack
|
15 | +000002E6: 91DF POP R29 Pop register from stack
|
16 | +000002E7: 911F POP R17 Pop register from stack
|
17 | +000002E8: 910F POP R16 Pop register from stack
|
18 | +000002E9: 90FF POP R15 Pop register from stack
|
19 | +000002EA: 90EF POP R14 Pop register from stack
|
20 | +000002EB: 90DF POP R13 Pop register from stack
|
21 | +000002EC: 90CF POP R12 Pop register from stack
|
22 | +000002ED: 90BF POP R11 Pop register from stack
|
23 | +000002EE: 90AF POP R10 Pop register from stack
|
24 | +000002EF: 9508 RET Subroutine return
|
Diverse Optimierungsparameter hab ich durchprobiert, immer das selbe
Problem. Auffällig ist, dass der Stackpointer zum Zeitpunkt des
Programmaufrufs bei 0x21F0 ist. Ziemlich hoch oder?
Hat jemand eine Ahnung?
Danke
Thomas