Forum: Mikrocontroller und Digitale Elektronik Atmega88 Code kompiliert ohne Fehler und läuft nicht


von Udo F. (utm)


Lesenswert?

Nabend zusammen,

habe endlich mein Mini-Beispiel für eine funktionierende USART 
Schnittstelle hinbekommen.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define BAUD 9600UL
5
#define UBRR_VALUE ((F_CPU+BAUD*8)/(BAUD*16)-1)
6
#define BAUD_REAL (F_CPU/(16*(UBRR_VALUE+1)))
7
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
8
9
int main( void ){
10
    if ((BAUD_REAL < 990)||(BAUD_ERROR > 1010)){
11
        DDRD |= (1<<PD6);
12
        PORTD |= (1<<PD6);
13
    }
14
15
    UBRR0H = (uint8_t)(UBRR_VALUE >> 8);
16
    UBRR0L = (uint8_t)UBRR_VALUE;
17
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
18
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
19
20
    while(1){
21
        UDR0 = 'B';
22
        _delay_ms(2000);
23
    }   
24
}

Funktioniert und macht genau das was es soll. Ich verwende hier einen 
sh-u09c5 zum Lesen.

Jetzt wollte ich das Ganze natürlich erweitern auf Strings und habe 
folgende Funktionen hinzugefügt:
1
int uart_putc(unsigned char c);
2
void uart_puts(char *s);
3
4
int uart_putc(unsigned char c)
5
{
6
    return 0;
7
}
8
9
void uart_puts (char *s)
10
{
11
    while (*s)
12
    {
13
        uart_putc(*s);
14
        s++;
15
    }
16
}
Es kompiliert-ich bekomme per avrdude keine Fehler o.Ä. Aber es wird 
nichts mehr gesendet. Ich rufe beide Funktionen nicht einmal auf und 
dennoch macht es irgendwie alles kaputt.
Wenn ich die beiden Funktionen lösche und den Atmega erneut bespiele 
klappt alles wieder wunderbar. Ich kann es mir absolut nicht erklären. 
Ich hoffe ihr könnt mir einen Tipp geben.

von pnp (Gast)


Lesenswert?

Schau dir mal genau an, was putc() macht :-)

von Udo F. (utm)


Lesenswert?

pnp schrieb:
> Schau dir mal genau an, was putc() macht :-)

In meinem Fall macht es natürlich nichts außer direkt raus zu springen 
aber das ist ja nur dafür gedacht um zu zeigen, dass der eigentliche 
Code nicht mehr funktioniert obwohl doch die Funktionen nirgendwo 
aufgerufen werden.

Ich hatte das aus dem Tutorial: 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Senden_einer_Zeichenkette_.28String.29 
und die Funktionen sahen vorher so aus:
1
int uart_putc(unsigned char c)
2
{
3
    while (!(UCSR0A & (1<<UDRE0))){}
4
    UDR0 = c;
5
    return 0;
6
}
7
8
9
void uart_puts (char *s)
10
{
11
    while (*s)
12
    {   
13
        uart_putc(*s);
14
        s++;
15
    }
16
}
Da dies aber zum selben Ergebnis führte - nämlich dass nichts mehr 
gesendet wird (obwohl beide Funktionen erneut nirgendwo aufgerufen 
wurden) - habe ich die while Schleife aus uart_putc entfernt. Ich 
dachte, dass ich irgendwas mit UCSR0A oder UDRE0 falsch mache und habs 
dann auf das nötigste reduziert.

von MaWin (Gast)


Lesenswert?

Bitte komplettes Projekt geben. Im gezeigten Code ist kein Fehler. Er 
muss also woanders liegen.

von Udo F. (utm)


Lesenswert?

Sehr gerne
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define BAUD 9600UL                  
5
#define UBRR_VALUE ((F_CPU+BAUD*8)/(BAUD*16)-1)
6
#define BAUD_REAL (F_CPU/(16*(UBRR_VALUE+1)))
7
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
8
#define TX_BUFFER_SIZE 128
9
 
10
int uart_putc(unsigned char c);
11
void uaart_puts(char *s);
12
13
int main( void )
14
{
15
    if ((BAUD_REAL < 990)||(BAUD_ERROR > 1010)){
16
        DDRD |= (1<<PD6);
17
        PORTD |= (1<<PD6);
18
    }
19
20
    UBRR0H = (uint8_t)(UBRR_VALUE >> 8);       
21
    UBRR0L = (uint8_t)UBRR_VALUE;            
22
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);  
23
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
24
25
    while(1){
26
        UDR0 = 'B';
27
  _delay_ms(2000);
28
    }
29
    
30
}
31
int uart_putc(unsigned char c)
32
{
33
    return 0;
34
}
35
36
void uart_puts (char *s)
37
{
38
    while (*s)
39
    {
40
        uart_putc(*s);
41
        s++;
42
    }
43
}
Filename uart_verysimple.c
1
avr-gcc -mmcu=atmega88a -Wall -Os -DF_CPU=8000000UL -c uart_verysimple.c -o uart_verysimple.o;
2
avr-gcc uart_verysimple.o -o uart_verysimple.elf;
3
avr-objcopy -O ihex -j .text -j .data uart_verysimple.elf uart_verysimple.hex;
4
avrdude -c usbasp -pm88 -U flash:w:uart_verysimple.hex:a;
ckdiv8 Bit ist ausgeschaltet (auf 1 gesetzt)

