Dieser Artikel wird z.Z. formatiert;
Die Datei Get_Flash_FileSector.bas ist noch nicht eingebunden !
Hier ist ein Multi-Achs-Controller zur interpolierenden Bahn-Steuerung von (z.Z.) bis zu 8-Achsen entstanden, ich habe ihn RoBo-mac genannt. Vom Roboternetz habe ich vieles gelernt, das in die Entwicklung eingeflossen ist; mit diesem Artikel möchte ich mich revanchieren. Sogar für die C+++ Fans habe ich einen Hinweis.
Inhaltsverzeichnis
Vorwort
Kaum war RoBo-mac fertig, kam die Frage auf, ob man so einen CNC- und Roboter Controller nicht auch Stand-Alone, ohne PC betreiben könne. Bevor es nun bald die SD-Card Variante gibt, mußte ich lernen "wie das geht": Nahezu alles was ich hier zu Papier gebracht habe, habe ich (viel zu lange) im Internet recherchiert aber nichts zusammenhängendes zum Thema, sondern nur Fragmente gefunden. Für dieses Tutorial selbst gebührt mir das Copyright, für den zusammengetragenen Code der begleitenden Tutorial-Datei (Get_Flash_FileSector.bas) nur bedingt.
Mit einigen Links verweise ich auf diejenigen, von denen ich "Honig gesaugt" habe – da vieles mehrfach und wiederholt zitiert wurde, ist jedoch nicht immer klar, wer der eigentliche Ur-Autor wirklich ist. Einige sind kommerzielle Anbieter, die durchaus sinnvolles zu verkaufen haben, andere hoch qualifizierte "Hobby-isten"; viel Hintergrund Know-how auch bei http://de.wikipedia.org/wiki/SD_Memory_Card.
SD und MMC Karten
SD, eigentlich SD-Memory Cards sind intelligente MCC Karten, hier ein Blick ins innere: http://de.wikipedia.org/w/index.php?title=Datei:Sdcard_panasonic64mb_inside_front.jpg&filetimestamp=20080829140929
SD steht für Security Digital – und kümmert sich um Urheberschutz und unerlaubtes Kopieren (DRMS = Digital-Rights-Management-Systeme). Dieses Security Know-how unterliegt strenger Geheimhaltung und deren Nutzung einer Lizenz. Wer bereit ist, hierfür mehrjährig mehrere 10.000 US$ Royalty jährlich zu zahlen, kann beantragen, als Geheimnisträger in den Club aufgenommen zu werden. Mehr dazu und vielleicht noch ein paar nützliche Infos unter http://www.sdcard.org
Für alle, die es lieber umsonst möchten, geht es hier weiter:
Ihre explosionsartige Marktakzeptanz verdankt die SD Karte einem genialen Marketing-Schachzug: Nicht alles unterliegt der Lizenz und Geheimhaltung, sondern wurde gezielt für Otto-Normalverbraucher zugänglich gemacht und veröffentlicht. SD-Karten können "Royalty free" über das SPI (Serial Peripheral Interface) angesprochen werden, hierfür stehen die Pin 1 bis 7 zur Verfügung (8 und 9 sind die "geheimen").
Pin-Belegung
Ein Anschlußbild der Pin-Belegung und sein Interface zum ATMega 128 findet sich unter "Schematic" hier: http://members.aon.at/voegel/index.html?Downloads.htm
Pin 8 der SD-Card liegt unmittelbar neben Pin 7, Pin 9 unter der abgeschrägten Ecke neben Pin 1.
SD und MMC Karten sind elektrisch und programm-technisch (zumindest für den veröffentlichten Teil) Pin-kompatibel. Mechanisch gibt es Einschränkungen. SD-Karten haben ein etwas dickeres Gehäuse als MMC-Karten. SD-Karten passen daher nicht in MMC-Steckplätze; umgekehrt ist dies bedingt möglich: Manchmal nur ein mal - falls man die kurze MMC nicht wieder aus dem langen SD Slot heraus bekommt !!!
SD-Schreibschutz
SD-Karten haben einen "Schreibschutz Schieber" der mit der eigentlichen SD-Technologie nichts zu tun hat, sondern im Slot einen mechanischen Kontakt gegen Masse betätigt. Der Schreibschutz kann also geräteseitig vom Microprozessor ausgewertet werden – muß aber nicht.
TTL-Kompatibilität
Elektrisch zählen SD und MMC Cards zur Flash-Technologie und arbeiten mit einer Systemspannung von 3,3 V (im Gegensatz zur TTL–Welt mit einer Systemspannung von 5 V). - Und damit sind sie mit "normalen" Mikroprozessoren nur bedingt kontaktfähig. Während man "von oben nach unten" mit 2 in Reihe geschalteten Dioden die Spannungssysteme angleichen kann, ist dies umgekehrt natürlich nicht möglich; die 3,3 V liegen zwar knapp über der Trigger-Schwelle des Mikroprozessor Einganges - aber eben sehr knapp.
- Dies und ähnliches sind ein ewiger Quell teuflischen Unheils: Tage habe ich schon verschwendet, um festzustellen, das das Netzteil "eigentlich reicht" (reichen müßte) – aber eben nur eigentlich, abgesehen von wenigen usec, die den Datentransfer torpedierten! Also als Low End Bastlerlösung, na ja:
Professionelles bietet http://www.display3000.de
dort gibt es für gute 20,- EU einen SD-Karten Connector mit Spannungs Level Shifter. Wer gerne SMD lötet, kann von Maxim den "MAX 3392 EEUD" hierfür einsetzen. Hier sein Datenblatt: http://www.datasheetcatalog.com/datasheets_pdf/M/A/X/3/MAX3392EEUD.shtml
SD/MMC Karten und C+++
Bevor wir nun zu BASCOM kommen noch der Tip für die C-Fans: Ulrich Radig (http://www.ulrichradig.de/home/index.php/avr/mmc-sd ) bietet einen SD-Kartenleser von Roland Riegel (http://www.roland-riegel.de/sd-reader/index.html ) mit detaillierten Informationen aus der C+++ Welt. Da dies nicht meine Welt ist, kann ich nur den Quell-Hinweis geben.
Ein Vorschlag zur Low End Hardware Verdrahtung auf Basis eines "alten ISA Slots" und ohne den o.g. Spannungs Level Shifter findet sich ebenfalls bei Ulrich Radig.
BASCOM, SD/MMC und andere Flash-Karten
Es gibt mit BASCOM zwei Möglichkeiten, Daten auf der (SD/MMC)-Karte zu speichern bzw. zu lesen:
- zum einen mit AVR-DOS
- zum anderen mit DriveWriteSektor() bzw. DriveReadSektor()
Beide sind Bestandteile von BASCOM - und für den nicht kommerziellen Gebrauch ist AVR-DOS bereits Bestandteil der BASCOM Lizenz. Da das ganze recht strukturiert angelegt ist, beherrscht BASCOM noch einige andere Karten wie z.B. CF und wohl auch richtige Laufwerke. An Stelle der hier und im folgenden verwendeten "MMC.LBX / MMC.LIB / Config_MMC.bas" sind dann die entsprechenden Pendants einzusetzen.
Schlüsselfunktion im BASCOM-Dateimanagement hat der Befehl "Initfilesystem()"; er liest den Master-Boot Record, die FAT etc. und muß vor allen anderen Datei-Befehlen als erster aufgerufen werden. Wird nach einem "Initfilesystem()" die Speicherkarte gewechselt, so geht alles durcheinander! Es macht also Sinn, über den Slot-Kontakt (Interrupt oder Polling) zu prüfen, ob die Karte seit dem letzten "Initfilesystem()" nicht gezogen wurde.
- Hier ein Code-Schnipsel, der allerdings nur überprüft, ob auf dem Entwicklungsboard überhaupt die Karte gesteckt ist. Bei den ersten Gehversuchen und Software Tests war ich ins stolpern geraten; das Aufstehen dauerte mehrere Stunden, bis ich merkte, daß die Karte nicht gesteckt war!
'Hardware: Mega 128 / LCD-Display 4 * 20 / SD-Kartenhalter von Display 3000 Config Lcdbus = 4 '4-bit Step_Step_Mode Config Lcd = 20 * 4 '20x4 LCD display Config Lcdpin = Pin , Db4 = Porte.4 , Db5 = Porte.5 , Db6 = Porte.6 , Db7 = Porte.7 , E = Porte.3 , Rs = Porte.2 Const Lcd_line1 = "" Const Lcd_line2 = "CopyRight:" Const Lcd_line3 = " www.RoBo-mac.de" Cls : Cursor Off Noblink Locate 1 , 1 : Lcd Lcd_line1 Locate 2 , 1 : Lcd Lcd_line2 Locate 3 , 1 : Lcd Lcd_line3 'Special Function (Display 3000) Config Pinb.4 = Input 'Pad Nr. 9 Cardsensor Config Pinb.5 = Output 'Pad Nr.10 SD-Card active (High) / inaktiv (Low) Config Pinb.6 = Input 'Pad Nr.11 Writprotect active (Low) / inaktiv (High) Config Pinb.7 = Output 'nicht belegt Portb = &B01110000 If Pinb.4 = 1 Then Locate 4 , 1 : Lcd "Card NO" Else Locate 4 , 1 : Lcd "Card YES " If Pinb.6 = 1 Then Locate 4 , 11 : Lcd "read only" Else Locate 4 , 11 : Lcd "read/write" End If End If
- Nach einem "Initfilesystem()" weiß BASCOM, wie die Flash-Card organisiert ist.
Während AVR-DOS sich um alles kümmert, wird beim direkten Zugriff jeder Datentransfer per DriveWriteSektor() bzw. DriveReadSektor() über Sektoren blockweise abgewickelt. Um an bestimmte Informationen und ihre Bytes heranzukommen müssen wir nur wissen, in welchem Sektor sie "wo" stehen. NUR – und darum dreht es sich hier.
AVR-DOS
kann Files erzeugen, öffnen, überschreiben, Daten anhängen usw. Es ist ausgesprochen mächtig, braucht aber auch mächtig viel System Ressourcen (Empfehlung Mega 128). Was es kann, findet sich auf der Autoren-WebSite: http://members.aon.at/voegel/index.html?Downloads.htm unter "Interactive File System Interpreter with Description of commands"; laden Sie beide herunter, wir brauchen sie gleich!
Das ist nicht die BASCOM-Website (www.mcselec.com), sondern die von Josef Franz Vögel, der viel zu BASCOM beigesteuert hat. Gezählt habe ich ca. 70 Befehle "aus der guten alten DOS-Zeit" und darüber hinaus bis zur FAT 32 !
Um SD/MMC Karten mit AVR-DOS aus dem eigenen Programm zu lesen müssen sich im BASCOM - LIB Ordner die Dateien
- AVR-DOS.LBX
- MMC.LBX
befindenden sowie die Dateien
- CONFIG_AVR-DOS.bas
- CONFIG_MMC.bas
in den Ordner kopiert werden, indem sich das eigene Projekt befindet. Mit dem Befehl
- $include "Config_AVR-DOS.BAS"
- $include "Config_ MMC.BAS"
im eigenen Programm werden sie beim compilieren eingebunden.
Alternativ hierzu kann der Code von CONFIG_AVR-DOS.bas und Config_MMC.bas ins eigene Programm kopiert werden, die beiden "$Include Befehle entfallen dann. Beide Wege sind im Ergebnis absolut gleichwertig.
- In den Internetforen "geistern" eine Menge von Beiträgen herum, die den 2ten Weg des Kopierens genutzt haben – und sich gelegentlich als "Neuer Lösungsansatz" präsentieren. Wenn in diesen Quellcodes Variablen der (schwer lesbaren) Art " Cperrdrivereadresponse / Cpsectorsperclusternotsupported etc." enthalten sind, so stammen die Ur-Lösungsansätze mit hoher Wahrscheinlichkeit aus der Schmiede von Josef Franz Vögel.
Machen wir es uns nochmals bewußt:
Ein DOS findet Dateien, weil die von ihr befragte FAT weiß, wo und wie der Dateiinhalt (ggf. auch noch fragmentiert) gespeichert ist.
DOS-Interpreter, ein Schnupper-Kurs
Über das Terminalprogramm von BASCOM (Aufruf mit Control T) und eine COM Verbindung zwischen PC und Mikroprozessor können wir jetzt die Flash-Card ansprechen.
- Installations-Info am Ende von Test_DOS_Drive.bas zu File System Interpreter beachten, sowie die Datei FS-Interpreter.bas in den Ordner kopieren, indem sich das eigene Projekt befindet.
- Tip
- Für die ersten Gehversuche recht hilfreich ist die Datei Test_DOS_Drive.bas (Download Vögel, s.o.), in die man weit oben meinen Karten-Prüf-Schnipsel einbauen sollte.
- Ich habe mit dem PC die Datei "Kurztext.txt" mit dem sinnvollen Inhalt:
- Das ist ein Kurztext
- 123456789
erzeugt und in die erste Verzeichnis Ebene kopiert (um es lebensnah zu gestalten, befinden sich hier noch einige andere Dateien und Verzeichnisse).
AVR-DOS Directory
Mit diesen Befehlen finden sich die Dateien im Directory, die wir zuvor mit dem PC geschrieben haben.
- TYPE Kurztext.txt
- zeigt den Inhalt der Datei
- DUMP Kurztext.txt
- das Hex-Dump hierzu
Das ist vielleicht schön aber sinnlos! Letztendlich wollen wir Daten per Mikroprozessor sammeln, auf der Flash-Card speichern und diese am PC auswerten oder mit Daten, die ein PC-Programm geschrieben hat, den Mikroprozessor etwas tun lassen.
AVR-DOS File
Studieren wir hierzu die Befehle der Gruppe File open, read and write
- Die meisten dieser Befehle arbeiten nicht mit dem Datei-Namen, sondern einer File-Nummer – und die wissen wir nicht.
- Die File-open Befehle geben freundlicher weise dies File-Nummer zurück, wenn wir sie mit dem Namen aufrufen
- FOB Kurztext.txt
- bringt z.B. 128 (kann natürlich auch eine andere Nr. sein)!
- FILEINFO 128
- zeigt den Hex-Dump der Datei Kurztext.txt und einige Informationen,
- u.a. Sector#: z.B. 3200 (kann natürlich auch eine andere Nr. sein)!
Nun wird's spannend: Unter Drive/Card sector finden wir den Befehl SD, und wahrlich:
- SD 3200
- zeigt den Hex-Dump der Datei Kurztext.txt
- CLOSE 128
- schließt die Datei Kurztext.txt
- FILEINFO 128
- meldet: No Filehandle for 128 found
aber
- SD 3200
- zeigt trotzdem den Hex-Dump der Datei Kurztext.txt
wir probieren
- RL 128
- und erhalten Error: 67 (die Datei ist ja auch geschlossen)
also nochmals
- FOB Kurztext.txt
- bringt z.B. 128 (kann natürlich auch eine andere Nr. sein)!
- Das erste RL 128
- zeigt die Zeile 1 "Das ist ein Kurztext"
- Das zweite RL 128
- zeigt die Zeile 2 "123456789"
- Das dritte RL 128
- bringt die Fehlermeldung DOS Error: 1
- Nun ja, die Datei hat nur 2 Zeilen!
AVR-DOS Error-Code
Falls irgendwas schief läuft, erhalten wir eine Information:
- DOS Error: xxx
- Diese Nr. (xxx) bezieht sich auf ein DOS eigenes Nummernsystem, daß mit den BASCOM Error-Nr. nichts zu tun hat. Es ist unter AVR-DOS beschrieben.
BASCOM, direkter Sektor Zugriff
Mit deutlich weniger Möglichkeiten, dafür aber ohne den Zeitfresser-Umweg über die FAT arbeiten die Befehle
- DriveWriteSektor() und DriveReadSektor() etc;
- sie lesen/schreiben einen vollständigen Sector (512 Byte). Ob dies der richtige Sector ist und ob er überhaupt beschrieben werden darf, hierum kümmern sich diese Befehle nicht; dafür gibt es das DOS! - Oder wir müssen selber wissen, was wir tun!
Beide Befehle arbeiten mit der gleichen Syntax:
- Fehler = DriveReadSector(SRAM, Flash) -- Read schiebt von Flash nach SRAM
- Fehler = DriveWriteSector(SRAM, Flash) -- Write schiebt von SRAM nach Flash
- Fehler
- Wenn kein Fehler auftritt, ist der Rückgabewert 0 und die Welt in Ordnung.
- Ist der Rückgabewert <> 0 , so gibt die ERROR-Tabelle Auskunft, was schief gelaufen ist. Ob und wie wir dies Programm technisch auswerten bleibt uns überlassen.
- SRAM
- Ist die Adresse einer Variablen im SRAM.
- Unangenehm, die wissen wir nicht.
- Wir wissen nur,
- wie die Variable heißt, weil wir ihr mit Dim Buffer As String * 512 ein Plätzchen von 512 Byte im SRAM zugewiesen haben.
- Mit Pointer = Varptr(buffer) schreibt BASCOM die SRAM-Adresse von "Buffer" in die Variable Pointer.
- Flash
- Ist der Sector auf der SD/MMC-Karte, den wir bearbeiten wollen.
- So einen komfortablen Befehl wie Varptr() für die SRAM-Adresse gibt es hierfür leider nicht – und darum habe ich dieses Tutorial und die Datei Get_Flash_FileSector.bas geschrieben. Das ist eine Art Kochbuch zum Thema!
- Get_Flash_FileSector.bas baut auf Test_DOS_Drive.bas (Download Vögel, s.o.) und vielen Fragmenten, die ich in Internet-Foren gefunden habe, auf. Daher nochmals: Für die Formulierungen gebührt mir das Copyright, für den Code der begleitenden Tutorial-Datei nur sehr bedingt.
FAT, Sektoren und Cluster
Damit es nicht zu einfach wird:
Mehrere Sektoren bilden einen Cluster. Bei den SD-Cards sind es wohl meist 32. Wieviel Sektoren das je Cluster wirklich sind, bestimmt das Betriebssystem entsprechend dem eingesetzten Speichermedium. Wichtig ist: DOS / Windows speichert eine Datei immer in ganzen Clustern.
Wenngleich die folgende Tabelle nicht mehr ganz taufrisch ist, erkennen wir, daß eine Cluster Größe von 32 Sektoren nicht zwangsläufig eine FAT 32 erfordert.
Laufwerksgröße FAT-Typ Sektoren Cluster- (logischer Datenträger) pro Cluster größe ---------------- -------- ----------- ------- (Disketten) 360K 12-bit 2 1K 720K 12-bit 2 1K 1.2 MB 12-bit 1 512 Byte 1.44 MB 12-bit 1 512 Byte 2.88 MB 12-bit 2 1K (Festplatten) 0 MB - 15 MB 12-bit 8 4K 16 MB - 127 MB 16-bit 4 2K 128 MB - 255 MB 16-bit 8 4K 256 MB - 511 MB 16-bit 16 8K 512 MB - 1023 MB 16-bit 32 16K 1024 MB - 2048 MB 16-bit 64 32K
- Auf einem MS-DOS-Datenträger wird einer Datei mit einer Größe von 1 Byte 1 Cluster Speicherplatz zugeordnet, wobei der nicht genutzte Teil des Clusters verschwendet ist. Einer Datei, die gemäß ihrer Größe 3,2 Cluster benötigt, werden 4 Cluster zugewiesen. Insgesamt folgt daraus, daß kleinere Cluster weniger Verschwendung zur Folge haben. Quelle und mehr dazu unter: http://support.microsoft.com/kb/67321
Der Begriff FAT16 steht für ein 16 Byte Adressiersystem der Cluster, FAT32 für ein 32 Byte Adressiersystem. Mehr hierzu unter: http://users.iafrica.com/c/cq/cquirke/fat.htm#EntryStructure ebenfalls hilfreich: http://www.dewassoc.com/kbase/index.html – Aber sehr mächtig !!!
Während innerhalb eines Clusters die Sektoren immer fortlaufend sind, können die Cluster mehrerer Dateien im Laufe der Zeit in Ihrer Reihenfolge gemischt (fragmentiert) werden.
Immer wieder Jungfrau
Wenn wir Dateien mit dem PC auf der Flash-Card speichern, kann es passieren, daß sie nicht zusammenhängend in fortlaufenden Clustern und mithin Sektoren, sondern fragmentiert gespeichert werden. AVR-DOS findet die Zusammenhänge; die Drive...Sector() Befehle nicht. Um das Problem zu umgehen, empfiehlt es sich frisch formatierte SD/MMC zu verwenden und für den Datentransfer vom AVR zum PC zuvor ein Dummy-File (lieber zu groß als zu klein) als Platzhalter anzulegen.
Ein Formatierer befindet sich hier: http://www.sdcard.org/consumers/formatter/#download Der Formatierer hat eine "Qick" Funktion. Die löscht zwar nicht den Dateninhalt, sondern lediglich die FAT etc. dies ist jedoch völlig ausreichend. Alternativ hierzu, kann eine vorhandene Datei mit den Windows – üblichen Befehlen gelöscht werden – in jedem Falle muß das Stammverzeichnis im Explorer als "leer" angezeigt werden.
Hier ein Dummy-Datei Generator http://www.raylow.com/2009/01/dummy-file-generator-v200.html Dieses Dummy-File können wir umbenennen. Wenn es das erste ist, daß wir geschrieben haben, befindet es sich sein Start-Sektor (bei einer FAT 32) mit hoher Sicherheit an Sector# 512.
- Ob 512 wirklich der Start-Sektor ist, wird mit Get_Flash_FileSector.bas oder Test_DOS_Drive.bas unter
- "Data First Sector:" ausgewiesen.
Programm technisch kann dies vieles vereinfachen.
System Resourcen
Der Mega128 hat ja schon eine ganz ansehnliche Speicherkapazität. Trotzdem:
Compilieren wir die Datei Get_Flash_FileSector.bas mit Function_Switch = 1 so belegt dies 32% seines Programm-Speichers; die beiden anderen Varianten (2 bzw.3) liegen um 5% bzw. 1%. Aber: Function_Switch = 1 bzw. 2 haben einen nahezu gleich großen SRAM Bedarf von gut 3.000 Byte und belegen rund 75 % seiner Kapazität.
Und nun das Wunder:
- Function_Switch = 3 frißt nur knapp 800 SRAM Byte, denn die Sektor-Befehle benötigen kein: Config_AVR-DOS.bas !!!
BASCOM ohne DOS
Diesen Vorteil erkaufen wir uns damit, daß wir letztendlich auf der Flash-Card nur eine Datei (mit dem Start-Sektor 512) nutzen können. Natürlich können wir mehrere Flash-Cards (jeweils eine je Datei) verwenden, aber da kann wohl beim Verwechseln einiges Unglück passieren – denn den Dateinamen können wir so nicht lesen.
Zwar weist der Root Start Sector 480 einiges aus, was an den Dateinamen entfernt erinnert – aber hier wird es kryptisch; das packt nur noch AVR-DOS. Spätestens bei langen Dateinamen (also denen mit mehr als 8-Buchstaben) steigt aber auch AVR-DOS aus.
Lange DateiNamen & Date/Time
Es geht trotzdem: Zugegeben, etwas tricky und nur, wenn der AVR eine vom PC geschriebene Datei auswerten soll, die wir kennen – weil wir sie selbst erzeugt haben. Wenn das PC-Programm die ersten (z.B. 64) Byte des Sektors 512 mit dem Filename und dem Zeitstempel belegt, können wir diese gezielt auslesen und über das LCD oder das Terminal-Programm anzeigen. Und hierfür brauchen wir noch nicht mal eine zusätzliche Variable im SRAM, - Overlay macht's möglich!
- Wenn Sie mit der DIM Overlay-Option nicht vertraut sind, sollten Sie unbedingt das BASCOM Manual hierzu und die Artikel Bascom Speicherstrukturen und Bascom UART Inputlesen.
Get_Flash_FileSector.bas zeigt im Gültigkeitsbereich des Compiler-Schalters 3 ein Code-Beispiel für einen Dateinamen von max. 40 Zeichen zuz. Extension (40.3).
Tutorial-Datei
Eigentlich wollte ich die Tutorial-Datei als Download einstellen, - habe aber nicht gefunden, wie das geht. Wenn das jemand weis, wäre ich für eine Info --> NLB@Manager-OnWeb.de dankbar.
Zunächst daher etwas umständlicher im Copy und Paste Verfahren:
Get_Flash_FileSector.bas
'CopyRight 'Dipl.-Ing. Norbert L. Brodtmann , Gütersloh Germany 'This program is wrote to become familiar with SD-Card technologies 'in order to integrate it in my 8-acis Robotic-Controller (www.RoBo-mac.de). 'It is based on J.F. Vögel's AVR-DOS and uses parts of its code issued in his product documentation. 'It may be used in accordance of BASCOM's and AVR-DOS's license policy and agreement. '* This program returns the Start-Sector Number of any file - short filenames (8.3) - stored in a Flash-Card ' in order to use it with direct access of the commands DriveWriteSektor() / DriveReadSektor() etc. '* It also gives output to measure Transfer-Time; to benefit this, you need an oscilloscope. '* You can use this program just to become familiar with SD-Cards too ' or include parts in your application. Therefore it is divvied in 5 parts. 'Part 1 'Declaration based on the used Hardware (Mega 128 / LCD 4 x 20 / SD-Card board of Display 3000). 'Part 2 'Additional declaration of including AVR-DOS and the type of Flash-Card used (FC, SD/MCC etc. ). 'Please note: You have to adapt the "config_CARD.bas" (for example Config_MMC.bas) to your system too. 'There is a (Compiler-) Function-switch to select of the following possibilities. 'Function_1 Test DOS-Commands using COM/TERMINAL in dialog 'Function_2 Running Part 3 to 5 'Function_3 Direct Sector Access and measurement of transfer-time by using an oscilloscope (Bort B.7) ' In addition you will find a trick to read a file's ' - (Long)-Name (up to 40 Characters + Extension = 44 in total incl. "dot") and its ' - Date/Time-Stamp. 'Function_1/2 needs a SRAM Size > 3k, Function_3 less than 1k 'Part 3 'A "GOSUB" Routine_fileinfo 'Asking for the files name (8.3) and searching information concerning this file (also including the Sector#) 'Part 4 'A "GOSUB" Routine_sector_select 'using the Sector# with the command DriveReadSektor() as a "how to do" example 'Part 5 'A "GOSUB" Routine_transfer_time_1 'to measure transfer time. Bort B.7 toggles with every DriveReadSektor() command. 'Using an oscilloscope you will get an frequency. Each period consists the time to read two sectors! 'This Routine is based on something similar I found in the Internet several times '- however I do not know the Copyright owner, I suppose it is shareware. 'Please note: 'There is a tutorial (in German language) concerning these items at ...... '--- Part1 --------------------------------------------------- $regfile = "m128def.dat" 'ATmega128 $crystal = 16000000 '--- Config Lcdbus = 4 '4-bit Step_Step_Mode Config Lcd = 20 * 4 '20x4 LCD display Config Lcdpin = Pin , Db4 = Porte.4 , Db5 = Porte.5 , Db6 = Porte.6 , Db7 = Porte.7 , E = Porte.3 , Rs = Porte.2 Const Lcd_line1 = "Get_Flash_FileSector" Const Lcd_line2 = "CopyRight:" Const Lcd_line3 = " www.RoBo-mac.de" Cls : Cursor Off Noblink Locate 1 , 1 : Lcd Lcd_line1 Locate 2 , 1 : Lcd Lcd_line2 Locate 3 , 1 : Lcd Lcd_line3 'Special Function (Display 3000) Config Pinb.4 = Input 'Cardsensor Config Pinb.5 = Output 'SD-Card active (High) / inaktiv (Low) Config Pinb.6 = Input 'Writeprotect active (Low) / inaktiv (High) Config Pinb.7 = Output 'Toggel Portb = &B01110000 If Pinb.4 = 1 Then Locate 4 , 1 : Lcd "Card NO" End Else Locate 4 , 1 : Lcd "Card YES " If Pinb.6 = 1 Then Locate 4 , 11 : Lcd "read only" Else Locate 4 , 11 : Lcd "read/write" End If End If '--- Part2 --------------------------------------------------- ' Adjust HW Stack, Soft-Stack and Frame size to 128 minimum each!!! $hwstack = 128 $swstack = 128 $framesize = 128 Enable Interrupts $baud1 = 9600 Open "Com1:" As Binary As #1 ' use #1 for fs_interpreter 'Include here your driver for Compactflash/HardDisk or other '$include "Config_CompactFlash_M128.bas" '$Include "Config_HardDisk_M128.bas" $include "Config_MMC.bas" 'Select a function 'Const Function_switch = 1 'SRAM ca. 3340 / FS_Interpreter.bas active 'Const Function_switch = 2 'SRAM ca. 3030 / will use Part 3 to 5 Const Function_switch = 3 'SRAM ca. 780 / Just direct Sector Access #if Function_switch = 3 'Direct Sector Access and measurement of transfer-time 'Does not neet: Config_AVR-DOS.bas !!! Dim Ptr As Word 'Address-Pointer SRAM Dim Buffer As String * 512 Dim Mmc_error As Byte Dim Sector_now As Word Ptr = Varptr(buffer) For Sector_now = 512 To 10511 '512 is normaly the first Data-Sector 'Sector_now = 512 'endles 'Toggle Portb.7 Set Portb.7 Mmc_error = Drivereadsector(ptr , Sector_now) 'Ca. 1,37 msec HW / 6,05 msec SW per Sector 'Mmc_error = Drivewritesector(ptr , Sector_now) 'Ca. 1,83 msec HW / 7,5 msec SW per Sector Reset Portb.7 ''( 'The following code will only work fine, if these information '- are specially placed by the PC-Program writing the file '- to a very fresh formatted SD-Card!!! Dim Datei_name As String * 45 At Buffer + 00 Overlay 'File Name max: (40.3) Dim Datei_date_time As String * 19 At Buffer + 45 Overlay Dim Interim As Byte Dim Interim_2 As Byte At Mmc_error + 00 Overlay If Sector_now = 512 Then Waitms 1500 Locate 4 , 1 : Lcd Spc(20) Locate 4 , 1 : Lcd Mid(datei_name , 1 , 20) Wait 1 Interim_2 = Len(datei_name) 'Shiftlcd Left moves whole display, therefore If 20 < Interim_2 Then Interim_2 = Interim_2 - 19 For Interim = 2 To Interim_2 Locate 4 , 1 : Lcd Mid(datei_name , Interim , 20) Waitms 200 Next Wait 1 End If Locate 4 , 1 : Lcd Mid(datei_date_time , 1 , 19) + " " Wait 1 End If '') Next End '------------------------------------------------------------- #else $include "Config_AVR-DOS.bas" 'Include AVR-DOS Configuration and library Dim Btemp1 As Byte Print #1 , "Wait for Drive" If Gbdriveerror = 0 Then Print #1 , "Init File System ... "; Btemp1 = Initfilesystem(1) ' Partition 1 ' use 0 for drive without Master boot record If Btemp1 <> 0 Then Print #1 , Print #1 , "Error: " ; Btemp1 ; " at Init file system" Print #1 , End Else Print #1 , " OK" Print #1 , "Filesystem: " ; Gbfilesystem Print #1 , "FAT Start Sector: " ; Glfatfirstsector Print #1 , "Root Start Sector: " ; Glrootfirstsector Print #1 , "Data First Sector: " ; Gldatafirstsector Print #1 , "Max. Cluster Nummber: " ; Glmaxclusternumber Print #1 , "Sectors per Cluster: " ; Gbsectorspercluster Print #1 , "Root Entries: " ; Gwrootentries Print #1 , "Sectors per FAT: " ; Glsectorsperfat Print #1 , "Number of FATs: " ; Gbnumberoffats Print #1 , Print #1 , End If Else Print #1 , "Error during Drive Init: " ; Gbdriveerror End End If #endif #if Function_switch = 1 Config Clock = Soft Config Date = Mdy , Separator = . $include "FS_Interpreter.bas" 'No GOSUBs allowed, (DIM conflicts) #endif #if Function_switch = 2 Gosub Routine_fileinfo Gosub Routine_sector_select Gosub Routine_transfer_time_1 #endif End #if Function_switch = 2 '--- Part3 --------------------------------------------------- Routine_fileinfo: Dim File_name As String * 12 Dim Pbfilenr As Byte Dim Lltemp1 As Long Dim Lbfilenumber As Byte Dim Lbfilemode As Byte Dim Lwfiledirentry As Word Dim Llfiledirsectornumber As Long Dim Llfilefirstcluster As Long Dim Llfilesize As Long Dim Llfileposition As Long Dim Llfilesectornumber As Long Dim Lbfilebufferstatus As Byte Dim Lwfilebufferaddress As Word Dim Sector_start As Long Pbfilenr = 127 'use 127, to avoid conflicts with auto generatet numbers from FreeFile (128 to 255) File_select: Input "Select FileName (8.3) / Type END to finish program " , File_name Locate 2 , 1 : Lcd "File: " Locate 2 , 7 : Lcd File_name Locate 3 , 1 : Lcd " " If Ucase(file_name) = "END" Then Print #1 , "Program finished" Locate 3 , 1 : Lcd "Program finished" End End If Open File_name For Input As #pbfilenr Loadadr Pbfilenr , X ld r24, X !Call _GetFileHandle brcc PrintFileInfo1 rjmp PrintFileInfoError Printfileinfo1: Loadadr Lbfilenumber , X ldi r24, 25 !Call _Mem_Copy Loadadr Lwfilebufferaddress , X st X+, zl st X+, zh Print #1 , Print #1 , "File " ; File_name Print #1 , "Handle#: " ; Lbfilenumber Print #1 , "Open mode: " ; Bin(lbfilemode) Print #1 , "Dir Entry#: " ; Lwfiledirentry Print #1 , "Dir Sector#: " ; Llfiledirsectornumber Print #1 , "First Cluster#: " ; Llfilefirstcluster Print #1 , "Size: " ; Llfilesize Print #1 , "Position: " ; Llfileposition Print #1 , "Sector#: " ; Llfilesectornumber Print #1 , "Buffer Status: " ; Bin(lbfilebufferstatus) Lltemp1 = 0 Sector_start = Llfilesectornumber Close #pbfilenr Locate 3 , 1 : Lcd "Sector#:" Locate 3 , 10 : Lcd Sector_start Return Printfileinfoerror: 'Print #1 , "No Filehandle for " ; Pbfilenr ; " found" Print #1 , "FileName < " ; File_name ; " > Not Found " Print #1 , Locate 3 , 1 : Lcd " Not Found " Goto File_select '--- Part4 --------------------------------------------------- Routine_sector_select: Dim Ptr As Word 'Address-Pointer SRAM Dim Buffer As String * 512 Dim Mmc_error As Byte Dim Sector_now As Long Dim Sector_size As Long Dim Sector_max As Long Sector_size = Llfilesize Shift Sector_size , Right , 9 'Division 512 Byte/Sector 'Btemp1 = Llfilesize \ 512 'does not work correct, therefore: Shift Sector_size , Left , 9 If Sector_size < Llfilesize Then Shift Sector_size , Right , 9 Sector_size = Sector_size + 1 Else Shift Sector_size , Right , 9 End If Ptr = Varptr(buffer) 'SRAM Adr von Buffer Mmc_error = Drivereadsector(ptr , Sector_start) Print Print Print "SectorSize: " ; Sector_size Print "Read Start-Sector(" ; Sector_start ; ") ok." Print Print Buffer Print Return '--- Part5 --------------------------------------------------- Routine_transfer_time_1: Print "For 'Transfer-Time' measurement with an oscilloscope use toggling PortB.7" Print "- 1 Period represents 2 Sectors" Print Print "Test the 'Transfer-Time' " Print " - for Read and Write (to be choosen by changing block-marker)" Print " - with and without the Print-Commands" Print " - with Soft/Hard SPI. To do so, select used SPI in File Config_CARD.bas" Print Input "To start the test, strike ENTER/RETURN now ! / Type END to finish program" , File_name Print Print If Ucase(file_name) = "END" Then Print #1 , "Program finished" Locate 3 , 1 : Lcd "Program finished" End End If Ptr = Varptr(buffer) Sector_max = Sector_start + Sector_size Sector_max = Sector_max - 1 If Gbdriveerror = 0 Then Mmc_error = Driveinit() If Mmc_error = 0 Then Print "Driveinit Ok. " For Sector_now = Sector_start To Sector_max Toggle Portb.7 'Read ''( Mmc_error = Drivereadsector(ptr , Sector_now) If Mmc_error = 0 Then Print "ReadSector(" ; Sector_now ; ") ok." Print Buffer Else Print "Error during ReadSector(" ; Sector_now ; ") : " ; Mmc_error End If '') '---------------- 'Write '( ' ' Mmc_error = Drivewritesector(ptr , Sector_now) If Mmc_error = 0 Then Print "WriteSector(" ; Sector_now ; ") ok." Print Buffer Else Print "Error during WriteSector(" ; Sector_now ; ") : " ; Mmc_error End If ') Next Sector_now Else Print "Error during Driveinit(): " ; Mmc_error End If Print "End of Test" End If Return #endif
Daten-Transferzeit
Verbleibt die Frage: Wie schnell ist der Datentransfer ?
- Das Hardware SPI des AVR MEGA128 wird mit 4 MHz getaktet. Hiermit liegt die Lesezeit je Sektor von DriveReadSector() recht stabil bei ca. 1,35 msec, beim Schreiben bei ca. 1,65 msec. Mit dem Software SPI stark schwankend bei dem 4 bis 5 fachen Wert.
- 512 Byte je 1,35 msec entspricht 2,6 usec pro Byte bzw. einer Datentransferrate von ca. 380 kByte/sec. Im Vergleich zur COM-Schnittstelle ist dies extrem schnell, im Vergleich zu USB und FireWire gemächlich.
- Und nun die gute Nachricht:
- Falls die 1,35 msec zu lang sind – Robo-mac muß in dieser Zeit bis zu 50 Schritte für 8 Achsen interpolieren – kann der Datentransfer per Interrupt unterbrochen werden.