www.mikrocontroller.net

Forum: Codesammlung MMC/SD Bootloader füt ATMega16

Autor: Stefan Seegel (Gast)
Datum: 12.04.2007 13:43
Dateianhang: MMC_Bootloader.zip (85,2 KB, 1024 Downloads)

Hallo,

im Anhang findet sich ein Bootloader, der seine Updates von einer MMC/SD
Karte bezieht. Der Bootloader passt knapp in 2kB, so dass der Bootloader
vom Mega8 bis zu den Großen verwendet werden kann.

Ausstattung:
- Unterstützung für FAT16 (Partitionstyp 0x06)
- Überprüfung der "Geräte-ID", so dass automatisch die richtige Datei,
und nur diese, von der Karte geladen wird
- Überprüfung der Versionkennung, so dass nur aktualisiert wird wenn
eine neuere Software auf der Karte vorhanden ist
- CRC Überprüfung; das Hauptprogramm wird nur dann gestartet, wenn die
CRC (befindet sich in den letzten beiden Bytes des Hauptprogrammes)
korrekt ist.

Einschränkungen:
- Auf der Karte muss ein MBR vorhanden sein, und es wird nur die erste
Partition überprüft (meine letzten 3 Karten die ich gekauft habe waren
bereits so eingerichtet mit FAT16 Partition). Ggf. selber einen MBR auf
die Karte schreiben

Beschreibung:
Im Bootloader wird eine Gerätekennng (DEVID) im makefile definiert. Für
jedes Gerät sollte eine eigene Kennung vergeben werden.
Im Hauptprogramm wird diese Gerätekennung, die Softwareversionsnummer
und 2 leere Bytes, in die später die CRC kommt, über eine Section ans
Ende des Hauptprogramms geschrieben.
Nach dem erzeugen des Hauptprogramms muss noch mit dem ebenfalls
beiliegenden Tool "crcgen" die CRC in die hex-Datei geschrieben werden.
Nun wird noch die hex-Datei auf eine MMC kopiert (Dateiname egal) und
fertig. Der Bootloader erkennt dann an der Dateigröße und der DEVID dass
es sich um ein Update für dieses Gerät handelt. Nachdem die
Versionsnummer (im Makefile des Hauptprogramms hinterlegt) überprüft
wurde beginnt der Updatevorgang. Anschließend wird noch die CRC im Flash
überprüft und das Hauptprogramm gestartet.


Zu tun:
Der Bootloader passt derzeit ganz knapp in 2 kB, für ein paar
Statusausgaben (Display, LEDs, etc) ist kein Platz mehr. Vielleicht
könnte sich jemand den Code ansehen der mehr von "effizientem
Programmieren" versteht als ich, und noch das ein oder andere Byte
herauskitzeln.


So, dann viel Spaß beim Testen,

Stefan
Autor: Jörg (Gast)
Datum: 12.04.2007 15:58

Sieht gut aus! (sehr flüchtig draufgeguckt)

Ich brauche zwar keinen solchen Bootloader, aber kann mir vielleicht was
für meinen abgucken. ;-)

Zum Thema unter gcc kleiner kriegen siehe hier:
Beitrag "Tricks, wie ich mein Compilat kleiner kriege"

Bin noch nich ganz durch damit, werde bestimmt noch was ergänzen, aber
besonders die "umstrittenen" -mint8 und -mtiny-stack bringen viel.
Autor: Jörg (Gast)
Datum: 12.04.2007 16:28

Eins fällt mir doch noch auf:
In deinem .lss File sieht man, daß du dir die Bibliotheksfunktion
udivmodsi4 "eingefangen" hast, eine allgemeine Division. Die ist recht
teuer.
Sie wird 2 mal benutzt:
Einmal in fat16_readfilesector für Teilen durch SectorsPerCluster.
Versuch' da vorher einen Zweierexponenten draus zu gewinnen, dann ist
hier ein Rechtsschieben möglich.
Das zweite Mal ein paar Zeilen tiefer, ich durchschaue aber nicht warum.
Autor: Stefan (Gast)
Datum: 12.04.2007 20:14

Hallo!

Danke für die Tips, bin nun schon auf 1976 Bytes unten, vorher waren es
etwa 2040.
Das mit der Division muss ich mir mal genauer ansehen...

Stefan
Autor: Jörg (Gast)
Datum: 12.04.2007 22:53

Kleine Anmerkung, habe ich gerade rausgefunden:
<avr/boot.h> ist nicht ganz -mint8 fest. Der Check
 #elif (FLASHEND > USHRT_MAX) 
tut nicht mehr das gewünschte, weil USHRT_MAX sich halbiert. An dieser
Stelle sollte besser UINT16_MAX stehen. Mal sehen, ob ich den Autor
ausfindig machen kann.
Als Abhilfe kann man die internen __boot_page_XXX_normal Funktionen
direkt verwenden. (Oder die jeweils anderen, je nach Controller)
Autor: Stefan (Gast)
Datum: 12.04.2007 22:54
Dateianhang: MMC_Bootloader.zip (84,5 KB, 408 Downloads)

So,