von Thomas F. (igel)


Lesenswert?

Vergleich mal Zeile 11 mit Zeile 36.

von Hugo H. (hugohurtig1)


Lesenswert?

Thomas F. schrieb:
> Vergleich mal Zeile 11 mit Zeile 36.

Ja - und praktisch ist auch immer, wenn man Funktionen, die ausgeführt 
werden sollen, (aus MAIN heraus) aufruft :-)

Dann funktioniert das Beispiel auch ...

Nicht genutzter Code / Variablen werden nicht compiliert - macht ja auch 
wenig Sinn.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Thomas F. schrieb:
> Vergleich mal Zeile 11 mit Zeile 36.
Im obigen Original war das noch anders.
Ja, da wäre es manchmal sinnvoller, einfach die *.c Datei anzuhängen...

Udo F. schrieb:
> Sehr gerne
Und was tut jetzt der Code? Oder was erwartest du dass der tut?

Udo F. schrieb:
> habe ich die while Schleife aus uart_putc entfernt. Ich dachte, dass ich
> irgendwas mit UCSR0A oder UDRE0 falsch mache und habs dann auf das nötigste
> reduziert.
Genau das, was du da entfernt hast, ist "das Nötigste", denn diese Zeile 
sorgt dafür, dass der UART nicht einfach überfahren, sondern die 
Übertragung jedes einzelnen Bytes abgewartet wird.
In dem ganz Code vom ersten Post übernimmt das Delay das Abwarten auf 
das Freiwerden des UART-TX-Registers.

von Udo F. (utm)


Lesenswert?

Thomas F. schrieb:
> Vergleich mal Zeile 11 mit Zeile 36.

Sorry das ist nur ein Typo. Die Namen der Funktionen stimmen überein.

: Bearbeitet durch User
von Udo F. (utm)


Lesenswert?

Hugo H. schrieb:
> Thomas F. schrieb:
>> Vergleich mal Zeile 11 mit Zeile 36.
>
> Ja - und praktisch ist auch immer, wenn man Funktionen, die ausgeführt
> werden sollen, (aus MAIN heraus) aufruft :-)
>
> Dann funktioniert das Beispiel auch ...
>
> Nicht genutzter Code / Variablen werden nicht compiliert - macht ja auch
> wenig Sinn.

Nein weil genau das will ich ja damit zeigen. Es gibt Funktionen, die 
eben nicht aufgerufen werden und es aber nicht mehr funktioniert.
Ich erwarte doch, dass wenn ich Code habe, der nicht aufgerufen wird, 
somit nicht compiliert wird, keine Änderung im Programm bewirkt.
Ohne die beiden uart Funktionen wird alle 2 Sekunden ein B geschrieben 
was ich auch mittels sh-u09c5 und hterm lesen/sehen kann.
Mit diesen Funktionen, die ja nichts machen und auch nicht aufgerufen 
werden wird nichts mehr vom Controller geschickt. Obwohl die main ja 
unangetastet ist.

von Hugo H. (hugohurtig1)


Lesenswert?

Udo F. schrieb:
> Es gibt Funktionen, die
> eben nicht aufgerufen werden und es aber nicht mehr funktioniert.

Nach Änderung mit den unsinnigen Funktionen:
1
uart.elf:     file format elf32-avr
2
3
Sections:
4
Idx Name          Size      VMA       LMA       File off  Algn
5
  0 .data         00000000  00800100  00800100  000000d0  2**0
6
                  CONTENTS, ALLOC, LOAD, DATA
7
  1 .text         0000007c  00000000  00000000  00000054  2**1
8
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
9
  2 .comment      00000030  00000000  00000000  000000d0  2**0
10
                  CONTENTS, READONLY
11
  3 .note.gnu.avr.deviceinfo 0000003c  00000000  00000000  00000100  2**2
12
                  CONTENTS, READONLY
13
  4 .debug_aranges 00000030  00000000  00000000  0000013c  2**0
14
                  CONTENTS, READONLY, DEBUGGING
15
  5 .debug_info   00000764  00000000  00000000  0000016c  2**0
16
                  CONTENTS, READONLY, DEBUGGING
17
  6 .debug_abbrev 000006b7  00000000  00000000  000008d0  2**0
18
                  CONTENTS, READONLY, DEBUGGING
19
  7 .debug_line   0000029a  00000000  00000000  00000f87  2**0
20
                  CONTENTS, READONLY, DEBUGGING
21
  8 .debug_frame  00000044  00000000  00000000  00001224  2**2
22
                  CONTENTS, READONLY, DEBUGGING
23
  9 .debug_str    00000388  00000000  00000000  00001268  2**0
24
                  CONTENTS, READONLY, DEBUGGING
25
 10 .debug_loc    00000056  00000000  00000000  000015f0  2**0
26
                  CONTENTS, READONLY, DEBUGGING
27
 11 .debug_ranges 00000020  00000000  00000000  00001646  2**0
28
                  CONTENTS, READONLY, DEBUGGING
29
30
Disassembly of section .text:
31
32
00000000 <__vectors>:
33
   0:  19 c0         rjmp  .+50       ; 0x34 <__ctors_end>
34
   2:  20 c0         rjmp  .+64       ; 0x44 <__bad_interrupt>
35
   4:  1f c0         rjmp  .+62       ; 0x44 <__bad_interrupt>
