Forum: Mikrocontroller und Digitale Elektronik USB-Speicherstick simulieren


von Michael A. (michael_a43)


Lesenswert?

Hallo,

ist es möglich, mit einem µC einen USB-Speicherstick zu simulieren, der 
von einem PC als Speichermedium erkannt wird.

Hier eine Erklärung über eine mögliche Verwendung.
Ich habe einen Server, der NUR !! Dateien an einem angeschlossenen 
USB-Stick schreiben kann. Anhand des Dateinamens, den der Server auf 
meinen simulierten USB-Stick schreiben will, soll der µC dann 
Schaltvorgänge ausführen.

Es geht hier also nicht darum, Daten real zu speichern, sondern es muss 
ein USB-Stick von einem µC simuliert werden und bei einem Zugriff auf 
den simulierten USB-Stick (anhand von verschiedenen Dateinamen) Ausgänge 
geschalten werden.

Gruß,

Michael

von Ralf (Gast)


Lesenswert?

NxP LPC17xx können das glaub ich, die haben soweit ich weiss einen 
integrierten MSD-Treiber. Bin aber nicht ganz sicher, musst du im DB/UM 
nachschlagen.

Ralf

von Peter B. (pbuenger)


Lesenswert?

Guck Dir mal die App-Note AVR273 von Atmel an, da müßte eigentlich alles 
drinstehen, was Du suchst.

Peter

von Johnny B. (johnnyb)


Lesenswert?

Für die MSP430 Mikrocontroller von TI mit USB gibts kostenlose 
Firmwarebeispiele, damit sich diese als sogenanntes Mass Storage Device, 
also Speicherstick ausgeben können.
Damit solltest Du Deine Anforderungen eigentlich in überschaubarer Zeit 
implementieren können.

Hier ein Propagandadokument von TI zum MSP430 mit USB:
http://www.ti.com/lit/wp/slay014/slay014.pdf?DCMP=OTC-MCU_Newsflash&HQS=Other%2bNL%2bmcunf_aug10_msp430_mc5

von Tek (Gast)


Lesenswert?

Das hier könnte au weiterhelfen:
http://www.fourwalledcubicle.com/LUFA.php

von 123 (Gast)


Lesenswert?

Moin.

das wird so nix.

das was du suchst nent sich USB MSC Mass storage class. beispiele gibts 
von vielen MCU herstellern. somit nichts besonderes.

nur MSC ist ein block layer, das erst mal gar nix von dateien weiss. 
(512Byte blöcke)

den rest macht windows. (dateisystem)

Problem an der sache ist, du weist nicht wann, wie windows die dateien 
auf dem Stick aktuallisiert. hängt auch noch von der Windows version ab, 
und von den einstllungen (sicheres entfernen chaching, ... ) linux kann 
das schon wieder ganz anders aussehen.

auf mcu seite müsstest du somit den MSC stack implementieren, siehe 
hoben, und ein dateisystem (FAT 12 / 16 32  ntfs / ? ) das bei jedem 
sektor zugriff kontrolliert, welche datei jetzt wie verändert worden 
ist. Problem, das das nicht zeitsynchron laufen kann. siehe hoben. ggf 
lesen die Host OS das auch wieder gegen zum validieren.

somit prinzipiell möglich nur nicht die schönste art so was zu 
implementieren.

Solltest du aber jemals auf die idea kommen, informationen vom stick 
richtung pc zu übertragen. bist du gekniffen. das tut nicht, da der pc 
dateien ggf cacht, und dadurch werden änderungen an der datei nicht am 
pc sichtbar werden. Weiter: aufgrund von block layer und dateisystem, 
gibt das mit absoluter sicherheit dan datensalat.

alternativ vorschlag, HID, ist unter linux und windows fast genauso 
einfach anzusprechen, und bereitet weniger probleme von wegen 
dateisystem, caching, synchrone zugriffe auf dateisystem von 2 
verschiedenen steiten, ...

da gibts auch schon vertige ICs, die man an usb anschliesen kann im 
irgendwelche relais zu steuen.

gruss

von Jörg S. (joerg-s)


Lesenswert?

Ralf schrieb:
> NxP LPC17xx können das glaub ich, die haben soweit ich weiss einen
> integrierten MSD-Treiber. Bin aber nicht ganz sicher, musst du im DB/UM
> nachschlagen.
Die LPC13xx haben einen "USB-Stick Modus". Der ist aber nur zum 
programmieren. Man kann also eine neue Firmware per Drag&Drop auf den 
Controller spielen.
Die LPC17xx können MSD meines wissens nicht direkt.

von 123 (Gast)