wie nicht anders zu erwarten, hier schon mal eine neue Version. Der
Bootloader ist nun 1952 Bytes groß, und es ist noch ein neues, äußerst
informatives Merkmal hinzugekommen: Oben in main.c kann man einen
Portpin definieren, an der eine Led angeschlossen ist. Die LED wird
aktiviert, sobald der Bootloader startet und die MMC Karte durchsucht
wird. Wird ein passendes Update gefunden, wird selbiges installiert,
währenddessen die Led flackert. Nach diesem Vorgang wird der CRC-Test im
Applikationsbereich durchgeführt. Verläuft der Test positiv verlischt
die Led und das Hauptprogramm wird gestartet. Andernfalls bleibt die Led
aktiv und der Bootloader hält an. So wird verhindert dass eine
fehlerhafte Applikation gestartet wird, und man hat eine direkte
Rückkopplung, wie der Aktualisierungsvorgang verlief.

Ausblick:
Evtl. könnte man Pin 3 des 10-pin ISP Steckers misbrauchen und auf
diesen z.B. den SS Pin auflegen. Dadurch wäre es möglich, eine MMC-Karte
direkt an den ISP Header anzuschließen, zumindest bei den Prozessoren
deren MISO/MOSI Pins gleichzeitig für ISP und SPI verwendet werden (z.B.
Mega16).
Mal sehen, evtl. entwickle ich bei Gelegenheit ein kleines
Adapterplatinchen auf der der MMC-Sockel, ein 3.3 V Spannungsregler, die
Spannungsteiler und ein 10-pin Header drauf sind. So muss man nicht
immer das Notebook zum Gerät oder das Gerät zum Rechner tragen, sondern
schließt einfach kurz die MMC an, Reset drücken, kurz warten, fertig.

Gruß
Stefan
Autor: Robert S. (razer) Benutzerseite
Datum: 15.04.2007 11:32

Hallo Stefan,

Dein Bootloader ist wirklich nicht schlecht, Kompliment!!

Eine Frage, wäre es schwer, den Bootloader auf einen Mega128
umzuschreiben??

mfg Robert
Autor: Stefan (Gast)
Datum: 15.04.2007 23:30

Tach,

nein, wäre nicht schwer... Ich hatte das ganze ursprünglich für einen
Mega128 entwickelt, weil ich aus dem Bauch heraus vermutet hatte dass
der Bootloader mehr als 2 kB Platz braucht. Nachdem ich sah dass es
knapp in 2 k passt, habe ich den Bootloader mit Defines etc. versehen,
so dass er universell verwendbar ist.
Du musst im Bootloader-Makefile zunächst BOOTLOADERSTARTADR entsprechend
setzten, je nachdem wie groß du die Bootloadersektion mit den Fusebits
einstellst und BOOTLDRSIZE ebenfalls entsprechend anpassen. In mmc_lib.h
müssen die Port Pins angepasst werden an denen die MMC hängt.
Im Hauptprogramm muss dann ebenfalls noch im makefile BOOTLDRSIZE und
BOOTLDRINFOSTART angepasst werden, damit der Bootloader die
"Hundemarke", Versionnummer und CRC finden kann.

Viel Spaß,
Stefan
Autor: holger (Gast)
Datum: 17.04.2007 23:48

@ Stefan

Du hast nur einen Buffer fat_buf. Ein Sektor ist 512 Bytes
groß. Warum also beide als Parameter übergeben ?

void mmc_read_buffer(void)
{
 unsigned char *buf;
 unsigned short len;

 buf = fat_buf;
 len= 512;

  while (len)
  {
    spi_send_byte(0xFF);
    len--;
    *buf++ = SPDR;
  }
}
Autor: holger (Gast)
Datum: 19.04.2007 19:57
Dateianhang: HolgerBootloader.zip (11,5 KB, 184 Downloads)

@ Stefan

Hab mal ein bisschen rumgespielt. Aber leider nicht ausprobiert.
Nur mal was zum nachdenken ! Ein bisschen ausklammern,
ein % entsorgt. Über die Größe der Clusternummern nachdenken.

Startpunkt war 1972 Bytes mit WinAVR 3.4.6.
Rausgekommen ist 1890 Bytes.

Gut, das mit void mmc_read_buffer(void)
könnte man sich ja noch mal überlegen ;)

Gruß
 Holger
Autor: holger (Gast)
Datum: 19.04.2007 20:57
Dateianhang: HolgerBootloader2.zip (29,4 KB, 175 Downloads)

Und nun steht er bei 1820 Bytes.
Autor: holger (Gast)
Datum: 20.04.2007 19:04
Dateianhang: HolgerBootloader3.zip (28 KB, 192 Downloads)

Und jetzt komme ich auf 1716 Bytes.
Soll ich weitermachen ?
Autor: Werner B. (Gast)
Datum: 20.04.2007 21:19

In zwei Jahren ist er weg ;-)
Autor: Stefan (Gast)
Datum: 20.04.2007 21:27

>Soll ich weitermachen ?

Na ich bitte darum ! :-)

>Und jetzt komme ich auf 1716 Bytes.

Hm, mein Compiler sagt 1724, aber was soll's, trotzdem um Welten
kleiner. Super!

Von manchen Sachen kann man zwar deren "logische Herkunft" nicht mehr so
gut erkennen, z.B. sowas
if ((entry_num * sizeof(direntry_t) / 512) >= RootDirRegionSize)

wird ersetzt durch
if ((entry_num / 16) >= RootDirRegionSize)

, aber was solls, den Zweck das Compilat kleiner zu kriegen erfüllt es
ja deutlich.

Also wenn noch was rauskommt, immer her damit.
Dann kann ich mir schonmal gedanken drüber machen ob/was man noch an
sinnvollen Funktionen einbauen kann.

Bis dann,