36
   6:  1e c0         rjmp  .+60       ; 0x44 <__bad_interrupt>
37
   8:  1d c0         rjmp  .+58       ; 0x44 <__bad_interrupt>
38
   a:  1c c0         rjmp  .+56       ; 0x44 <__bad_interrupt>
39
   c:  1b c0         rjmp  .+54       ; 0x44 <__bad_interrupt>
40
   e:  1a c0         rjmp  .+52       ; 0x44 <__bad_interrupt>
41
  10:  19 c0         rjmp  .+50       ; 0x44 <__bad_interrupt>
42
  12:  18 c0         rjmp  .+48       ; 0x44 <__bad_interrupt>
43
  14:  17 c0         rjmp  .+46       ; 0x44 <__bad_interrupt>
44
  16:  16 c0         rjmp  .+44       ; 0x44 <__bad_interrupt>
45
  18:  15 c0         rjmp  .+42       ; 0x44 <__bad_interrupt>
46
  1a:  14 c0         rjmp  .+40       ; 0x44 <__bad_interrupt>
47
  1c:  13 c0         rjmp  .+38       ; 0x44 <__bad_interrupt>
48
  1e:  12 c0         rjmp  .+36       ; 0x44 <__bad_interrupt>
49
  20:  11 c0         rjmp  .+34       ; 0x44 <__bad_interrupt>
50
  22:  10 c0         rjmp  .+32       ; 0x44 <__bad_interrupt>
51
  24:  0f c0         rjmp  .+30       ; 0x44 <__bad_interrupt>
52
  26:  0e c0         rjmp  .+28       ; 0x44 <__bad_interrupt>
53
  28:  0d c0         rjmp  .+26       ; 0x44 <__bad_interrupt>
54
  2a:  0c c0         rjmp  .+24       ; 0x44 <__bad_interrupt>
55
  2c:  0b c0         rjmp  .+22       ; 0x44 <__bad_interrupt>
56
  2e:  0a c0         rjmp  .+20       ; 0x44 <__bad_interrupt>
57
  30:  09 c0         rjmp  .+18       ; 0x44 <__bad_interrupt>
58
  32:  08 c0         rjmp  .+16       ; 0x44 <__bad_interrupt>
59
60
00000034 <__ctors_end>:
61
  34:  11 24         eor  r1, r1
62
  36:  1f be         out  0x3f, r1  ; 63
63
  38:  cf ef         ldi  r28, 0xFF  ; 255
64
  3a:  d4 e0         ldi  r29, 0x04  ; 4
65
  3c:  de bf         out  0x3e, r29  ; 62
66
  3e:  cd bf         out  0x3d, r28  ; 61
67
  40:  02 d0         rcall  .+4        ; 0x46 <main>
68
  42:  1a c0         rjmp  .+52       ; 0x78 <_exit>
69
70
00000044 <__bad_interrupt>:
71
  44:  dd cf         rjmp  .-70       ; 0x0 <__vectors>