Lesenswert?

USB - HID Ic z.B. IOWarior nur als alternative. libs zum ansprechen 
gibts

von Reinhard Kern (Gast)


Lesenswert?

Hallo,

wie 123 schon ausgeführt hat, das wird garnicht gehen. Auf Seiten deiner 
Schaltung bekommst du nur einen Befehl der Art "schreibe xx Bytes in 
Block xy". Hinter welchen dieser Befehle ein Neuanlegen einer Datei 
steckt (auf jeden Fall mehrere davon), kannst du garnicht entnehmen. Und 
die Idee auf bestimmte xy zu reagieren kannst du auch gleich vergessen, 
die sind jedesmal anders und vom User nicht beeinflussbar.

Gruss Reinhard

von Gerd B. (Gast)


Lesenswert?

Doch, es geht.

von 123 (Gast)


Lesenswert?

moin

das geht prinzipiell schon.

nur der PC sagt lies bitte sektor x und folgende (jder 512 Byte gross ) 
und beim schreiben dann umgekehrt.

es können immer nur blöcke a 512 Byte gelesen / geschrieben werden!

Bei fat ist das anlegen einer datei in mehreren schritte zu zerlegen. je 
nach dem wie man es macht ist das dann power fail save (mit 
beeintächtigungen des dateisystems) oder führt zu totalschäden am 
dateisystem.

1. den speicher für die datei in der fat reservieren,
2. die reseriverten blöcke mit dem inhalt der datei füllen,
3. die entsprechenden informationen, start fat eintrag, dateiname, datum 
dateigrösse, ... in den verzeichnis strukturen eintragen.

(das sind die wesentlichen schritte, reihenfolge kann durchaus anders 
sein, ggf können es sogar mehr sein)


was auf der stick seite jetzt zu machen ist:

auf die sektor schreib / lese zugriffe reagieren, und dann entsprechend 
reagieren. wobei wie oben schon gesagt: caching könnte da einiges 
durcheinander bringen. (w2k wird immer mit caching auf den stick 
zugegriffen. hier wird definitif nicht gehen auser man erzwing den cach 
flush. bei xp kann mans einstillen, W7 erlaubt nur nach direkt access, 
linux kommt es auf die mountparameter an)

z.B. kurz hintereinander die gleiche datei ändern um z.B. irgend was zum 
blinken zu bringen, könnte vom caching/ io queue plötzlich zunichte 
gemacht werden. (OS ich bin doch nicht blöd und änder 2 mal den gleichen 
speicherbereich. das letzte ist wichtig, der rest ist für die tonne, 
wird doch sowieso vom 2. auftrag überschrieben)

somit währe schreibend möglich.


der rückkanal hingegen ist definitif nicht möglich. der PC geht nicht 
davon aus, das sich dateien / verwaltungs informationen auf einem 
speichermedium ohne sein zutun verändern könne. was bereits gelesen ist 
und im cach ist, muss nicht zwingend neu eingelesen werden.


somit der dringende rat, geht auf hid, erspart dier sicher einiges an 
kopfzerbechen und probleme. und ist aus einem c programm fast genauso 
leicht anzusprechen das anlegen einer datei. codebeispiele gibts genug 
im netz.

von Gerd B. (Gast)


Lesenswert?

Ich hatte sowas mal auf Basis eines PIC18F4550 gemacht. Von Mikrochip 
gibt es dafür eine Beispielprojekt, das zusammen mit einem Flashspeicher 
eine USB-Stick nachbildet.

Flash Speicher kann man entfernen, wenn man keine Daten abspeichern 
will. Und das braucht man eigentlich auch gar nicht.

Ich hab es so gemacht:

Im PIC war eine Dateistruktur fest im ROM hinterlegt. Mit einer Datei im 
Root. Etwa so:

F:FILE.TXT

Diese Datei ist <512 Bytes. und eigentlich leer.

PC öffnet diese Datei und ändert den Inhalt zu "1"
Dann findet ein Schreibzugiff statt. Den kannst Du abfangen, da er immer 
noch auf den gleichen Sektor stattfinden wird. Deshalb wird die FAT 
Tabelle nicht geändert.

PIC gibt dann zurück: "Schreiben erfolgreich". PC meint, da würde ne "1" 
drin stehen. Aber in Wirklichkeit hast Du nichts geschrieben, sondern 
nur ne LED eingeschaltet.

Wenn Du die Datei vom PC öffnest, wird sogar ne "1" drinstehen, weil der 
PC das im Zwischenspeicher hält.


Lesen geht auch. Man muss aber etwas tricksen.