Stefan

Ach ja, hast du auch ausprobiert ob das ganze funktioniert ? Kann das
derzeit nicht testen, weil ich für eine Woche im Ausland bin...
Autor: holger (Gast)
Datum: 20.04.2007 22:07

Hi Stefan,

>Ach ja, hast du auch ausprobiert ob das ganze funktioniert ? Kann das
>derzeit nicht testen, weil ich für eine Woche im Ausland bin...

Ist bei mir noch rein theoretisch. Probiert habe ich es noch
nicht. Mach ich am Wochenende aber auf jeden Fall.

>Von manchen Sachen kann man zwar deren "logische Herkunft" nicht mehr so
>gut erkennen, z.B. sowas
>if ((entry_num * sizeof(direntry_t) / 512) >= RootDirRegionSize)
>wird ersetzt durch
>if ((entry_num / 16) >= RootDirRegionSize)

sizeof(direntry_t) ist nun mal 32. Das wirds wohl auch immer bleiben.
Deine Klammersetzung zwingt den Compiler aber erstmal
entry_num * sizeof(direntry_t)
auszurechnen und danach durch 512 zu teilen.
Selber ausrechnen ist hier der bessere Weg.

Das meiste haben die Bitschubsereien mit SectorsPerCluster
gebracht. Echte Multiplikation bzw. Division vermeiden !

Dann die Funktionsparameter nicht selbst zum rechnen zu
benutzen. Pushs und Pops im *.lss sind rapide gesunken.

Als Abschluss: die minimal benötigten Datentypen
für einen Wert einsetzen.

Und wenn man einen Bootloader wirklich klein kriegen
will muss man heilige Kühe schlachten.
Bei MMC oder FAT16 Lib-Funktionen so weit wie möglich
auf Übergabeparameter verzichten.

Mehr habe ich nicht gemacht ;)



Autor: holger (Gast)
Datum: 20.04.2007 22:39

Das hätte ich jetzt fast vergessen !

@ Werner

>In zwei Jahren ist er weg ;-)

Geh spielen. Heute darfst du mal für ne Stunde raus.
Autor: holger (Gast)
Datum: 20.04.2007 23:49
Dateianhang: HolgerBootloader4.zip (28,2 KB, 161 Downloads)

Upps, schneller Bugfix :(
Autor: holger (Gast)
Datum: 21.04.2007 16:45
Dateianhang: HolgerBootloader5.zip (24,2 KB, 224 Downloads)

So, alles aufgebaut und getestet. Funktioniert prima.
War noch einiges an Bastelarbeiten zu erledigen:

Bei CMD1 wurde nicht lange genug gewartet (bei 16MHz).
Hab den Timeoutzähler dort entfernt. Wenn
von der Karte nix kommt fliegt sie jetzt
schon bei CMD0 raus.

Eine meiner SD Karten möchte doch glatt zwei
mmc_init() hintereinander haben.

In fat16.c kann man sich jetzt aussuchen
ob Karten mit oder ohne MBR zum Einsatz kommen.
Ohne MBR gehts unter 1700 Bytes ;)

Aufpassen: Im Anhang wird ein ATMega32 benutzt !
Hab auch die Sampleapp für ATMega32 dazugepackt.
Autor: Stefan (Gast)
Datum: 22.04.2007 14:31

Hervorragend,

konnte es leider immer noch nicht testen, weil ich noch nicht zu Hause
bin, werde ich aber nächste Woche tun.

Ich teste nächste Woche noch an einer kleinen Schaltung, mit der man
eine mmc-Karte an den ISP Stecker anschließen kann. Das Problem dabei
ist natürlich dass ein Pin (Chip Select) fehlt. Testhalber habe ich
einfach mal CS der MMC fest auf GND gelegt. Dabei muss man nach dem
Einschalten (Betriebsspannung) 2x, danach immer 8x Reset drücken, dass
der Zugriff auf die MMC klappt. Mal sehen ob man das softwaretechnisch
irgendwie gebacken kriegt. Ich denke dass das Problem in der fehlenden
Bytesynchronisation durch CS liegt. Ich werde nächste Woche mal
versuchen, die CS Leitung durch die Resetleitung über einen Transistor
zu schalten. Wenn das alles klappt mach ich eine Platine, auf der ein
MMC Sockel, die Spannungsbegrenzung /-regler, eine Resettaster, ein ISP
10 Pin und ein ISP 6 Pin Header drauf ist. So hat man ein einfaches,
günstiges kompaktes leicht zu handhabendes Programmiergerät. Ich muss
z.B. immer mein Notebook mitsamt Evertool und Kabel in den Heizraum
tragen um ein Update in meine Heizungs zu kriegen.

Noch mal zum MBR/VBR: Meinst du es ist noch möglich den Bootloader
selber erkennen zu lassen ob ein MBR vorhanden ist oder nicht und
entsprechend zu reagieren ?

Bis denn,
Stefan
Autor: Stefan (Gast)
Datum: 22.04.2007 14:34

Noch was:
Ich habe ja alles bisher nur mit einem Mega 16 gtestet. hast du für
Deinen Mega 32 auch diese CRC Erzeugungssoftware benutzt, und hat's da
funktioniert ?

Stefan
Autor: holger (Gast)
Datum: 22.04.2007 17:48

>Noch mal zum MBR/VBR: Meinst du es ist noch möglich den Bootloader
>selber erkennen zu lassen ob ein MBR vorhanden ist oder nicht und
>entsprechend zu reagieren ?