72
73
00000046 <main>:
74
{
75
  if ((BAUD_REAL < 990)||(BAUD_ERROR > 1010)){
76
    DDRD |= (1<<PD6);
77
    PORTD |= (1<<PD6);
78
  }
79
  UBRR0H = (uint8_t)(UBRR_VALUE >> 8);
80
  46:  10 92 c5 00   sts  0x00C5, r1  ; 0x8000c5 <__TEXT_REGION_LENGTH__+0x7fe0c5>
81
  UBRR0L = (uint8_t)UBRR_VALUE;
82
  4a:  83 e3         ldi  r24, 0x33  ; 51
83
  4c:  80 93 c4 00   sts  0x00C4, r24  ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7fe0c4>
84
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
85
  50:  86 e0         ldi  r24, 0x06  ; 6
86
  52:  80 93 c2 00   sts  0x00C2, r24  ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7fe0c2>
87
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
88
  56:  88 e1         ldi  r24, 0x18  ; 24
89
  58:  80 93 c1 00   sts  0x00C1, r24  ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7fe0c1>
90
  while(1){
91
    UDR0 = 'B';
92
  5c:  e6 ec         ldi  r30, 0xC6  ; 198
93
  5e:  f0 e0         ldi  r31, 0x00  ; 0
94
  60:  82 e4         ldi  r24, 0x42  ; 66
95
  62:  80 83         st  Z, r24
96
  #else
97
    //round up by default
98
    __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
99
  #endif
100
101
  __builtin_avr_delay_cycles(__ticks_dc);
102
  64:  2f ef         ldi  r18, 0xFF  ; 255
103
  66:  33 ed         ldi  r19, 0xD3  ; 211
104
  68:  90 e3         ldi  r25, 0x30  ; 48
105
  6a:  21 50         subi  r18, 0x01  ; 1
106
  6c:  30 40         sbci  r19, 0x00  ; 0
107
  6e:  90 40         sbci  r25, 0x00  ; 0
108
  70:  e1 f7         brne  .-8        ; 0x6a <main+0x24>
109
  72:  00 c0         rjmp  .+0        ; 0x74 <main+0x2e>
110
  74:  00 00         nop
111
  76:  f5 cf         rjmp  .-22       ; 0x62 <main+0x1c>
112
113
00000078 <_exit>:
114
  78:  f8 94         cli
115
116
0000007a <__stop_program>:
117
  7a:  ff cf         rjmp  .-2        ; 0x7a <__stop_program>

Vor Änderung (die Funktionen entfernt):
1
uart.elf:     file format elf32-avr
2
3
Sections:
4
Idx Name          Size      VMA       LMA       File off  Algn
5
  0 .data         00000000  00800100  00800100  000000d0  2**0
6
                  CONTENTS, ALLOC, LOAD, DATA
7
  1 .text         0000007c  00000000  00000000  00000054  2**1
8
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
9
  2 .comment      00000030  00000000  00000000  000000d0  2**0
10
                  CONTENTS, READONLY
11
  3 .note.gnu.avr.deviceinfo 0000003c  00000000  00000000  00000100  2**2
12
                  CONTENTS, READONLY
13
  4 .debug_aranges 00000020  00000000  00000000  0000013c  2**0
14
                  CONTENTS, READONLY, DEBUGGING
15
  5 .debug_info   000006ff  00000000  00000000  0000015c  2**0
16
                  CONTENTS, READONLY, DEBUGGING
17
  6 .debug_abbrev 00000667  00000000  00000000  0000085b  2**0
18
                  CONTENTS, READONLY, DEBUGGING
19
  7 .debug_line   0000026e  00000000  00000000  00000ec2  2**0
20
                  CONTENTS, READONLY, DEBUGGING
21
  8 .debug_frame  00000024  00000000  00000000  00001130  2**2
22
                  CONTENTS, READONLY, DEBUGGING
23
  9 .debug_str    00000374  00000000  00000000  00001154  2**0
24
                  CONTENTS, READONLY, DEBUGGING
25
 10 .debug_ranges 00000010  00000000  00000000  000014c8  2**0
26
                  CONTENTS, READONLY, DEBUGGING
27
28
Disassembly of section .text:
29
30
00000000 <__vectors>:
31
   0:  19 c0         rjmp  .+50       ; 0x34 <__ctors_end>
32
   2:  20 c0         rjmp  .+64       ; 0x44 <__bad_interrupt>
33
   4:  1f c0         rjmp  .+62       ; 0x44 <__bad_interrupt>
34
   6:  1e c0         rjmp  .+60       ; 0x44 <__bad_interrupt>
35
   8:  1d c0         rjmp  .+58       ; 0x44 <__bad_interrupt>
36
   a:  1c c0         rjmp  .+56       ; 0x44 <__bad_interrupt>
37
   c:  1b c0         rjmp  .+54       ; 0x44 <__bad_interrupt>
38
   e:  1a c0         rjmp  .+52       ; 0x44 <__bad_interrupt>
39
  10:  19 c0         rjmp  .+50       ; 0x44 <__bad_interrupt>
40
  12:  18 c0         rjmp  .+48       ; 0x44 <__bad_interrupt>
41
  14:  17 c0         rjmp  .+46       ; 0x44 <__bad_interrupt>
42
  16:  16 c0         rjmp  .+44       ; 0x44 <__bad_interrupt>
43
  18:  15 c0         rjmp  .+42       ; 0x44 <__bad_interrupt>
44
  1a:  14 c0         rjmp  .+40       ; 0x44 <__bad_interrupt>
45
  1c:  13 c0         rjmp  .+38       ; 0x44 <__bad_interrupt>
46
  1e:  12 c0         rjmp  .+36       ; 0x44 <__bad_interrupt>
47
  20:  11 c0         rjmp  .+34       ; 0x44 <__bad_interrupt>
48
  22:  10 c0         rjmp  .+32       ; 0x44 <__bad_interrupt>
49
  24:  0f c0         rjmp  .+30       ; 0x44 <__bad_interrupt>
50
  26:  0e c0         rjmp  .+28       ; 0x44 <__bad_interrupt>
51
  28:  0d c0         rjmp  .+26       ; 0x44 <__bad_interrupt>
52
  2a:  0c c0         rjmp  .+24       ; 0x44 <__bad_interrupt>
53
  2c:  0b c0         rjmp  .+22       ; 0x44 <__bad_interrupt>
54
  2e:  0a c0         rjmp  .+20       ; 0x44 <__bad_interrupt>
55
  30:  09 c0         rjmp  .+18       ; 0x44 <__bad_interrupt>
56
  32:  08 c0         rjmp  .+16       ; 0x44 <__bad_interrupt>
57
58
00000034 <__ctors_end>:
59
  34:  11 24         eor  r1, r1
60
  36:  1f be         out  0x3f, r1  ; 63
61
  38:  cf ef         ldi  r28, 0xFF  ; 255
62
  3a:  d4 e0         ldi  r29, 0x04  ; 4
63
  3c:  de bf         out  0x3e, r29  ; 62
64
  3e:  cd bf         out  0x3d, r28  ; 61
65
  40:  02 d0         rcall  .+4        ; 0x46 <main>
66
  42:  1a c0         rjmp  .+52       ; 0x78 <_exit>
67
68
00000044 <__bad_interrupt>:
69
  44:  dd cf         rjmp  .-70       ; 0x0 <__vectors>
70
71
00000046 <main>:
72
{
73
  if ((BAUD_REAL < 990)||(BAUD_ERROR > 1010)){
74
    DDRD |= (1<<PD6);
75
    PORTD |= (1<<PD6);
76
  }
77
  UBRR0H = (uint8_t)(UBRR_VALUE >> 8);
78
  46:  10 92 c5 00   sts  0x00C5, r1  ; 0x8000c5 <__TEXT_REGION_LENGTH__+0x7fe0c5>
79
  UBRR0L = (uint8_t)UBRR_VALUE;
80
  4a:  83 e3         ldi  r24, 0x33  ; 51
81
  4c:  80 93 c4 00   sts  0x00C4, r24  ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7fe0c4>
82
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
83
  50:  86 e0         ldi  r24, 0x06  ; 6
84
  52:  80 93 c2 00   sts  0x00C2, r24  ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7fe0c2>
85
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
86
  56:  88 e1         ldi  r24, 0x18  ; 24
87
  58:  80 93 c1 00   sts  0x00C1, r24  ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7fe0c1>
88
  while(1){
89
    UDR0 = 'B';
90
  5c:  e6 ec         ldi  r30, 0xC6  ; 198
91
  5e:  f0 e0         ldi  r31, 0x00  ; 0
92
  60:  82 e4         ldi  r24, 0x42  ; 66
93
  62:  80 83         st  Z, r24
94
  #else
95
    //round up by default
96
    __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
97
  #endif
98
99
  __builtin_avr_delay_cycles(__ticks_dc);
100
  64:  2f ef         ldi  r18, 0xFF  ; 255
101
  66:  33 ed         ldi  r19, 0xD3  ; 211
102
  68:  90 e3         ldi  r25, 0x30  ; 48
103
  6a:  21 50         subi  r18, 0x01  ; 1
104
  6c:  30 40         sbci  r19, 0x00  ; 0
105
  6e:  90 40         sbci  r25, 0x00  ; 0
106
  70:  e1 f7         brne  .-8        ; 0x6a <main+0x24>
107
  72:  00 c0         rjmp  .+0        ; 0x74 <main+0x2e>
108
  74:  00 00         nop
109
  76:  f5 cf         rjmp  .-22       ; 0x62 <main+0x1c>
110
111
00000078 <_exit>:
112
  78:  f8 94         cli
113
114
0000007a <__stop_program>:
115
  7a:  ff cf         rjmp  .-2        ; 0x7a <__stop_program>

Zeige mir bitte den Unterschied (außer den Debug-Angaben) - es gibt 
keinen. Du zeigst schlicht nicht alles und damit brauchst Du scheinbar 
auch keine Hilfe.

von Udo F. (utm)


Angehängte Dateien:

Lesenswert?

Stimmt. Ich verheimliche bei meinem geheimen, komplexen Programm teile 
damit ihr die bloß nicht seht.

Ich bin Anfänger in Mikrokontroller-Entwicklung und komme nicht weiter. 
Ich kenne mich mit höheren Sprachen wir Java etc. aus aber eben nicht 
mit so low level Programmierung. Und deshalb ist ja meine Verwunderung 
so groß, dass Funktionen, die nichts machen, nicht aufgerufen werden, 
dennoch alles kaputt machen.

Es gibt exakt eine c-Datei, die ihr inzwischen vollständig habt.
Dazu gibt es die 4 Zeilen, mit denen ich den Code auf den Atmega88A 
bespiele. Das wars. Mehr ist nicht.

Ich glaube dir ja, dass, nachdem du das File analysiert hast, es keine 
Unterschiede gibt, aber dann kannst du mir doch auch glauben, dass ich 
nichts "verstecke".

Meiner Meinung nach kann es ja dann nur am Atmega88 liegen. Ich habe 
hier nochmal den output von avrdude als Anhang mitgegeben. Keine Ahnung 
ob das weiter hilft.

von Hugo H. (hugohurtig1)


Lesenswert?

Udo F. schrieb:
> Meiner Meinung nach kann es ja dann nur am Atmega88 liegen.

Meiner Meinung nach liegt es an Dir und Du nimmst Du das falsche 
Hex-File

"avrdude: writing flash (66 bytes)"

Wenn ich compiliere komme ich auf

"Program Memory Usage   :  124 bytes   1,5 % Full"

Mit _delay... kann es nicht so kurz (66 bytes) sein (Meiner Meinung 
nach).

: Bearbeitet durch User
von Udo F. (utm)


Lesenswert?

Danke für den Hinweis. Werds heut Abend ausprobieren und hoffentlich 
etwas herausfinden.

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> "Program Memory Usage   :  124 bytes   1,5 % Full"
> Mit _delay... kann es nicht so kurz (66 bytes) sein (Meiner Meinung
> nach).

Das Assembler Listing endet bei 0x7a (=122) mit 2 Bytes, kommt also hin. 
Da ist das delay auch drin. Die 124 sind alle belegt, da kann es nicht 
in Ordnung sein, dass er nur 66 Bytes davon in den Flash schreibt.

Ich würde da mal weiter nachforschen, bin ziemlich sicher dass Hugo es 
auf den Punkt gebracht hat.

Die Berechnung der Baudrate überlässt man normalerweise der AVR 
Bibliothek 
https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html

von Andreas B. (bitverdreher)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich würde da mal weiter nachforschen, bin ziemlich sicher dass Hugo es
> auf den Punkt gebracht hat.
Dazu wäre auch mal interessant wie das compiliert wurde.
Makefile?
Und auch wie avrdude aufgerufen wurde.
Da fehlt das Ganze drumherum.

von Udo F. (utm)


Lesenswert?

Andreas B. schrieb:
> Dazu wäre auch mal interessant wie das compiliert wurde.
> Makefile?
> Und auch wie avrdude aufgerufen wurde.
> Da fehlt das Ganze drumherum.
Das hatte ich bereits geschrieben:
1
avr-gcc -mmcu=atmega88a -Wall -Os -DF_CPU=8000000UL -c uart_verysimple.c -o uart_verysimple.o;
2
avr-gcc uart_verysimple.o -o uart_verysimple.elf;
3
avr-objcopy -O ihex -j .text -j .data uart_verysimple.elf uart_verysimple.hex;
4
avrdude -c usbasp -pm88 -U flash:w:uart_verysimple.hex:a;

Das ganze ist in einem Bash-Skript und wird einfach mittels: 
./doStuff.sh ausgeführt. Es ist somit kein wirkliches Makefile

von Andreas B. (bitverdreher)


Lesenswert?

Laß hier mal:
avrdude -c usbasp -pm88 -U flash:w:uart_verysimple.hex:a;
das :a am Schluß weg.

von Udo F. (utm)


Lesenswert?

Andreas B. schrieb:
> Laß hier mal:
> avrdude -c usbasp -pm88 -U flash:w:uart_verysimple.hex:a;
> das :a am Schluß weg.

Hab ich. Leider selbes Ergebnis.

Bzgl. der Anzahl der Bytes (von weiter oben). Ich habe mal die beiden 
Funktionen entfernt und mit/ohne :a den Chip bespielt.
In beiden Fällen läuft der Code wie geplant und avrdude sagt mir, dass 
er 48 Bytes geschrieben hat. Mit den Funktionen sind es 66.

von Stefan F. (Gast)


Lesenswert?

Udo F. schrieb:
> In beiden Fällen läuft der Code wie geplant und avrdude sagt mir, dass
> er 48 Bytes geschrieben hat. Mit den Funktionen sind es 66.

Dass der Maschinencode eine andere Größe hat als bei Hugo mag an den 
Compiler Optionen oder der Version liegen.

Bei dir werden die unbenutzten Funktionen offenbar nicht entfernt. Ich 
denke das liegt daran, dass du die sonst üblichen Compiler-und Linker 
Flags nicht verwendet hast. In meinem Makefile sind es diese
1
FLAGS += -ffunction-sections -fdata-sections
2
LDFLAGS += -Wl,--gc-sections

Das erklärt aber noch nicht, warum die größere Datei mit den ungenutzten 
Funktionen nicht funktioniert. Kannst du mal das Assembler-Listing 
zeigen, dass dein Rechner generiert (sie wie Hugo oben seins gezeigt 
hat)?

von Hugo H. (hugohurtig1)


Lesenswert?

Udo F. schrieb:
> Mit den Funktionen sind es 66

Selbst wenn ich "Optimize most" einstelle - -O3 - sind es immer noch 122 
Bytes. Daher gehe ich immer noch davon aus, dass Du das falsche 
.HEX-File flasht.

Zeige doch bitte mal die Compiler-Meldungen und das .LSS-File.

von Udo F. (utm)


Angehängte Dateien:

Lesenswert?

Habe es so kompiliert:
1
avr-gcc -mmcu=atmega88a -Wall -Os -DF_CPU=8000000UL -c uart_verysimple.c -S

von Hugo H. (hugohurtig1)


Lesenswert?

Udo F. schrieb:
> Habe es so kompiliert:

Und wo bitte sind die Compiler-Meldungen?

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Selbst wenn ich "Optimize most" einstelle - -O3 - sind es immer noch 122
> Bytes.

Kein Wunder. -O3 optimiert für maximale Performance auf Kosten der 
Programmgröße.

Wenn du es möglichst klein haben willst, musst du -Os verwenden, wie Udo 
es getan hat.

von Stefan F. (Gast)


Lesenswert?

Udo F. schrieb:
> Habe es so kompiliert

Leider stehen in dem Listing nicht die Adressen. Aber ich sehe da 
ungefähr 25 Befehle. Die meisten brauchen 2 Bytes, dazu kommt noch die 
Interrupt-Tabelle. Da sind die 66 also schon plausibel.

Das bringt mich aber auf eine Idee: Woher weiß der Linker, wie viel 
Platz er für die Interrupt-Tabelle reservieren muss, obwohl sie nicht im 
Assember Listing enthalten ist?

Kann es sein, dass du beim Linken
> avr-gcc uart_verysimple.o -o uart_verysimple.elf;
den µC Typ angeben musst? Ich mache das jedenfalls immer in meinem 
Makefile.

Vielleicht profitierst du auch davon, ein erprobtes Makefile zu 
benutzen. Meine persönliche Kopiervorlage findest du dort: 
http://stefanfrings.de/avr_hello_world/index.html

von Hugo H. (hugohurtig1)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Kein Wunder. -O3 optimiert für maximale Performance auf Kosten der
> Programmgröße.

Das spielt bei dem Mickey-Maus-Programm überhaupt keine Geige.

von Udo F. (utm)


Lesenswert?

Stefan ⛄ F. schrieb:
> Vielleicht profitierst du auch davon, ein erprobtes Makefile zu
> benutzen. Meine persönliche Kopiervorlage findest du dort:
> http://stefanfrings.de/avr_hello_world/index.html

Genau die Idee kam mir vor 10 Min. auch und .... es funktioniert. Ich 
fass es nicht!!!

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> dazu kommt noch die
> Interrupt-Tabelle. Da sind die 66 also schon plausibel

Wie lang ist denn die Interrupt-Tabelle?

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Das spielt bei dem Mickey-Maus-Programm überhaupt keine Geige.

Dann ist es wohl fehlerhaft gelinkt worden.

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Wie lang ist denn die Interrupt-Tabelle?

Schau in dein eigenes Listing:
1
00000000 <__vectors>:
2
   0:  19 c0         rjmp  .+50       ; 0x34 <__ctors_end>
3
   2:  20 c0         rjmp  .+64       ; 0x44 <__bad_interrupt>
4
   ...
5
  32:  08 c0         rjmp  .+16       ; 0x44 <__bad_interrupt>

Sieht nach 64 Bytes aus.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Sieht nach 64 Bytes aus.

Stefan ⛄ F. schrieb:
> Da sind die 66 also schon plausibel

Gut dann ist in den verbliebenen 2 Bytes der komplette Code versteckt. 
Das möchte ich auch können - wie geht das?

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Gut dann ist in den verbliebenen 2 Bytes der komplette Code versteckt.
> Das möchte ich auch können - wie geht das?

Quatsch

Die Interrupt-Tabelle hat 64 Bytes.
Der Programmcode hat 66 Bytes.

macht zusammen ungefähr die 124 bytes, die bei dir als
> "Program Memory Usage   :  124 bytes   1,5 % Full"
gemeldet wurden.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Quatsch
>
> Die Interrupt-Tabelle hat 64 Bytes.
> Der Programmcode hat 66 Bytes.
>
> macht zusammen ungefähr die 124 bytes, die bei dir als
>> "Program Memory Usage   :  124 bytes   1,5 % Full"
> gemeldet wurden.

Und was schiebt AVR-Dude auf den Controller? Nur den Programmcode? 
Spielt die Interrupt-Tabelle keine Rolle? Erhält der MC diese intuitiv?

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Und was schiebt AVR-Dude auf den Controller? Nur den Programmcode?

Das komplette gelinkte Programm, samt Interrupt Tabelle und 
Initialisierungs-Daten für Variablen (falls vorhanden).

> Spielt die Interrupt-Tabelle keine Rolle?

Ich habe dir doch gerade vorgerechnet, dass der Programmcode + 
Interrupt-Tabelle zusammen die gesamt-Größe ausmachen, die in den Flash 
übertragen werden müssen.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich habe dir doch gerade vorgerechnet, dass der Programmcode +
> Interrupt-Tabelle zusammen die gesamt-Größe ausmachen, die in den Flash
> übertragen werden müssen.

Und warum sind dann die 66 übertragenen Bytes plausibel? Addieren ist 
Dir bekannt?

Du hättest Politiker werden sollen - vielleicht sucht Armin ja noch 
Helfer :-)

Ich glaube, Du wohnst sogar in der Ecke - oder? Dann passt es ja.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Und warum sind dann die 66 übertragenen Bytes plausibel?

Weil er falsch (ohne Interrupt Vektoren) gelinkt hat. Ohne Interrupt 
Vektoren flasht er nur den Programmcode und der umfasst halt die 66 
Bytes.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Weil er falsch (ohne Interrupt Vektoren) gelinkt hat. Ohne Interrupt
> Vektoren flasht er nur den Programmcode und der umfasst halt die 66
> Bytes.

Ja - also nicht plausibel. Kannst Du es nicht zugeben, wenn Du Müll 
erzählt hast?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Hugo, ich weiß nicht was das werden soll. Entweder tust du so doof um 
mich zu ärgern, oder du versteht es wirklich nicht. Es hat keinen Sinn 
darauf weiter einzugehen.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan ⛄ F. schrieb:
> Hugo, ich weiß nicht was das werden soll. Entweder tust du so doof um
> mich zu ärgern, oder du versteht es wirklich nicht. Es hat keinen Sinn
> darauf weiter einzugehen.

Lies bitte mal Deine Posts durch und reflektiere diese - das reicht 
schon.

von Rainer V. (a_zip)


Lesenswert?

Nu schlagt euch doch nicht die Köpfe ein! Der To hat doch einen völligen 
Humbug gepostet!! Natürlich bin ich auch immer baff, wenn mein Programm 
nicht läuft. Neu ist die Variante, natürlich die hinterhältige Variante, 
dass das geniale Programm kompiliert werden kann und dennoch nicht 
läuft! Wenn das jetzt nicht mal dem Fass den Boden ausschlägt...anders 
herum gehts immer ganz einfach :-) aber sowas habe ich noch nicht 
erlebt!!!
Gruß Rainer

Beitrag #6665179 wurde von einem Moderator gelöscht.
von Rainer V. (a_zip)


Lesenswert?

Ich bleibe dabei...völliger Humbug!
Rainer

von c-hater (Gast)


Lesenswert?

Rainer V. schrieb:
> Nu schlagt euch doch nicht die Köpfe ein! Der To hat doch einen völligen
> Humbug gepostet!! Natürlich bin ich auch immer baff, wenn mein Programm
> nicht läuft. Neu ist die Variante, natürlich die hinterhältige Variante,
> dass das geniale Programm kompiliert werden kann und dennoch nicht
> läuft! Wenn das jetzt nicht mal dem Fass den Boden ausschlägt...anders
> herum gehts immer ganz einfach :-) aber sowas habe ich noch nicht
> erlebt!!!

GRIN. Wenn's so einfach wäre, dass erfolgreiches Kompilieren schon 
sicher die Programmfunktion herstellen könnte: Wer bräuchte denn dann 
überhaupt noch Programmierer? Code kann man generieren lassen oder 
klauen.

Aber ja, ICH habe schon verstanden, dass dein Beitrag eher sarkastisch 
gemeint war.

von Rainer V. (a_zip)


Lesenswert?

c-hater schrieb:
> Aber ja, ICH habe schon verstanden, dass dein Beitrag eher sarkastisch
> gemeint war.

ist doch aber wirklich kaum anders zu ertragen oder?? Endlich postet 
jemand einen Code, der anstandlos übersetzt wird...und er läuft nicht. 
Ich frage mich jetzt ernsthaft, wie ich das sagen soll...Ich sage "there 
is no understanding in the world" und das ist definitiv im Einklang mit 
den neusten Erkenntnissen von CERN über die wackelige 8te bis 12te 
Stelle im Welbild der momentan geltenden Physik. Ist doch Scheissegal, 
höre ich die Kandidaten schon schreien...aber ist es das wirklich...was 
wäre, wenn es einen Cetaur doch gegeben hätt? OK LG
Rainer

von Udo F. (utm)


Lesenswert?

Ich finds ziemlich krass was hier aus diesem Post - Zitat 'Mikey Maus 
Code' (was er definitiv ist!) - am Ende passiert ist.
Ich wollte mich auf jeden Fall bei euch Allen für die Hilfe bedanken, da 
ich alleine nicht weiter gekommen wäre.
Ich muss zugeben, dass ich bis jetzt nicht weiß, warum das Makefile es 
am Ende gerockt hat. Ich habe definitiv nichts am Code verändert.
Auf jeden Fall werde ich jetzt immer das besagte Makefile nutzen, da ich 
dann zur Not auch alle Informationen wie z.B. das LSS File bekomme und 
es bei weiteren Fragen dann zur Hand habe.
Wie gesagt-ich bin Anfänger und muss noch dazu lernen.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Udo F. schrieb:
> Ich muss zugeben, dass ich bis jetzt nicht weiß, warum das Makefile es
> am Ende gerockt hat

Sorry, das habe ich wohl nicht deutlich genug erklärt.

Du hast versäumt, beim zweiten Aufruf des gccc (Linker) anzugeben, für 
welchen Mikrocontroller das *.elf File erzuegt werden soll. Deswegen 
fehlte dort die Interrupt-Vektor Tabelle, also dieser ganze Block:
1
00000000 <__vectors>:
2
   0:  19 c0         rjmp  .+50       ; 0x34 <__ctors_end>
3
   2:  20 c0         rjmp  .+64       ; 0x44 <__bad_interrupt>
4
   4:  1f c0         rjmp  .+62       ; 0x44 <__bad_interrupt>
5
   6:  1e c0         rjmp  .+60       ; 0x44 <__bad_interrupt>
6
   8:  1d c0         rjmp  .+58       ; 0x44 <__bad_interrupt>
7
   a:  1c c0         rjmp  .+56       ; 0x44 <__bad_interrupt>
8
   c:  1b c0         rjmp  .+54       ; 0x44 <__bad_interrupt>
9
   e:  1a c0         rjmp  .+52       ; 0x44 <__bad_interrupt>
10
  10:  19 c0         rjmp  .+50       ; 0x44 <__bad_interrupt>
11
  12:  18 c0         rjmp  .+48       ; 0x44 <__bad_interrupt>
12
  14:  17 c0         rjmp  .+46       ; 0x44 <__bad_interrupt>
13
  16:  16 c0         rjmp  .+44       ; 0x44 <__bad_interrupt>
14
  18:  15 c0         rjmp  .+42       ; 0x44 <__bad_interrupt>
15
  1a:  14 c0         rjmp  .+40       ; 0x44 <__bad_interrupt>
16
  1c:  13 c0         rjmp  .+38       ; 0x44 <__bad_interrupt>
17
  1e:  12 c0         rjmp  .+36       ; 0x44 <__bad_interrupt>
18
  20:  11 c0         rjmp  .+34       ; 0x44 <__bad_interrupt>
19
  22:  10 c0         rjmp  .+32       ; 0x44 <__bad_interrupt>
20
  24:  0f c0         rjmp  .+30       ; 0x44 <__bad_interrupt>
21
  26:  0e c0         rjmp  .+28       ; 0x44 <__bad_interrupt>
22
  28:  0d c0         rjmp  .+26       ; 0x44 <__bad_interrupt>
23
  2a:  0c c0         rjmp  .+24       ; 0x44 <__bad_interrupt>
24
  2c:  0b c0         rjmp  .+22       ; 0x44 <__bad_interrupt>
25
  2e:  0a c0         rjmp  .+20       ; 0x44 <__bad_interrupt>
26
  30:  09 c0         rjmp  .+18       ; 0x44 <__bad_interrupt>
27
  32:  08 c0         rjmp  .+16       ; 0x44 <__bad_interrupt>

Den siehst du in deinem C-Quelltext nicht, weil er eben vom Linker 
automatisch ergänzt wird. Aber nur, wen man dem Linker sagt, für welchen 
Mikrocontroller er das tun soll.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.