Forum: Mikrocontroller und Digitale Elektronik Attiny-Entwicklungsumgebung rott?


von Mark S. (voltwide)


Lesenswert?

/*
Problem AVR-Programmierung

Seit zwei Tagen beiße ich mir die Zähne aus an meinem 
AVR-Entwicklungssystem,
das anscheinend keinen lauffähigen code mehr erzeugt.
Wird im angehängten Code-Beispiel die Zeile 6 auskommentiert, dann 
funktioniert die Portausgabe im Hauptprogramm nicht mehr.
Der adressierte port ist dann zwar auf Ausgang programmiert, liefert 
jedoch low.
Offenbar kann man den Fehler auch mit x-beliebigen anderen eingefügten 
dummy-code herbeiführen.

Meine Entwicklungsumgebung besteht aus

Kernel
$ uname -a
Linux pc4 3.16.0-5-amd64 #1 SMP Debian 3.16.51-3+deb8u1 (2018-01-08) 
x86_64 GNU/Linux

Distribution
$ lsb_release -a
No LSB modules are available.
Distributor ID:  LinuxMint
Description:  LMDE 2 Betsy
Release:  2
Codename:  betsy

IDE
Codeblocks aus SVN build 04.Feb.2018
AVR-gcc V4.8.1
AVRdude V6.1
SPI-programmer USBtiny (Lady Ada)
Attiny 25

Anzumerken ist dass ich verschiedene AVR Projekte in den letzten Jahren 
zum Laufen gebracht habe und bis vor wenigen Wochen auf diesem System 
lauffähigen Code generieren konnte.
Sowohl der Programmer als auch das Zielsystem wurden getauscht, jedoch 
ohne Erfolg.
Irgendwie riecht es nach einem ganz dämlichen Trivialfehler, aber ich 
komme einfach nicht drauf.
Es wäre schön, wenn jemand dazu eine zündende Idee haben könnte.

Dies ist der Minimalcode, bei dem der Fehler reproduzierbar auftritt.
*/

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

void PowerUp(void) {
    DDRB            = (1<<PB2);
    //DDRB            = (1<<PB2);    //!!!
}
//++++++++ Main Program

int main(void) {
    for (;;) {
    PowerUp();
    PORTB |= (1<<PB2);
    }
}

von Jim M. (turboj)


Lesenswert?

Könnte ein Problem mit dem Stack(-Pointer) sein.

Die ganz kurze Funktion macht der Compiler inline (also ohne 
Funktionsaufruf), die längere mit "richtigem" Call benutzt Stack. Das 
knallt u.U. erst beim Rücksprung.

Zeig mal das Disassembly...

von Mark S. (voltwide)


Lesenswert?

bin/Release/TPA325xPowerManager.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000044  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00800060  00000044  000000d8  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .fuse         00000003  00820000  00820000  000000d8  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  3 .comment      00000011  00000000  00000000  000000db  2**0
                  CONTENTS, READONLY

Disassembly of section .text:

00000000 <__vectors>:
   0:  0e c0         rjmp  .+28       ; 0x1e <__ctors_end>
   2:  15 c0         rjmp  .+42       ; 0x2e <__bad_interrupt>
   4:  14 c0         rjmp  .+40       ; 0x2e <__bad_interrupt>
   6:  13 c0         rjmp  .+38       ; 0x2e <__bad_interrupt>
   8:  12 c0         rjmp  .+36       ; 0x2e <__bad_interrupt>
   a:  11 c0         rjmp  .+34       ; 0x2e <__bad_interrupt>
   c:  10 c0         rjmp  .+32       ; 0x2e <__bad_interrupt>
   e:  0f c0         rjmp  .+30       ; 0x2e <__bad_interrupt>
  10:  0e c0         rjmp  .+28       ; 0x2e <__bad_interrupt>
  12:  0d c0         rjmp  .+26       ; 0x2e <__bad_interrupt>
  14:  0c c0         rjmp  .+24       ; 0x2e <__bad_interrupt>
  16:  0b c0         rjmp  .+22       ; 0x2e <__bad_interrupt>
  18:  0a c0         rjmp  .+20       ; 0x2e <__bad_interrupt>
  1a:  09 c0         rjmp  .+18       ; 0x2e <__bad_interrupt>
  1c:  08 c0         rjmp  .+16       ; 0x2e <__bad_interrupt>

0000001e <__ctors_end>:
  1e:  11 24         eor  r1, r1
  20:  1f be         out  0x3f, r1  ; 63
  22:  cf e5         ldi  r28, 0x5F  ; 95
  24:  d2 e0         ldi  r29, 0x02  ; 2
  26:  de bf         out  0x3e, r29  ; 62
  28:  cd bf         out  0x3d, r28  ; 61
  2a:  06 d0         rcall  .+12       ; 0x38 <main>
  2c:  09 c0         rjmp  .+18       ; 0x40 <_exit>