Mit bsFileSysType könnte man das machen, bzw. habe ich das
schon mal gemacht. Da steht eigentlich immer "FAT12", "FAT16" drin.
Bei meinen Karten jedenfalls. Wenn nix
drin steht ist das natürlich Panne :(

Sektor 0 auf bsFileSysType[0]=='F' und bsFileSysType[4]=='6'
checken. Stimmen beide nicht hat man einen MBR, einen
FAT12 oder FAT32 Bootsektor vor sich. Dann einfach auf Teufel
komm raus einen MBR annehmen, und Sektor an bootsecoffset
lesen. Dort wieder bsFileSysType[0]=='F' und bsFileSysType[4]=='6'
checken. Wird wieder nix gefunden wars ne FAT12 oder FAT32
formatierte MMC/SD. Oder gar nicht formatiert.

>Ich habe ja alles bisher nur mit einem Mega 16 gtestet. hast du für
>Deinen Mega 32 auch diese CRC Erzeugungssoftware benutzt, und hat's da
>funktioniert ?

Ja, klappt prima das Proggi.
Autor: holger (Gast)
Datum: 23.04.2007 21:40
Dateianhang: HolgerBootloader6.zip (31,3 KB, 196 Downloads)

Ich habe die einfache automatische MBR/VBR Erkennung für FAT16
eingebaut.
Man hat aber immer noch die freie Wahl in fat16.c :)

// !! define only ONE of these !!
//#define USE_MBR  //if card has a master boot record, partitiontable
//#define USE_VBR  //if sector 0 is a bootsector
#define USE_MBR_VBR_AUTO //auto mode

Dann habe ich noch ein paar Übergabeparameter entsorgt
die entweder gar nicht benutzt oder als Variable
bereits global definiert wurden. Ein wenig an Schleifen rumgefummelt.

Der Lowscore mit

#define USE_MBR_VBR_AUTO //auto mode

steht jetzt bei 1678 Bytes, und es funktioniert immer noch ;)
Autor: Jörg (Gast)
Datum: 24.04.2007 10:02

Ihr (speziell Holger) macht ja prima Fortschritte!

Was hältst Du davon, Deine "Erfolgsrezepte" in der Wiki-Seite zu diesem
Thread hinzuzufügen:
Beitrag "Tricks, wie ich mein Compilat kleiner kriege"
http://www.mikrocontroller.net/articles/AVR-GCC-Co...

Ich habe gesehen, das ihr -mtiny-stack verwendet, aber den Stack nicht
wie in dem Thread gelernt auf eine glatte Page initialisiert. Damit ist
der verbleibende Platz recht zufällig.

Die Option -mint8 wäre noch möglich, ich habe damit mittlerweile gute
Erfahrungen gemacht, wenn man die Wirkung im Hinterkopf behält und Typen
fester Größe auf <stdint.h> verwendet. Bringt ziemlich viel.

Unter 1 KiB wird der Code aber vermutlich nicht kommen.  :-(
Mit meinem Bootloader habe ich allerdings auch bei ca. 1600 Bytes
angefangen, jetzt bin ich auf 1014 runter. Nach Holgers aktuellen Tricks
muß ich nochmal Ausschau halten. Das man die Übergabeparameter besser
nicht modifiziert (sondern Kopien davon) war mir neu.

Dank und Gruß
Jörg
Autor: holger (Gast)
Datum: 24.04.2007 19:08

@ Jörg

>Die Option -mint8 wäre noch möglich,

Geht nicht :( Dann kennt er RAMPZ nicht mehr !
Das brauchen wir aber halt nun mal.
An die Compiler internen Header Files trau
ich mich besser nicht ran. Wer weiss was das wieder
für Nebenwirkungen (in meinen anderen Programmen) hat.

>Das man die Übergabeparameter besser
>nicht modifiziert (sondern Kopien davon) war mir neu.

Mir auch, aber die Pushs, Pops sind erheblicher weniger
geworden ! Klappt aber irgendwie nicht immer.
Möglicherweise stimmts auch einfach nur nicht.
Vieleicht waren es doch nur die anderen Optimierungen.

@ Stefan

Können wir die CRC auch von oben nach unten berechnen ?
Bringt nochmal 6 Bytes bei Umwandlung einer for()
in eine while() Schleife ;)
Autor: holger (Gast)
Datum: 24.04.2007 21:28
Dateianhang: HolgerBootloader7.zip (31,4 KB, 178 Downloads)

Jetzt gehts mit 1642 Bytes.

void flash_update(void)
erzeugte komischerweise 6 Pushs und 6 Pops.
Habs einfach in die main loop eingefügt. Pushs, Pops waren dann weg.

void fat16_readfilesector(uint16_t startcluster, uint32_t filesector)
benutzt keine absolute Sektornummer sondern eine relative
Sektornummer im File. Bei AVR/ATMega reicht da auch uint16_t ;)
void fat16_readfilesector(uint16_t startcluster, uint16_t filesector)

Statt break eine Schleife direkt mit return beendet.
Spart die Abfrage hinter der Schleife.

Ich denke das wars dann jetzt aber auch.
Autor: Jörg (Gast)
Datum: 24.04.2007 23:18

@Holger:

RAMPZ kenne ich als Mega8-User nicht. Keine Ahnung, warum das zum
Problem wird. Man kann verschiedene C-Files auch mit unterschiedlichen
Flags kompilieren, das Problem so vielleicht "auslagern".