Getestet habe ich das unter Windows2000,XP,Vista,Solaris,OSX und Linux.

von Michael A. (michael_a43)


Lesenswert?

Vielen Dank für die ganzen Infos...

An das Problem mit dem Cachen von den Dateien hab ich nicht gedacht, 
aber es gibt ja auch positive Erfahrung.
Da ich es unter Linux betreibe, habe ich hier etwas mehr einfluss.

Als HID-Device geht es leider nicht, da ich nur Daten schreiben/lesen 
kann.
Wenn ich mehr Möglichkeiten hätte, dann würde ich hier gleich den µC per 
Ethernet anbinden und hätte den ganzen Umweg nicht.

Hab mir gerade eine AT90USB.. bestellt und werde dies mal ausprobieren.

Gruß,

Michael

von 123 (Gast)


Lesenswert?

?????

moment unter linux / unix ist ALLES eine datei. vereppeln kann ich mich 
selber.

je nach distrie taucht für dein hid device ein character device im dev 
verzeichnis auf. auf das du wieder mit file IO zugreifen kannst. du must 
bei HID nur die richtige zahl an zeichen schreiben dann geht das auch. 
HID point nummer + anzahl der zeichen die der hid point haben will. zu 
wenig oder zuviel füren zu keinem ergebniss. ok ggf sind rootrechte 
notwendig / rechte anzupassen.

ggf muss man dazu ein die entsprechneden regeln eintragen / dev nodes 
anlegen.

und je nach distrie must du auch bei Mass Storage hand anlegen ( mount 
point / mount parameter )

was ggf einfacher gehen würde wenn es umbedingt mass storage sein muss.

mach das ganze ohne dateisystem, und greif direkt auf block device ebene 
zu. dazu gibt es das tool dd. aber vorsicht. braucht glaubich root 
rechte und damit kann man sich ganz böse das system in jenseitz 
befördern wenn man was falsches eintipt. (gibts auch wir windows)

von Michael A. (michael_a43)


Lesenswert?

Unter Linux kenn ich mich als Root aus - mit dd schon so einiges 
gemacht.

Ich hab hier aber einen Server, der nur über einen FTP oder 
Dateifreigaba  (Samba) verfügt.
Ich kann auf diesem Server NICHTS ändern - sonst müsste ich ja nicht 
diesen umständlichen Weg gehen.
....wollte Dich also nicht "veräppeln"

Michael

von 123 (Gast)


Lesenswert?

nabend,

was darfst / kannst du nicht an dem server  verändern? die sicht nach 
aussen (firewall  netwerkinterfaces  ... )? oder auch die 
configuration  module  treiber die geladen werden?

ggf könnte man so was änliches wie sysfs oder prog fs implementieren und 
für smb / ftp mounter, der dann als übersetzer dient. ist aber dann 
warscheinlich kernel programierung mit entsprecheden anpassungen. könnte 
aber als modul geladen werden. und ohne kernel übersetzung entwickelt 
werden. ggf beim kernel update sind anpassungen notwendig.


was mich an der ganzen sache stört. ist, das auf der einen seite auf 
sektor ebene zugegriffen wird, und auf der anderen seite, erkannt werden 
muss, welche datei verändert wird.

gibt es unter linux nicht die möglichkeit ein volum / laufwerk als ganze 
datei zu mounten? damit könntest du gezielt sektoren über ftp / smb 
manipulieren. was auf device seite das dateisystem eliminieren würde. 
(komplexe software, fehleranfällig)
beispiel. ein 16MB Stick taucht als eine datei mit 16mb im smb auf.

es gibt im linux kernel ganz sub syteme wie z.B. LED  PIO  ... mit 
einem entsprechenden Kerneltreiber könne man das dann durch eine mount 
ins prog / sysfs erledigen. (Documentation/gpio.txt)

mit entsprechender HW und dem entsprechenden Treiber lassen sich z.B. 
mit embedded hw leds über die console ein und aussschalten / sogar 
configureren.

gruss

von R. M. (rmax)


Lesenswert?

@Michael: Das klingt aber danach, als ob Dein Server ebenfalls unter 
Linux läuft, und das läßt hoffen, daß er vielleicht soweit 
hack^H^H^H^Herweiterbar ist, daß er auch andere USB-Geräteklassen 
unterstützt als die, die der Hersteller ursrprünglich vorgesehen hatte.

von Matthias Melcher (Gast)


Lesenswert?

Ich würde mal ein paar alte USB Sticks sammeln und aufschrauben/sägen. 
Wenn Du Glück hast, dann ist der Controller vom RAM schön sauber 
getrennt und Du kannst den Daten- und Adressbus abgreifen?

