Da habe ich ein altes Board gefunden, auf das ich irgendwann einen Atmega8A gelötet hatte, und wollte "mal eben" testen, ob's noch funktioniert.
"Mal eben" ist jetzt zwei Tage her und ich bin ausreichend frustriert, um hier nachzufragen:
Hintergrund:
Ich hatte die Idee einen Array für die Port-Pins anzulegen und in der Timer-ISR über die einzelnen Pins zu gehen und jeweils einen auf Output, low zu stellen und alle anderen auf Input mit pull-up.
Aber nichts tat sich.
Nun kann man sich ja mit Pointern beim Dereferenzieren ins Knie schießen, besonders, wenn der Compiler auf die Idee kommt, den Array im Flash zu belassen.
Testweise habe ich den Array mal mit "const PinDesc PROGMEM..." absichtlich im Flash gelassen und von dort mit pgm_read_word() ausgelesen. Das funktioniert, und die Pins werden wie erwartet getoggelt.
Dann habe ich die "Array im RAM"-Version (m8a_Pin-Test2.c) so umgestrickt, dass sie fast genau der "Array im Flash"-Version (m8a_Pin-Test.c) entspricht - sie funktioniert trotzdem nicht.
Die ISR wird aufgerufen, das ist es nicht.
Der Array liegt in der .data section, sollte von __do_copy_data ins RAM kopiert worden sein und hat da offenbar auch einen von 0 verschiedenen Inhalt. Also muss der wohl den falschen Typ haben - aber wie? Ich seh's nicht.
Und sowohl in simulavr als auch in simavr funktioniert die "Array im RAM"-Version.
Was genau funktioniert denn nicht? Die Pins werden nicht geschaltet?
Genau.
Es rühren sich nur die "zum Debuggen" ohne Zugriff auf den Array getoggelten PB0 und PD2.
Hast du mal versucht...
die erzeugte Programmdatei zu disassemblieren und beide Versionen zu
vergleichen, ob die Daten dort sind bzw. abgelegt werden, wo sie sein
sollen?
Ja. Bei der Flash-Version liegt das Array in .text, bei der RAM-Version in .data. Der Inhalt scheint identisch.
die Daten zu Beginn des Programms seriell auszugeben und zu
vergleichen?
Das kommt morgen, wenn ich wieder zu Hause bin. Ich habe gerade keinen USB-seriell-Adapter bei mir.
Aber in m8a_Pin-Test2.c wird der Inhalt des Arrays geprüft. Wenn da nichts drin wäre, würde PD2 nicht getoggelt. Wird er aber.
Ich habe mal alle 3 Versionen kompiliert (mein GCC ist allerdings Version 15.2). Wegoptimiert wird da allerdings nichts - die Befehle zum Setzen der Register sind vorhanden. Das hätte mich auch gewundert, weil es dann in simulavr / simavr auch nichts hätte tun sollen.
Sorry, bei mir ist es gestern etwas spät geworden. Daher erst jetzt meine Meldung.
Zunächst das TL;DR:
Problem gelöst. Es ist doch immer wieder schön, wie kreativ man sich mit einer IDE ins Knie schießen kann. Vielen Dank für Eure Anteilnahme. ;-)
Wann immer man anfängt, Typecasts zu schreiben, sollte man sich Gedanken
machen, ob sie wirklich nötig sind.
Ja, alles richtig. Am Anfang hatte ich ja auch:
1
typedefstruct{
2
volatileuint8_t*ddr;
3
volatileuint8_t*port;
4
uint8_tmask;
5
}PinDesc;
6
7
PinDesctestPins[]={
8
// PORTB (exclude PB6, PB7)
9
{&DDRB,&PORTB,_BV(PB0)},...
und dann in der ISR:
1
constPinDesc*pin=&testPins[currentPin];
2
...
3
*(pin->ddr)|=pin->mask;// DDRx = 1 → output
4
*(pin->port)&=~pin->mask;// PORTx = 0 → drive low
Aber nachdem das nicht ging aber in der Flash-Version schon, habe ich die Unterschiede zwischen den Source-Dateien minimiert, um im diff nur noch das Wesentliche zu sehen.
Nun habe ich versucht, die Daten per UART auszugeben - und bin gleich vor eine Wand gelaufen. Wenn ich in eine Firmware eine UART-Routine einbaue, dann lasse ich die auch gleich beim Start Name und Version der Anwendung ausgeben. Aber es kam nur x-mal 0xFF. Weiteres Probieren ergab: Ein Register konnte ich auslesen und per UART ausgeben. Ebenso Bytes aus dem Flash, die per PROGMEM angelegt und per pgm_read_byte() gelesen wurden. Aber ein string literal? Nope. Nada.
Nee, wie (fast) immer der User.
Dieses Laptop benutze ich nur selten und eigentlich nie zum programmieren. Aber irgendwann hatte ich da Eclipse und avr-gcc installiert, wohl nur halbseiden eingerichtet und offenbar nie benutzt.
Aus unerfindlichen Gründen stand bei "Post-build Steps":
1
avr-size ${ProjName} ;avr-objcopy -O ihex -j text ${ProjName} ${ProjName}.hex
Irgendwer muss da an meinem Laptop gewesen sein... ;-)
Man könnte das natürlich noch drin lassen, aber halt in deutlich
abgeschwächter Form …
Das Beispiel auf avrdude anzupassen fänd ich ganz schon, mit Target wie "make flash". Das "aktuelle" Makefile erstellt ja nur die Binaries, ohne was damit zu machen. Oder Targets "flash-elf" "flash-hex" etc.
Das Beispiel auf avrdude anzupassen fänd ich ganz schon, mit Target wie
"make flash".
Stimmt. Mache ich ja für mich selbst auch so. ;-)
Auch müssten die Codebeispiele mal überarbeitet werden, einen STK500 hat ja heute kaum noch jemand. Allerdings hatte der natürlich mit seinen 8 LEDs und 8 Tasten schön viel Hardware zum Spielen gleich an Bord.
Auch müssten die Codebeispiele mal überarbeitet werden,
Immerhin scheinen die examples noch zu compilieren — zumindest "demo", das ja beim Build generiert wird. Aber Zeug wie SIGNAL und avr/signal.h ist auch schon etwas angestaubt.
einen STK500 hat ja heute kaum noch jemand.
Da kann ich mit meinen selbstgebastelten Programmern und Boeards nicht mitreden... Sollte aber doch fast egal sein, solange man LED-Ports etc. anpassen kann.
Ist denn schon absehbar wann es eine neue libc Version gibt?
einen STK500 hat
ja heute kaum noch jemand. Allerdings hatte der natürlich mit seinen 8
LEDs und 8 Tasten schön viel Hardware zum Spielen gleich an Bord.
Ich war früher gerne auf den Seminaren der Halbleiterhersteller. Da bekam man in der Regel auch Eval-Boards usw. Mittags gab es ein reichliches Buffet und am Abend konnte man sich mit den Entwicklern bei einem Glas Wein noch unterhalten. Diese Zeiten sind leider lange vorbei.
Ich habe noch das erste STK für AT90S1200/2313/8515. Da saß ein AT89C2051 als Programmer drauf.
Dann gab es das STK300 mit ATmega103, leider ohne Programmer-µC. Das mußte man an den LPT-Port anschließen, habe ich daher nie benutzt.
Und dann das originale STK500 mit AT90S1200 und AT90S8535. Der AT90S1200 war nur für Firmware-Updates zuständig, da die AVRs alle noch keinen Bootloader unterstützten. Somit konnte man das STK500 auch nicht aussperren.
Keineswegs, es gibt inzwischen einige (viele?) Fertiger, die ODB++
unterstützen
Hab mal geschaut, im Altium OutputJob gibt es die Option ODB++ Files, da weiß ich aber nicht was man da alles konfigurieren muß.
Es entsteht ein Zip mit 53 Dateien und 37 Ordnern, 4MB (1MB Zip). Also deutlich mehr Schrunz, als bei Gerber/NC Drill.
Ich müßte mal den Fertiger fragen, ob der daran überhaupt Interesse hat und was er davon wirklich braucht.
Es ist immer viel Arbeit, etwas bewährtes durch was neues zu ersetzen. Der bisherige OutputJob wurde schon viele Jahre nicht mehr angefaßt, sondern immer nur in neue Projekte kopiert.
Also deutlich mehr Schrunz, als bei Gerber/NC Drill.
Anders gesagt: deutlich klarer im Detail.
Bei den einzelnen Gerberdateien brauchte es ja fast immer irgendeine Form der Nebenabsprache, damit der Empfänger sich auch sicher sein kann, dass er sie genau so verwendet, wie der Absender sie meinte – ob nun in Form einer separaten Beschreibungsdatei oder einer Namenskonvention.
Ich müßte mal den Fertiger fragen, ob der daran überhaupt Interesse hat
und was er davon wirklich braucht.
Ich habe es letztens bei Aisler mal benutzt (auch aus Altium heraus), das hat auf Anhieb und völlig aufwandsarm für mich klaglos funktioniert.
Aber das ist jetzt hier genug OT. Es ging ja darum, dass der TE sich selbst beim Produzieren der iHex-Datei ins Knie geschossen hatte, was ihm bei direkter Verwendung der ELF-Datei gar nicht hätte passieren können.
Wofür das? Wenn du einen Bootloader hast, überschreibt der sich eh nicht
selbst.
Bei einem Upload per ISP ist der Bootloader außen vor. Bei einem Chip Erase ist auch der Bootloader weg.
Das EEPROM lässt sich nicht aus/über dem verwendeten Optiboot beschreiben.
Es ist in manchen Situationen schlicht praktisch Bootloader, EEPROM und Anwendung in einem Rutsch zu schreiben.
Ansonsten:
Das "Warum das so gemacht wird?" kann ich nicht beantworten, denn ist nicht auf meinem Mist gewachsen. Ist vor über 10 Jahren so gebaut worden.
Ansonsten kann man den sicher als separate Objektdatei mit eigener
section dazu linken.
Der Bootloader liegt als .hex und als Quellcode vor.
Ein übersetzen des Bootloaders ist in der IDE nicht vorgesehen, auch wenn die Toolchain vollständig vorliegt. Wobei ich meine, dass make fehlt, bin mir da aber nicht sicher.
So wie ich das sehe wäre dafür ein tiefgreifender Umbau des Arduinobuilders nötig. Eine AVR Extrawurst, die bei den anderen µC Typen dann zu Seiteneffekten führen könnte.
Nein, ich erwarte nicht, dass das jemand umbaut. Und ich sehe mich dazu nicht in der Lage.
Darum auch meine Frage nach "einfach".
Deine Antwort interpretiere ich so: Nein! Nicht einfach.
Naja, irgendwas müsstest du in jedem Falle dafür machen. Wenn man Umbauten kategorisch ausschließt, dann kann man auch nie etwas ändern. Den Bootloader gleich mit zu compilieren (und ihm eine eigene section zu spendieren), wäre durchaus keine unelegante Lösung. Hätte auch den Vorteil, dass ihn sich jemand einfach lokal ändern kann, falls er dafür Bedarf hat.
Man kann ja auch weiter Hexfiles nehmen, wenn man das unbedingt will. Ist ja nur, dass des TE's Fehler mit dem ELF-File gar nicht erst passiert wäre.
Prinzipiell könntest du auch das Hexfile für den Bootloader separat noch mit angeben, halt als ein zweites -Uflash:w:…
Das (default) chip erase wird ja nur einmal am Anfang gemacht. Dann kannst du für Application Flash+EEPROM das ELF-File direkt nehmen und für den Bootloader das Hexfile hinterher schieben. Muss man gar nichts erst vorab mergen. ;-)
Habe ich jetzt nicht probiert, aber sollte funktionieren.
Das mergen ist eigentlich kein Problem.
Denn das macht der Arduino Builder automatisch.
Es wird eine Anwendung.eep, eine Anwendung.hex und eine Anwendung.with_bootloader.hex erzeugt.
Wüsste auch nicht wie man das abschalten/ändern kann.
Bei einem Upload per ISP ist der Bootloader außen vor. Bei einem Chip
Erase ist auch der Bootloader weg.
Das EEPROM lässt sich nicht aus/über dem verwendeten Optiboot
beschreiben.
Hallo? Es geht um eine Anleitung für EINSTEIGER und auch nicht um Arduino oder was auch immer.