Das mit den Übergabeparametern habe ich jetzt in meinem Bootloader
probiert, leider kein Effekt.  :-(

CRC rückwärts geht zwar, liefert aber ein anderes Ergebnis. Müßte die
PC-Software drauf Rücksicht nehmen. Ich vewende übrigens einen anderen
CRC, nicht aus den WinAVR-Headern. Der erzeugt kleineren Code:
// incremental CRC
static uint16_t crc16(const uint8_t byte, uint16_t crc)
{
    uint8_t i;

    crc ^= byte;
    for (i=8; i>0; i--)        
    {                        
        if (crc & 0x0001)        
            crc = (crc >> 1) ^ 0x8408; // reverse 0x1021 poly 
        else                      
            crc >>= 1;            
    }                        
    return crc;
}

  
Autor: Werner B. (Gast)
Datum: 25.04.2007 18:16

main.c: Mache die Funktion check_file() static inline. Wird nur ein mal
aufgerufen. Spart den call und den return. Evtl. kann auch die
Registerbelegung vom Compiler besser Optimiert werden.

dto. für wait_start_byte() in mmc_lib.c

mmc_lib.c: in mmc_start_read_block. Spart shift-loop
  adr <<= 1;
  
  cmd[0] = 0x40 + MMC_READ_SINGLE_BLOCK;
  cmd[1] = (adr & 0x00FF0000) >> 0x10;
  cmd[2] = (adr & 0x0000FF00) >> 0x08;
  cmd[3] = (adr & 0x000000FF);
  cmd[4] = 0;

Man kann sicher noch mehr "einmalig" aufgerufene Fuktionen als "static
inline" definieren und somit den call/return sparen wenn man (Igitt) die
anderen C Files included statt linkt.
Autor: holger (Gast)
Datum: 25.04.2007 18:49

@ Werner

Klasse Tipps. Code ist jetzt nur noch 1602 Bytes.
Besonders das einsparen von shifts bringts.

>dto. für wait_start_byte() in mmc_lib.c

Bringt leider nichts. Codesize unverändert. Vieleicht
besser Funktion im Code einsetzten wo sie benutzt
wird.

@ Jörg

Ich probiere auch deine CRC Routine auf jeden Fall noch aus.
Autor: holger (Gast)
Datum: 25.04.2007 21:27
Dateianhang: HolgerBootloader8.zip (17,2 KB, 174 Downloads)

Zusammenfassung:

@ Jörg
Deine CRC Routine brachte zwei Bytes Ersparnis.
Dafür das PC Programm umschreiben ? Hmm naja, vieleicht
später mal.

@ Werner

#include "fat16.c"
#include "mmc_lib.c"

in main.c bringt gar nichts :(

wait_start_byte() als Code einsetzen brachte nichts.
Code wurde größer.

Da filesector sich als uint16 erwiesen hat
konnten in fat16_readfilesector() nochmal
8 Bytes rausgeholt werden.

Stand der Dinge ist nun 1596 Bytes.

Noch jemand ne Idee ?
Autor: Stefan (Gast)
Datum: 27.04.2007 01:55

N'abend!

Hab gerade mal Deine letzte Version ausprobiert. Leider funktioniert der
Bootloader hier garnicht mehr :-( Wenn ich den Mega 16 zurücklese
stimmen die ersten 1024 Bytes mit der Updatedatei überein, aber danach
steht "Müll" anstatt 0en drin. Werde mal suchen woran das liegt...

Gruß
Stefan
Autor: Hagen Re (hagen)
Datum: 27.04.2007 09:53

man kann noch ca. 60 bytes sparen wenn man auf ISR's verzichtet, den GCC
Startup Code, den GCC bad_interrupt_vector entfernt und function main()
direkt am Reset Einsprung des Bootloaders platziert. Alle globalen
Variablen die initialisiert werden müssen (auf 0) muß man dann von Hand
initialisieren.

So mache ich dies bei meinem ATMega8 Bootloader (ähnlich AVR910) der
ohne Assembler (also pures C) zu benutzen in 256 Words reinpasst.

Gruß Hagen
Autor: holger (Gast)
Datum: 27.04.2007 17:00

@ Stefan

Also der Bootloader funktioniert bei mir noch.
Das per Bootloader geladene Programm auch, aber
du hast recht. Der Bereich bis Flashend ist nicht 0. Da wiederholt
sich immer wieder irgend ein Müll.
Autor: holger (Gast)
Datum: 27.04.2007 18:35
Dateianhang: HolgerBootloader9.zip (17 KB, 155 Downloads)

So, jetzt klappt es bei mir wieder
und die Daten hinter dem Testprogramm
sind wieder alle 0.

Es lag am einfügen von flash_update()
in die main loop. Sorry :(

1618 Bytes ist ja auch nicht schlecht.
Autor: holger (Gast)
Datum: 27.04.2007 21:56
Dateianhang: HolgerBootloader10.zip (31,3 KB, 250 Downloads)

Mein letzter Stand ist jetzt 1580 Bytes.

Inhalt vom ATmega nachdem der Bootloader geflasht hat
natürlich ausgelesen und angesehen. Das Testprogramm läuft.

Bis hier hin klappts.


Autor: Stefan (Gast)
Datum: 28.04.2007 14:53
Dateianhang: MMC_Bootloader.zip (86 KB, 290 Downloads)

Fein!

Nachdem ihr nun soviel Platz geschaffen habt, habe ich selbigen genutzt:
Der Bootloader unterstützt nun FAT16 und FAT12, so dass auch ältere,
kleine Karten, die eigentlich für fast nichts anderes mehr genutzt
werden können, verwendet werden können. Selbst wenn man per Hand auf
einer 16 MB Karte eine FAT16 Partition erstellt, baut Windows diese beim
Formatieren in eine FAT12 Partition um, so dass kleine Karten bisher
nicht verwendet werden konnten.

Weiterhin ist es nun möglich, des CS Pin der Karte fest auf GND zu
legen, so dass man eine Karte bei bestehenden Schaltungen einfach an den
ISP Stecker anschließen kann (bei 5 V Systemen natürlich mit weiterhin
mit Pegelanpassung dazwischen). Ich werde demnächst wie schon angedroht
eine kleine Platine fertig machen, auf der ein Kartensockel, ISP 6 Pin,
ISP 10 Pin, Resetknopf und Pegelwandler vorhanden ist.

Viel Spaß

Stefan

P.S. Den Bootloader im Anhang habe ich mit einer 512 MB Karte FAT16 mit
MBR, mit einer 16 MB Karte FAT12 mit MBR und einer 16 MB Karte FAT12
ohne MBR erfolgreich getestet.
Autor: Jürgen C (Gast)
Datum: 28.04.2007 20:59

Hallo Stefan,
das Projekt ist genau was ich suche
(Beitrag "Bootloader für Mega 128 mit SD Karte")
Wärst Du bereit mir eine Version für den MEGA 128 mit einer kurzen
Installationsanleitung zu erstellen?
Bei Interesse könnten wir uns über weiter Details unterhalten.
Meine Anwendung ist ein Hobbyprojekt, deshalb brauchst Du Dir über
Gewährleistung und Dergleichen keine Gedanken machen. Funktionieren
sollte
es aber schon.

Viele Grüße

Jürgen
Autor: Stefan (Gast)
Datum: 28.04.2007 21:02

Hab' mal eben aus dem Projekt einen kleinen Artikel gemacht:

http://www.mikrocontroller.net/articles/MMC/SD_Boo...
Autor: Stefan (Gast)
Datum: 29.04.2007 01:03

Hallo Jürgen,

Deiner Anfrage unter dem angegebenen Link entnehme ich, dass du Bascom
benutzt. Ich weiß leider nicht ob und wie man damit Memory-Sections
erstellen kann, denn das ist für das Hauptprogramm zwingend
erforderlich.
Den Bootloader für den Mega128 könnte ich Dir schon kompilieren, kann
ihn aber nicht testen, weil ich für mein STK500 nicht diesen
Adaptersockel für den Mega128 habe.

Gruß
Stefan
Autor: Jürgen C (Gast)
Datum: 29.04.2007 16:06

Hallo Stefan,

vielen Dank für Deine Hilfsbereitschaft.
Leider finde ich in Bascom keine Möglichkeit an
einer bestimten Adresse eine Memory-Sections zu erstellen.
Ich könnte aber die erforderlichen Daten von Hand an der
entsprechenden Stelle eintragen.
Zum Testen wäre es einfacher, wenn der Bootloader auch Versionsnummer
gleich der bereits installierten Version akzeptieren würde.
Wenn es dir nicht zu viel Mühe bereitet, könnten wir ja mal einen
Versuch machen.
Als Funktionsanzeige wäre bei mir der PORTB.4 geeignet.

Viele Grüße

Jürgen
Autor: Jürgen C (Gast)
Datum: 29.04.2007 16:28

Hallo Stefan,

Mmc_chip_select liegt auf Portb.0 (SS)
Mmc_data_input liegt auf Portb.3 (MISO)
Mmc_data_output liegt auf Portb.2 (MOSI)
Mmc_clock liegt auf Portb.1 (SCK)

Gruß

Jürgen
Autor: Stefan (Gast)
Datum: 29.04.2007 20:56
Dateianhang: MMC_Bootloader.zip (87,4 KB, 262 Downloads)

Im Anhang ist das Projekt nochmal, es gibt jeweils einen Unterordner
"atmega128". Kann jetzt aber nicht verspechen dass es klappt, weil ich
das mangels Mega128 nicht testen kann. Bitte sag' aber in jeddem Fall
bescheid.

Gruß
Stefan
Autor: Jürgen C (Gast)
Datum: 01.05.2007 15:26

Hallo Stefan,

leider beschreibt der Bootloader nur die ersten 64kb, d.h. er schreibt
64kb und die weiteren 64kb schreibt er nochmals über die ersten.
(So sieht es zumindest aus.)

Das Ergebnis sieht dann wie folgt aus:

00000 - 0F7F7 = 00

0F7F8 = 78
0F7F9 = 56
0F7FA = 34
0F7FB = 12
0F7FC = 00
0F7FD = 01

0F7FE - 0FFFF = 00

10000 = 10
10001 = 00
10002 = F8
10003 = 00

10004 - 1F7FF = FF (nicht beschrieben)

1F800 = 0C (Beginn des Bootloaders)

Ich vermute das RAMPZ Register muss noch entsprechend verwendet werden,
damit die richtige Page beschrieben wird.
(ATmega128 Datenblatt Seite 12
 RAMPZ0 = 0: lower 64 k
 RAMPZ0 = 1: higher 64 k wird von ELPM/SPM verwendet.)

Im Main Programm verwendest Du den Portb.4 für die Flash-LED. Leider
kann
ich hier keine Reaktion erkennen. Im Programmspeicher findet jedoch die
oben beschriebene Änderung statt.

Bei meiner Hardware sind folgende Ausgänge mit einer LED verbunden und
können für Kontrollanzeigen verwendet werden.
Pinf.3
Pinf.7
Pine.4
Pind.7
Pind.6
Pind.4
Ping.4
Pinb.4

Bei Portx.x = 0 leuchtet die LED

Viele Grüße


Jürgen

Autor: Stefan (Gast)
Datum: 03.05.2007 02:20

Hallo Jürgen,

habe den Fehler gefunden: memcpy_P funktioniert nur bis zur 64 k Grenze,
und einige Variablen müssen von 16 Bit auf 32 Bit erweitert werden. Ich
habe mir heute mal ein Design mit einem Mega128 aus der Bastelkiste
gekramt mit dem ich das testen kann. Im Moment liegt der Bootloader für
den Mega128 leider über 2048 Bytes, nämlich bei etwa 2150. Ist zwar
weiter kein Problem, weil der Mega128 Bootsections bis 8 k kann, aber
wäre schade die Bootloadersectiongröße wegen ein paar Bytes vergrößern
zu müssen. Wenn's soweit stell ich selbigen hier rein. Eventuell mach
ich ein Flag rein, mit dem man den FAT12 teil per Define abschalten kann
(also nur FAT16), so würde es wieder in die 2 k passen. Oder vielleicht
schauen die anderen Kolegen aus dem Thread nochmal drüber und kriegen
das Ding noch kleiner ;-)

Gruß
Stefan
Autor: Jürgen C (Gast)
Datum: 03.05.2007 22:46

Hallo Stefan,

mich stören die 2150 Byte nicht, da ich zur Zeit erst etwa 30% des
verfüg-
baren Speichers nutze. Es würden also auch die 64kb reichen.

Gruß

Jürgen.
Autor: Stefan (Gast)
Datum: 04.05.2007 22:29
Dateianhang: Bootloader_Mega128.zip (63,9 KB, 313 Downloads)

So, hier nochmal der Bootloader für den Mega128. Er ist nun für eine
Bootsectiongröße von 4096 Bytes (2048 Words) ausgelegt (auch im
Hauptprogramm beachten!) und ist 2106 Bytes groß. Vielleicht kriegt das
ja noch jemand um 58 Bytes kleiner...

Gruß
Stefan
Autor: Robert S. (razer) Benutzerseite
Datum: 04.05.2007 22:38

Danke fürs portieren des Bootloaders auf den Mega128. Ihr seit spitze :)
Hab leider noch keine Zeit gehabt, ihn anzupassen, da ich keine Hardware
noch habe. 58 Bytes kleiner wären halt schon schön ;)

mfg Robert
Autor: holger (Gast)
Datum: 04.05.2007 23:30

@ Stefan

Merkwürdig, einmal make clean, danach make all
und die Codesize ist nur noch 2046 ;)
Autor: Stefan Seegel (energizer)
Datum: 04.05.2007 23:55