So bleibt der Stick wirklich absolut kompatibel zum Server und du 
schreibst halt immer die selbe Datei.

Du musst auch garnicht den ganzen Adressbus dekodieren, sondern einfach 
nur dem Datenbus lauschen: dann wartet Deine CPU auf eine magische 
Sequenz auf dem Datenbus mit Datenbytes und Checksumme. Mit einem 
Datenblatt vom RAM und einem Latch am Datenbus, der vom CS oder WE 
getriggert wird kannst Du sogar mit ner lahmen CPU noch wenigstens Teile 
vom Datenverkehr abhören.

Das wäre natürlich ein heftiger Hack, könnte aber klappen. Rückkanal 
geht so auch, wenn Du auf dem Stick Leiterbahnen vom Datenbus auftrennen 
kannst.

 - Matthias

von Gerd B. (Gast)


Lesenswert?

Eigentlich sollte es mit nem µC als MSD recht einfach gehen.
Ich würde sogar sagen in eins/zwei Stunden.

Ich hatte sowas ähnliches mal auf PIC Basis gemacht.

Flash Speicher brauchst Du keinen.
Du erzeugst Dir folgende Verzeichnisstruktur:
USB_STICK/FOLDER/

Damit mit:
1
SDC_Error SectorRead(dword sector_addr, byte* buffer)
2
{
3
  if ((sector_addr==0)||(sector_addr==0+6))  //BootSektor
4
  {
5
      ...
6
  }
7
  else if ((sector_addr==1)||(sector_addr==1+6))  //FSInfo
8
  {
9
      ...
10
  }
11
  else if ((sector_addr==2)||(sector_addr==2+6)||(sector_addr==12)||(sector_addr==12+6))  //3. leerer Cluster mit Signatur
12
  {
13
    ...
14
    }
15
  else if (sector_fat==0)  //FAT (Sektor 1 von 5)
16
  {
17
    ...
18
  }
19
  else if ((sector_fat>=1)&&(sector_fat<(1+FLASH_FAT_SECTORS)))  //  Flash FAT
20
  {
21
      ...
22
  }
23
24
  else if (sector_addr==(RESSECTORS+2*SECPERFAT))  // Root Verzeichnis Einträge
25
  {
26
    setDirEntry(&buffer[0x000],"USB_STICK  ",VOLLABEL,0,0);
27
    setDirEntry(&buffer[0x0C0],"FOLDER     ",DIRECTORY,128,0);
28
29
  }
30
  
31
  ..
32
  
33
  return 0;
34
}


Und beim Schreiben fängst Du dann eine Sequenz "xxx.." ab:
1
SDC_Error SectorWrite(dword sector_addr, byte* buffer)
2
{
3
  int i;
4
  xsen = 0;
5
  for (i=0;i<512;i++) 
6
  {
7
       // nach Startsequenz "xxx..." suchen
8
       if (buffer[i] == 'x') 
9
       {
10
             xsen ++;
11
       }
12
       else 
13
       { 
14
          //3 x-se gefunden, nächstes Zeichen wird ausgewertet
15
          if (xsen >= 3)
16
          {
17
18
             // Ausgänge schalten
19
             if (buffer[i] == '0' ) SwitchOff_Output_A();
20
             if (buffer[i] == '1' ) SwitchOn_Output_A();
21
             if (buffer[i] == '2' ) SwitchOff_Output_B();
22
             if (buffer[i] == '3' ) SwitchOn_Output_B();
23
              ....
24
           }
25
26
            xsen = 0;
27
       }
28
29
   }
30
  
31
   return 0; // immer 0 für "Schreiben hat funktioniert"
32
}

Also xxx wäre die Sequenz, um dein "Ausgang-Setzen" einzuleiten. Das 
Zeichen nach dem xxx ist dann Dein Steuerzeichen.

Die ganze Problematik mit dem Cache kannst Du umgehen, indem Du jedesmal 
eine neue Datei schreibst. Zum Beispiel mit einem Datumsstempel.

so würde also ein Schreiben auf:

2011-08-27_83025_001_xxx3.txt den Ausgang B setzen.
Dein Stick würde sagen: "ok, hab ich geschrieben". Das Linux Filesystem 
glaubt das auch. Aber dein Stick hat eh kein Flash, und kann deshalb 
auch nie voll werden.

von Purzel H. (hacky)


Lesenswert?

Es gibt ein Buch von Jan Axelson zum Thema Massenspeicher am USB. Ich 
hab ein wenige geblaettert, und fand das unterliegende Protokoll bildet 
den SCSI Bus nach. Dh es schaut nach einer Menge Arbeit aus.