0000002e <__bad_interrupt>:
  2e:  e8 cf         rjmp  .-48       ; 0x0 <__vectors>

00000030 <PowerUp>:
  30:  8c e0         ldi  r24, 0x0C  ; 12
  32:  87 bb         out  0x17, r24  ; 23
  34:  87 bb         out  0x17, r24  ; 23
  36:  08 95         ret

00000038 <main>:
  38:  cc e0         ldi  r28, 0x0C  ; 12
  3a:  fa df         rcall  .-12       ; 0x30 <PowerUp>
  3c:  c8 bb         out  0x18, r28  ; 24
  3e:  fd cf         rjmp  .-6        ; 0x3a <main+0x2>

00000040 <_exit>:
  40:  f8 94         cli

00000042 <__stop_program>:
  42:  ff cf         rjmp  .-2        ; 0x42 <__stop_program>

von Mark S. (voltwide)


Lesenswert?

Solche Effekte kenne ich bislang nur wenn Interrupts ausgelöst werden 
auf nicht existente Interrupt-handler.

von MWS (Gast)


Lesenswert?

Es sollte auffallen, dass 1<<x niemals 2 Bits setzen kann, wie es bei 
0x0C geschieht.
Ergo: Compiler kaputt.

von Bernd S. (wirrer_haarschopf)


Lesenswert?

MWS schrieb:
> Es sollte auffallen, dass 1<<x niemals 2 Bits setzen kann, wie es bei
> 0x0C geschieht.
> Ergo: Compiler kaputt.

Also "Compiler kaputt" ist es doch in etwa 101% aller Fälle nicht. 
Insbesondere nicht bei so einem offensichtlichen Fehler.

Der CPP scheint aus 1<<PB2 den Wert 0x0C zu generieren. Muss also was in 
den entsprechenden Header Files mit den Definitionen kaputt sein. Schau 
doch mal wie PB2 definiert ist.

: Bearbeitet durch User
von xyz (Gast)


Lesenswert?

Denke an den Klassiker fehlende Klamern in Defines.

von Johannes S. (Gast)


Lesenswert?

Und was macht PINB2 statt PB2?

Edit:
ok, sollte nix bringen, sind zumindest in meinem alten gcc gleich 
definiert. Ist schon komisch das der Compiler aus einem zweit Bits 
macht. Aber das richtige ist doch trotzdem dabei, nach dem disassembly 
müsste nur noch PB3 zusätzlich als Ausgang gesetzt werden?

von Mark S. (voltwide)


Lesenswert?

ich bin nun nicht so der disassembly-Versteher.
Vlt liegt der Fehler aber hier - Bildschirmausgabe vom 
CodeBlocks-Compiler-Lauf. Gleich in der ersten Zeile, wieso steht da an 
einer Stelle mmcu=attiny85, obwohl in den settings nur Attiny25 angehakt 
ist?
In früheren Läufen hatte ich in der Tat den Attiny85 programmiert, was 
ja auch noch vor wenigen Wochen funktionierte.




-------------- Build: Release in TPA325xPowerManager (compiler: GNU GCC 
Compiler for AVR)---------------

avr-gcc -mmcu=attiny85 -Wall -DF_CPU=1000000UL -Os -mmcu=attiny25  -c 
main.c -o obj/Release/main.o
avr-g++  -o bin/Release/TPA325xPowerManager.elf obj/Release/fuse.o 
obj/Release/main.o  -mmcu=attiny85 
-Wl,-Map=bin/Release/TPA325xPowerManager.map,--cref
Output file is bin/Release/TPA325xPowerManager.elf with size 1.98 KB
Running project post-build steps
avr-objdump -h -S bin/Release/TPA325xPowerManager.elf > 
bin/Release/TPA325xPowerManager.lss
avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex 
bin/Release/TPA325xPowerManager.elf bin/Release/TPA325xPowerManager.hex
avr-objcopy --no-change-warnings -j .eeprom --change-section-lma 
.eeprom=0 -O ihex bin/Release/TPA325xPowerManager.elf 
bin/Release/TPA325xPowerManager.eep
avr-objcopy --no-change-warnings -j .lock --change-section-lma .lock=0 
-O ihex bin/Release/TPA325xPowerManager.elf 
bin/Release/TPA325xPowerManager.lock
avr-objcopy --no-change-warnings -j .signature --change-section-lma 
.signature=0 -O ihex bin/Release/TPA325xPowerManager.elf 
bin/Release/TPA325xPowerManager.sig
avr-objcopy --no-change-warnings -j .fuse --change-section-lma .fuse=0 
-O ihex bin/Release/TPA325xPowerManager.elf 
bin/Release/TPA325xPowerManager.fuse
srec_cat bin/Release/TPA325xPowerManager.fuse -Intel -crop 0x00 0x01 
-offset  0x00 -O bin/Release/TPA325xPowerManager.lfs -Intel
srec_cat bin/Release/TPA325xPowerManager.fuse -Intel -crop 0x01 0x02 
-offset -0x01 -O bin/Release/TPA325xPowerManager.hfs -Intel
/bin/sh: 1: srec_cat: not found
Process terminated with status 127 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))