holger:

hmmm, andere (ältere/neuere) Compilerversion ?
Autor: holger (Gast)
Datum: 05.05.2007 00:01

avr-gcc (GCC) 3.4.6

Ich hab dein makefile nicht verändert und auch (noch)
nicht am Quellcode rumgefummelt.
Autor: Stefan Seegel (energizer)
Datum: 05.05.2007 00:05

Hmm, war heute wohl zu lange an der Kiste gesessen, hab auch 3.4.6., und
nun auf einmal auch 2046 ?!
Naja, aber die LED Ansteuerung ist noch auskommentiert, mit LED
Ansteuerung sind's 2062. Naja, vielleicht gehen ja die 14 Bytes noch weg
wenn du was am Source machst ;-)

Gruß
Stefan
Autor: holger (Gast)
Datum: 05.05.2007 00:31
Dateianhang: new.zip (60,4 KB, 193 Downloads)

10 Bytes in mmc_lib gespart.

Gute Nacht ;)
Autor: Stefan Seegel (energizer)
Datum: 05.05.2007 09:48

/*
  for (i=0; i<6; i++)
  {//Send 6 Bytes
    spi_send_byte(cmd[i]);
  }
*/

        i=6;
  while(i)
  {//Send 6 Bytes
    spi_send_byte(cmd[i]);
    i--;
  }