von gerd b. (Gast)


Lesenswert?

So.
Ich hab's mal ausprobiert. Und es tut.

Plattform ist ein AT90USBKey Board. Passt also zu Deinem AT90USB.

Hier der Sourcecode + Binary: 
http://sebulli.com/download/MSD_Control.zip
Projekt hab ich für Linux angepasst. Das Wichtigste steht in 
MSD_Control/at90usb128/lib_mem/df/df.c

1. (make in: MSD_Control/at90usb128/demo/MSD_Control/gcc)
2. Board in den Bootload Modus setzen (HWB + RES -> HWB)
3. dfu-programmer at90usb1287 erase
4. dfu-programmer at90usb1287 flash MSD_Control.hex
(Siehe auch 
http://www.avrfreaks.net/wiki/index.php/Documentation:Tutorials_AT90UsbKey_under_Linux)

Led einschalten, indem zb. die Datei XXXE_Led0_ON.txt per Drag&Drop in 
den WRITE Ordner kopiert wird

von Michael A. (michael_a43)


Lesenswert?

Hallo Gerd,

vielen lieben Dank für den Beispiel und Deine Mühen.
Werde es gleich ausprobieren, sobald mein µC kommt.

Gruß,

Michael

von gerd b. (Gast)


Lesenswert?


von Michael A. (michael_a43)


Lesenswert?

Ich hab mir eine AT90USB1287 bestellt und mach gerade dazu eine einfache 
Platine.

von gerd b. (Gast)


Lesenswert?

Ok. Auf das Board hättest Du es 1:1 aufspielen können.
Ich denke für den Chip alleine müsste man nochmals etwas anpassen.
ZB glaube ich, dass die Flash-Bausteine (die ja nicht benutzt werden) 
zur Zeit noch initialisiert werden. Wenn keine da sind, könnte die 
Software ewig warten.

Dann ist mir noch was zum Cachen aufgefallen:
Beim Schreiben einer Datei wird der Dateiname abgelegt. Angenommen, der 
ist 16 Bytes lang, dann werden nur 16 Bytes des 512 Bytes Block belegt. 
Wenn man jetzt eine neue Datei anlegt, wird der neue Dateiname dahinter 
geschrieben. Aber beim Schreiben wird höchstwahrscheinlich der erste 
Name auch nochmals geschrieben, da ja immer 512 Bytes Blöcke benutzt 
werden.

Deshalb wäre wahrscheinlich sowas besser (falls möglich):
Datei XXXA_Led0Off.txt anlegen.
Datei XXXB_Led1Off.txt anlegen.
Datei XXXC_Led2Off.txt anlegen.
Datei XXXD_Led3Off.txt anlegen.


Datei XXXA_Led0Off.txt in XXXE_Led0On.txt umbennen zum Einschalten LED0
Datei XXXE_Led0On.txt in XXXA_Led0Off.txt umbennen zum Ausschalten LED0

Dann bräcuhte man auch nicht mehr einen Zeitstempel, es würde immer bei 
4 Dateien bleiben.

Aber man braucht eine "RENAME".

gerd

von ABC (Gast)


Lesenswert?

bei jedem schreibvorgang in eine datei, egal ob die nun existiert oder 
nicht, wird immer die verwaltungsstruktur für die datei aktuallisiert. 
Hier steht drin wie die datei heist, kurzer und langer dateinamen, 
grösse der datei, erster block in der fat tabelle, der zu der datei 
gehört und das datum für erstellung, änderung und letzter zugriff, Datei 
oder Verzeichniss, Dateiattribute, ...

wie oben schon mal kurz beschrieben. sind für das anlegen einer neuen 
datei

1. die fat zu aktuallisieren,
2. die veraltungsstrukturen
3. die datei selber mit inhalt zu füllen.

das alles ist nur ein grobe abläufe. das kann noch viel komplizierter 
weden, wenn z.B. die verwaltungsstrukturen in der Fat auch noch speicher 
anfordern (z.B. bei unterverzeichnissen oder FAT32 )

da das host system linux ist, kann man das caching deaktivieren. ist nur 
ein mount parameter den man entsprechend angeben muss.
die umstände mit immer einer neuen datei könnte man sich hier sparen. 
(windows ist ja nicht gefordert)

von Michael A. (michael_a43)


Lesenswert?

Hallo Gerd,

heute kam mein µC und auch die Platine.
Board funktioniert schon und er lässt sich auch über FLIP Flashen.

Muss jetzt Dein Beispiel im AVR-Studio umsetzten.
Melde mich, sobald es funktioniert.

Gruß,

Michael

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.