von Johannes S. (Gast)


Lesenswert?

mein altes AtmelStudio mit gcc 3.4 macht es richtiger:
1
0000002c <PowerUp>:
2
3
#include <stdlib.h>
4
#include <avr/io.h>
5
6
void PowerUp(void) {
7
  DDRB            = (1<<PB2);
8
  2c:  84 e0         ldi  r24, 0x04  ; 4
9
  2e:  87 bb         out  0x17, r24  ; 23
10
  DDRB            = (1<<PB2);    //!!!
11
  30:  87 bb         out  0x17, r24  ; 23
12
  32:  08 95         ret
13
14
00000034 <main>:
15
}
16
//++++++++ Main Program
17
18
int main(void) {
19
  for (;;) {
20
    PowerUp();
21
  34:  fb df         rcall  .-10       ; 0x2c <PowerUp>
22
    PORTB |= (1<<PB2);
23
  36:  c2 9a         sbi  0x18, 2  ; 24
24
  38:  fd cf         rjmp  .-6        ; 0x34 <main>
25
26
0000003a <_exit>:
27
  3a:  f8 94         cli
28
29
0000003c <__stop_program>:
30
  3c:  ff cf         rjmp  .-2        ; 0x3c <__stop_program>

wenn ich die //!!! Zeile auskommentiere wird auch nur ein out generiert.

von Stefan F. (Gast)


Lesenswert?

Interessant wären tatsächlich mal die ganzen Kommandozeilen vom 
schlechten Fall zu sehen.

von Johannes S. (Gast)


Lesenswert?

Ja, die doppelte mcu definition wird den Compiler verwirrt haben. Kenne 
CodeBlocks nicht, aber das muss irgendwo in den Projektsettings liegen. 
Evtl.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Zumindest mit 4.8.0 kann ich das nicht nachvollziehen.

* Wie sieht Präcompilat (*.i) und Assembly (*.s) aus wenn -save-temps 
angegeben wird?

* Ist sicher, dass die Dateien neu generiert werden, d.h. dass das 
Makefile i.O. ist?

* Was ist die Ausgabe mit zusätzlich -v beim Compilieren / Linken?

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

ohne das jetzt im Detail geprüft zu haben: ich vermute die falsche mcu 
definition führt dazu das der Stackpointer falsch initialisiert wird 
(tiny85 hat 512 Byte RAM, tiny24 nur 128 Bytes) und dann der Rücksprung 
aus PowerUp() nicht mehr im main() landet. Damit wird der Port 
initialisiert, aber das Bit in main nicht mehr gesetzt.
Das passiert vielleicht wenn man das CodeBlocks Projekt kopiert und die 
mcu Einstellung verändert, dann muss die IDE ja die alte Einstellung 
erkennen und ändern. Das hat sie wohl nicht und den tiny25 hinzugefügt. 
Vielleicht korrigiert die IDE das wenn man noch andere 
Compilereinstellungen ändert.
Aber eigentlich wollte ich mir die AVR gar nicht mehr ansehen...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Johannes S. schrieb:
> ich vermute die falsche mcu definition führt dazu das der Stackpointer
> falsch initialisiert wird (tiny85 hat 512 Byte RAM, tiny24
> nur 128 Bytes)

Was aber nicht das 0xC für 1<<PB2 erklärt.

Tatsächlich wird der Startcode für ATtiny85 verwendet:
1
COLLECT_GCC_OPTIONS='-mmcu=attiny85' '-mmcu=attiny25' '-Os' '-save-temps' '-v' '-fverbose-asm'
2
collect2 version 4.8.0 20130306 (experimental)
3
.../avr/bin/ld -m avr25 .../avr/lib/avr25/crttn85.o ...
4
GNU ld (GNU Binutils) 2.23.52.20130301
5
6
0000001e <__ctors_end>:
7
  1e:  11 24         eor  r1, r1
8
  20:  1f be         out  0x3f, r1  ; 63
9
  22:  cf e5         ldi  r28, 0x5F  ; 95
10
  24:  d2 e0         ldi  r29, 0x02  ; 2
11
  26:  de bf         out  0x3e, r29  ; 62
12
  28:  cd bf         out  0x3d, r28  ; 61
13
  2a:  06 d0         rcall  .+12       ; 0x38 <main>
14
  2c:  08 c0         rjmp  .+16       ; 0x3e <_exit>

: Bearbeitet durch User
von Pirx (Gast)


Lesenswert?

Pack mal das PowerUp() vor die For-Schleife.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Pirx schrieb:
> Pack mal das PowerUp() vor die For-Schleife.

Ergibt immer noch kein 0x0C; immer nur 0x04.

von Johannes S. (Gast)


Lesenswert?

Das 0x0c konnte ich auch mit dem alten gcc 3.4 nicht provozieren.

von Arno (Gast)


Lesenswert?

Bernd S. schrieb:
> MWS schrieb:
>> Es sollte auffallen, dass 1<<x niemals 2 Bits setzen kann, wie es bei
>> 0x0C geschieht.
>> Ergo: Compiler kaputt.
>
> Also "Compiler kaputt" ist es doch in etwa 101% aller Fälle nicht.
> Insbesondere nicht bei so einem offensichtlichen Fehler.
>
> Der CPP scheint aus 1<<PB2 den Wert 0x0C zu generieren. Muss also was in
> den entsprechenden Header Files mit den Definitionen kaputt sein. Schau
> doch mal wie PB2 definiert ist.

Spannender Fehler. denn 1<<x kann eigentlich nicht mehr als ein Bit 
gesetzt haben, egal welchen Wert x hat, also egal wie PB2 definiert ist. 
Tut es aber sowohl in der Funktion PowerUp als auch in der main, beide 
Male 0x0c

Mein avr-gcc-4.9.2 macht das auch (erstmal) richtig:
1
ldi r24,lo8(4)
2
out 0x17,r24

Der eigentliche, beobachtete Fehler scheint aber tatsächlich der falsche 
Startup-Code zu sein, der den Stack-Pointer falsch initialisiert. Ist 
auch kein Wunder, denn der Linker-Aufruf (avr-g++) bekommt nur 
-mmcu=attiny85 mit.

Da scheint die IDE die korrekten Einstellungen noch nicht in alle 
Build-Schritte übertragen zu haben.

Kann es sein, dass auch die Disassembly-Ausgabe alt ist und du 
irgendwann mal PB2 und PB3 benutzt hast?

MfG, Arno

von Mark S. (voltwide)


Lesenswert?

Johannes S. schrieb:
> ohne das jetzt im Detail geprüft zu haben: ich vermute die falsche mcu
> definition führt dazu das der Stackpointer falsch initialisiert wird
> (tiny85 hat 512 Byte RAM, tiny24 nur 128 Bytes) und dann der Rücksprung
> aus PowerUp() nicht mehr im main() landet. Damit wird der Port
> initialisiert, aber das Bit in main nicht mehr gesetzt.
> Das passiert vielleicht wenn man das CodeBlocks Projekt kopiert und die
> mcu Einstellung verändert, dann muss die IDE ja die alte Einstellung
> erkennen und ändern. Das hat sie wohl nicht und den tiny25 hinzugefügt.
> Vielleicht korrigiert die IDE das wenn man noch andere
> Compilereinstellungen ändert.
> Aber eigentlich wollte ich mir die AVR gar nicht mehr ansehen...

So in der Richtung denke ich auch. Ich hatte im laufenden Projekt das 
target geändert. Werde das Projekt neu aufsetzen, das könnte schon die 
Lösung sein.
Dazu komme ich aber im Augenblick nicht (Gartenarbeit ist hat eben den 
höheren Prioritätslevel).

von Mark S. (voltwide)


Lesenswert?

Für die vielen hilfreichen Beiträge möchte ich mich hier mal herzlich 
bedanken. Innerhalb von CodeBlocks konnte ich keine Einstellungen 
finden, die das falsche Target korrigiert hätten. Also habe ich ein 
neues Attiny25-Projekt geöffnet - und voilà - nun läuft es wieder 
erwartungsgemäß.
Und ja, es ist für mich nachvollziehbar, dass der Code, gelinkt für den 
größeren RAM-Bereich des Attiny85 im Attiny25 wohl nicht funktionieren 
wird.

: Bearbeitet durch User
von Arno (Gast)


Lesenswert?

Ist damit auch der 0x0c-Fehler beseitigt? Den finde ich noch 
spannender...

MfG, Arno

von Bernd K. (prof7bit)


Lesenswert?

Arno schrieb:
> Ist damit auch der 0x0c-Fehler beseitigt? Den finde ich noch
> spannender...
>
> MfG, Arno

Würde mich auch interessieren. Lässt es sich bei irgendwem nachstellen 
wenn man den geposteten Compileraufruf an der Kommandozeile manuell 
nachvollzieht?

von Jim M. (turboj)


Lesenswert?

Arno schrieb:
> Ist damit auch der 0x0c-Fehler beseitigt? Den finde ich noch
> spannender...

Das ist mit einiger Sicherheit ein Copy&Paste Fehler. Im originalen Code 
steht wohl einfach:
1
 DDRB = (3<<PB2);

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.