Ähm, werden so die Kommandosequenzen nicht falsch rum gesendet ?

Stefan
Autor: holger (Gast)
Datum: 05.05.2007 11:19

Tschuldigung, war schon etwas spät :(

Sollte so aussehen:

        unsigned char *buf = cmd;

        i=6;
  while(i)
  {//Send 6 Bytes
    spi_send_byte(*buf++);
    i--;
  }
Autor: Stefan Seegel (energizer)
Datum: 05.05.2007 16:59

Ach Klasse, hab auch noch eine Kleinigkeit gefunden, nun sind's genau
2048 Bytes ;-)...

Noch was anderes: Wer ist "richtig fit" mit make ?
Die Frage ist ob make eine Differenz aus zwei Hex-Werten berechnen kann,
so könnte man
BOOTLDRSIZE = 0x800
#FLASHSIZE - BOOTLDRSIZE - 8
BOOTLDRINFOSTART = 0x37F8

z.B. ersetzten durch
FLASHSIZE = 0x4000
BOOTLDRINFOSTART = <0x4000 - 0x800 - 0x8> //Das müsste berechnet werden

?

Dann bräuchte man im makefile nicht mehr die Adresse der "Hundemarke"
selber ausrechnen...

Stefan
Autor: Werner B. (Gast)
Datum: 06.05.2007 12:19
Dateianhang: new2.zip (17,6 KB, 282 Downloads)

Nachdem ich nix besseres zu tun hatte (Steuer ist gemacht ;-) ), hab'
ich das ganze nochmals etwas "geschrumpft". Die Version aus "new.zip"
nun mit 1836 Bytes.

Allerdings nichts getestet, aber die Änderungen stammen im wesentlichen
aus meiner Portierung des MegaLOAD bootloaders auf den AVR-GCC.

Falls es Probleme gibt, bitte zuerst im Makefile:
Das "neue" gcrt1.S aus dem Makefile entfernen und die Zusätze von
"-nostartfiles -nodefaultlibs" bei den ALL_???FLAGS entfernen und
nochmals probieren und hier das Ergebnis posten.

P.S. Die Quelldateien sind "nicht aufgeräumt". Damit ist gemeint, daß
die Orginalzeilen nur auskommentiert sind.

Viel Spass

Werner
Autor: Maximilian Lang (Gast)
Datum: 27.06.2007 22:16

Hallo!

Ich bin in der uC Materie ganz ganz neu. Aber dieses Projekt finde ich
sehr interessant und möchte es von anfang an nutzen.

Habe ich das richtig verstanden, dass man den Chip für Softwareupdates
nicht mehr rausnehmen muss, sondern nur alte Karte raus neue Karte rein
fertig? Wenn ja wie geht das denn jetzt? Ist der Bootloader auf dem
Controller und der liesst sein Programm (zum Beispiel LED an) von der
MMC Karte???

LG Max
Autor: Stefan (Gast)
Datum: 28.06.2007 22:31

1. Ja, aber entweder Neustart oder Reset des µC ist nötig
2. Siehe im Datenblatt oder im Forum unter Bootloader
3. Ja, aber was meinst du mit "Programm zum Beispiel LED an" ?

Stefan
Autor: Maximilian Lang (Gast)
Datum: 30.06.2007 15:41

zu 3.) Wo liegt der Ausführcode? Wird der Code auf den uC gespielt oder
holt er sich den von der MMC Karte. Also muss man die MMC Karte drin
lassen oder kann man sie rausnehmen. Denn wenn nicht kann man ja größere
Programme schreiben! :)

Ich frage deswegen, weil ich dann die Möglichkeiten habe meinen Kollegen
einfach eine neue Hex zu schicken, die sie dann auf die MMC spielen
können.
Autor: Stefan (Gast)
Datum: 30.06.2007 15:50

AVRs können NUR Code aus dem Flash ausführen.
Aber egal wie, die Möglichkeit jemanden ein Update zu schicken welches
dieser dann auf eine MMC kopiert um ein neues Programm in den µC zu
bekommen hast du.

Stefan
Autor: Rudolph (Gast)
Datum: 06.07.2007 19:37

Hi!

Ich schaue mir das hier gerade so an und muss sagen, dass wäre genau das
richtige als Erweiterung für das MMC2IEC-Projekt bei dem ein Mega32 mit
SD-Karte als C64-Diskettenlaufwerk benutzt wird.

Ich habe noch nie Bootloader mit den AVR's benutzt.
Daher habe ich da mal ein paar Fragen.

Erstmal, wie sieht das aus, die Rede war hier nur von den alten
WinAVR Versionen, wie gut klappt das mit der 20070525?

>Nun kann das Hauptprogramm compiliert werden.
>Die entstehende .hex Datei (binary Format!)

Ja was denn nun, .hex oder binär?
Kann ich AVR-Studio überhaupt dazu bringen, ein .bin zu erzeugen oder
muss ich das nach dem compilieren noch konvertieren?

>wird anschließend noch mit dem Kommandozeilentool crcgen.exe behandelt
>(z.B. crcgen myflashfile.hex).

Wo finde ich das und gibt es das auch mit GUI für XP?
Und was macht das überhaupt genau? Einen Header mit der CRC32 davor
hängen?
Die .hex dabei in einen .bin konvertieren?

>Der Aufruf dieses Programmes kann auch vom makefile aus geschehen.

Da ich das AVR-Studio benutze, wie würde man das in die Projekt-Optionen
einfügen?

Sowieso, hat zufällig schon jemand eine Projekt-Datei für AVR-Studio
erstellt mit welcher man den Bootloader compilieren kann?

>Das Update benennt man am besten etwa in der Form MeinApparat-v1.0-bin,
>darf aber beliebig (lang) sein .

Was macht der Bootloader genau? Sucht nach der ersten .bin im
Hauptverzeichnis auf der Karte und schaut nach, ob die geeignet ist?
Daher ist der Name auch egal, weil sowieso nur nach der Erweiterung
gesucht wird?
Also muss man die alten Dateien auch immer löschen weil eine später
aufgespielte "xxx1.1.bin" nicht gefunden wird?

Gibt es eigentlich irgendeine Art von Lizenz für den Code?
Freeware? GPL? PuplicDomain?

Gruss, Rudolph
Autor: Rudolph (Gast)
Datum: 06.07.2007 20:06

Okay, crcgen gefunden, es hilft, wenn man nicht nur das letzte Archiv
runterlädt und aufmacht... :-)