Forum: FPGA, VHDL & Co. LM3S9B96 SPI über GPIO


von Olli (Gast)


Lesenswert?

Hallo, bi dabei mit Lm3S9B96 zu arbeiten und will über den GPIO mit der 
SPI ein Flash ansprechen, welches mit einem FPGA verbunden ist. Ich 
möchte Das Flash schreiben und lesen können über das SPI. So hab zwar 
soweit implementiert, aber kann keine daten zurücklesen. Beim FPGA soll 
der INIT PIN am Anfang auf low gesetzt werden, anschließend setze ich 
ihn dann auf High Impedanz, damit das FPGA konfiguriert werden kann, und 
nachdem das FPGA konfiguriert wird wird vom FPGA sowie der DONE Pin als 
auch INIT Pin auf High gesetzt.

Mein code:
1
int main(void){
2
3
 unsigned long ulDataTx[5];//={0};
4
 unsigned long tx_dummy[5];
5
 unsigned long ulDataRx[5];//={0};
6
 unsigned long rx_dummy[5];
7
 int ulindex;
8
9
 SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |   SYSCTL_XTAL_16MHZ);
10
11
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
12
13
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
14
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
15
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
16
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
17
18
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
19
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
20
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
21
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
22
                              //
23
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);
24
    GPIOPinTypeGPIOOutputOD(GPIO_PORTD_BASE, GPIO_PIN_6);// INIT Pin vom FPGA
25
26
27
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
28
29
    SSIEnable(SSI0_BASE);
30
31
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0);
32
33
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 'z');
34
35
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PA3_SSI0FSS, 0);
36
37
38
39
40
    while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx[0]))
41
        {
42
        }
43
44
    ulDataTx[0] = 0x90;
45
    ulDataTx[1] = 0x12;
46
    ulDataTx[2] = 0x13;
47
    ulDataTx[3] = 0x14;
48
    ulDataTx[4] = 0x15;
49
50
    for(ulindex = 0; ulindex < 5; ulindex++)
51
    {
52
        SSIDataPut(SSI0_BASE, ulDataTx[ulindex]);
53
        while(SSIBusy(SSI0_BASE))
54
        {
55
        }
56
        SSIDataGet(SSI0_BASE, &tx_dummy[ulindex]);
57
   }
58
59
  for(ulindex = 0; ulindex < 5; ulindex++)
60
    {
61
    SSIDataPut(SSI0_BASE, rx_dummy[ulindex]);
62
      SSIDataGet(SSI0_BASE, &ulDataRx[ulindex]);
63
      ulDataRx[ulindex] &= 0x00FF;
64
    }
65
66
67
68
69
70
  GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PA3_SSI0FSS, 1);
71
}

Kann mir einer sagen, was ich hier Falsch mache, weshalb ich keine Daten 
empfange, immer nur Null.

Ne andere Frage, der Modus für den SPI soll der im FPGA definiert werden 
oder soll er in mein c code definiert und ans FPGA übertragen werden.

Danke.

von Lattice User (Gast)


Lesenswert?

1. Welcher FPGA?

2. Der SPI Flash ist parallel an FPGA und Lm3S9B96?
2a. Wnn ja, ist sichergestellt dass der FPGA seine SPI Pins auf 
Highimpedance hat?

von PittyJ (Gast)


Lesenswert?

Sorry, ich verstehe überhaupt nicht, was das soll, was geht und was 
nicht geht. // sind ja auch mächtig viele Kommentare im Programm


Vielleicht solltest du das Problem in kleinere Schritte aufteilen, und 
dann immer schauen, bis wohin was noch geht.

von Olli (Gast)


Lesenswert?

Danke erstmal für die Antwort.

1. Es ist der Spartan 3A DSP

2. Also der Flash ist von ATMEL (AT45D) und ist Parallel zum FPGA. Und 
über den LM3S9B96 ist es mit dem Flash über die Pins verbunden. So 
gesehen, sollte ich doch unabhängig vom FPGA daten ins Flash schreiben 
und wieder lesen können. Den FPGA brauche ich ja nur um die Daten vom 
Flash ins FPGA zu laden. Und ja die sind auf High impedance.

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> Und ja die sind auf High impedance.

Ob das auch zutrifft wenn der FPGA noch nicht konfiguriert ist, wäre ich 
mir nocht so sicher. Aber das muss ein Xilinx Experte bentworten.

Zum AT45D;

Versuch erst mal die JEDEC ID zu lesen, Command 0x9F,
Ich finde übrigens im AT45DB642D Datasheet kein Command 0x90. Vielleicht 
ist das dein Problem.

von Olli (Gast)


Lesenswert?

Hallo,
Das ist erst Neugebiet für mich, bin grad dabei mich einzufinden. Was 
meinst du mit Commands. Heißt das ich muss zu einer bestimtmen Addresse 
was schicken und abfragen??
Also ich habe den AT45DB161D...

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> Was
> meinst du mit Commands. Heißt das ich muss zu einer bestimtmen Addresse
> was schicken und abfragen??

Bei einem SPI Flash ist das erste Byte das gesendet wird immer ein 
Command.
Einige dieser Commands sind in einem JEDEC Standard definiert, z.B. 0x03 
zum Lesen, und 0x9F zum Abfragen der ID.

Das Datenblatt des SPI Flashs hilft da ungemein weiter.

von PittyJ (Gast)


Lesenswert?

Ok, wird etwas klarer nun.
Bei Atmel gibt es ein Datenblatt zu dem AT45DB161D.
Ab Seite 25 stehen die möglichen Kommandos.

Mein Vorschlag wäre auch das Kommando 9F. Auf Seite 23 ist beschrieben, 
was als Antwort kommen soll.

Danach als Versuch mal Kommand0 03 + Adresse. Damit sollte man den 
Inhalt von Speicherzellen lesen können.

Bei mir hat das so mit einem anderen Flash auch geklappt.

von Olli (Gast)


Lesenswert?

Danke, für euere Antworten. Hab zwar angefangen gehabt das Datenblatt zu 
lesen war aber noch nicht soweit gekommen. Probiere es mal aus. Falls 
ich noch fragen haben sollte melde ich mich. Vielen Dank.

von Olli (Gast)


Lesenswert?

So hab doch noch ein par Fragen. Ich versteh das nicht so ganz mit den 
OPcodes. wie genau schreibe ich jetzt Daten ins Flash. dazu habe ich 
kein schreib opcode gefunden und zum lesen muss ich dann erst 3H senden 
und dann einfach nach daten abfragen, hab meinen code so umgestellt. bin 
mir nicht sicher ob es so in ordnung ist. Sind die CS richtig gesetzt 
oder soll alles in einem CS stattfinden.
1
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |   SYSCTL_XTAL_16MHZ);
2
3
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
4
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
5
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
6
7
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
8
GPIOPinConfigure(GPIO_PA3_SSI0FSS);
9
GPIOPinConfigure(GPIO_PA4_SSI0RX);
10
GPIOPinConfigure(GPIO_PA5_SSI0TX);
11
12
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);
13
GPIOPinTypeGPIOOutputOD(GPIO_PORTD_BASE, GPIO_PIN_6);//INIT PIN vom FPGA
14
15
SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
16
17
SSIEnable(SSI0_BASE);
18
19
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0); // Set INIT to Low
20
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS low
21
22
while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx[0]))
23
     {
24
     } 
25
SSIDataPut(SSI0_BASE, 0x84); // Buffer write
26
SSIDataGet(SSI0_BASE, &dummy);
27
SSIDataPut(SSI0_BASE, 0x00);
28
SSIDataGet(SSI0_BASE, &dummy);
29
SSIDataPut(SSI0_BASE, 0x00);
30
SSIDataGet(SSI0_BASE, &dummy);
31
SSIDataPut(SSI0_BASE, 0x00);
32
SSIDataGet(SSI0_BASE, &dummy);
33
SSIDataPut(SSI0_BASE, 0x12);
34
SSIDataGet(SSI0_BASE, &dummy);
35
36
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High
37
38
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS low
39
40
SSIDataPut(SSI0_BASE, 0x03);
41
SSIDataGet(SSI0_BASE, &dummy);
42
SSIDataPut(SSI0_BASE, 0x00);
43
SSIDataGet(SSI0_BASE, &dummy);
44
SSIDataPut(SSI0_BASE, 0x00);
45
SSIDataGet(SSI0_BASE, &dummy);
46
SSIDataPut(SSI0_BASE, 0x00);
47
48
SSIDataPut(SSI0_BASE, dummy);
49
SSIDataGet(SSI0_BASE, &ulDataRx);
50
51
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS set High
52
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 'z'); // Set to High impedance start of configuration

von P. K. (pek)


Lesenswert?

Es könnte aufschlussreich sein, mal Dein SPI-Interface mit dem KO 
anzuschauen (CLK und MISO). Dann kannst Du mal ausschliessen (ev. 
erhärten) dass kein Signal vom Flash her kommt.

von Lattice User (Gast)


Lesenswert?

Die CS sind im Prinzip richtig, aber zwiachen CS High und wieder Low 
sollte eine Pasue, sonst sieht der Flash das eventuell nicht. Steht aber 
sicher im Datenblatt wie lang das High mindestens anstehen muss.

Einen Flash kann man nicht einfach schreiben, das ist komplizierter. 
Obendrein kocht da jeder Hersteller sein eigenens Süppchen, und der 
Atmel Dataflash gehört zu den komplizierteren.
Um beim Atmel ein einzelnes Byte zu schreiben muss man einen Block in 
den Buffer (im Flash) übertragen, dann das Byte (am richtogen Ofsset 
modifizieren), und den Buffer zurückschreiben (geht IRC mit Autoerase).

Um das Interface zu testen verwende den Befehl 9F, ID Lesen. Wenn diese 
richtig gelesen wird funktioniert das SPI Interface, und dann kannst du 
dich genauer mit den Regentänzen beschäftigen die der Atmelflash 
benötigt.

(Für einen Anfänger wäre ein SSTI wesentlich einfacher).

von Olli (Gast)


Lesenswert?

Hallo,
Ich versuche jetzt erstmal die ID zurückzulesen nicht das klappt mal 
gerade bei mir.
1
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |   SYSCTL_XTAL_16MHZ);
2
3
        SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
4
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
5
6
        GPIOPinConfigure(GPIO_PA2_SSI0CLK);
7
        GPIOPinConfigure(GPIO_PA4_SSI0RX);
8
        GPIOPinConfigure(GPIO_PA5_SSI0TX);
9
                                                            //| GPIO_PIN_3
10
        GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_2);
11
12
        GPIODirModeSet(GPIO_PORTA_BASE, GPIO_PIN_3,GPIO_DIR_MODE_OUT);
13
14
15
16
        SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
17
18
        SSIEnable(SSI0_BASE);
19
20
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS low
21
22
SSIDataPut(SSI0_BASE, 0x9F);
23
SSIDataGet(SSI0_BASE, &dummy);
24
25
for(ulindex = 0; ulindex < 5; ulindex++)
26
    {
27
       SSIDataPut(SSI0_BASE, rx_dummy[ulindex]);
28
       SSIDataGet(SSI0_BASE, &ulDataRx[ulindex]);
29
30
    }
31
32
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High

von Olli (Gast)


Lesenswert?

Das Chipselect habe ich über gpio definiert, ist das auch in ordnung so?

von PittyJ (Gast)


Lesenswert?

Ich würde jetzt mal mit einem Scope schauen, was da wirklich an den 
Leitungen anliegt. Ob das Verhalten mit dem Datenblatt überein stimmt.

von Olli (Gast)


Lesenswert?

Ich habs am Oszi angeschlossen, also was ich da sehe ist, wenn ich 
Dataput ausführe, dann generiert er clock, cs und den SI Eingang vom 
Flash, am Oszi sehe ich dann die 9F. Jedoch wenn ich meine Schleife 
durchlaufe, sehe ich am Oszi nur den DataPut schritt mit dem Dummy byte, 
also ein clock dazu CS und leere Daten soweit so gut, jedoch wenn ich 
übers DataGet gehe dann passiert gar ncihts mehr kein Clock kein CS 
keine Daten am Ausgang. Was ist das denn jetzt. Warum pasiert nichts bei 
DAtaget. Danke.

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> Warum pasiert nichts bei
> DAtaget. Danke.

bei SPI wird immer gleichzeitig gelesen und geschrieben. Deswegen auch 
das SSIDataPut(SSI0_BASE, dummy); SSIDataGet gibt dann nur die Daten 
zurück die während SSIDataPut gelesen wurden.

von Olli (Gast)


Lesenswert?

Hallo,
habs soweit hinbekommen, dass ich die 9FH eingeben und die manufaktur ID 
zurücklesen kann, also lesen funktioniert schonmal, wie ist es denn mit 
schreiben, mit welchen commands tue ich schreiben. Da gibt es einmal 
Buffer write 84H oder Buffer 1 to Main Memory Page Program with Built-in 
Erase 83H, hab zwar gelesen, dass es komlizierter sein soll. Bin dankbar 
wenn mir hier weiter geholfen werden kann.

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> habs soweit hinbekommen, dass ich die 9FH eingeben und die manufaktur ID
> zurücklesen kann, also lesen funktioniert schonmal

Nein, SPI funktioniert, nicht nur das Lesen sondern auch das Schreiben 
auf das Device.

Jetzt musst du nur noch anschauen wie der Flash funktioniert und mit 
welchen Kommandos man Daten liest und schreibt, und vor allem wie ein 
Schreibyklus aussieht. Jeder Flash braucht Löschen, Schreiben, warten 
auf Schreiben beendet.
Lies endlich das Datasheet des Atmelflashs, ich meine wirklich lesen und 
nicht nur nach Details suchen.

von Olli (Gast)


Lesenswert?

HAllo,
Hab das Datasheet gelesen, habs auch jetzt soweit dass ich Daten 
schreiben und wieder lesen kann. D.H. dass ich erst ins Buffer schreibe 
und dann ins Main page transferieren kann, dann vom Main Page ins Buffer 
und vom Buffer lesen. Aber das hab ich wohl übersehen, nämlich das 
löschen. Auf der Ausgangsleitung sehe ich am Oszi das die richtigen 
Daten anliegen, jedoch mein ulDataRx krieg nicht die richtigen Daten, 
erst paar schritte später.
Gut ich versuch das mal aus.
Danke .

von Olli (Gast)


Lesenswert?

Nagut, es hat funktioniert, hoffe es war kein Zufall, kannst vielleicht 
einen Blick drüber werfrn ob es soweit in ordnung ist.
1
//JEDEC: lesen von ID 
2
SSIDataPut(SSI0_BASE, 0x9F);
3
        SSIDataGet(SSI0_BASE, &dummy);
4
5
        for(ulindex = 0; ulindex < 5; ulindex++)
6
           {
7
             SSIDataPut(SSI0_BASE, dummy);
8
             SSIDataGet(SSI0_BASE, &ulDataRx[ulindex]);
9
10
           }
11
12
        GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High
13
        for(o=0; o<50; o++);
14
15
16
        GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
17
          
18
           //Buffer 1 Write
19
           SSIDataPut(SSI0_BASE, 0x84);
20
           SSIDataGet(SSI0_BASE, &dummy);
21
           SSIDataPut(SSI0_BASE, 0x00);
22
           SSIDataGet(SSI0_BASE, &dummy);
23
           SSIDataPut(SSI0_BASE, 0x00);
24
           SSIDataGet(SSI0_BASE, &dummy);
25
           SSIDataPut(SSI0_BASE, 0x0A); // Addresse A
26
           SSIDataGet(SSI0_BASE, &dummy);
27
           SSIDataPut(SSI0_BASE, 0xAA); // Daten = 0xAA
28
           SSIDataGet(SSI0_BASE, &dummy);
29
           SSIDataPut(SSI0_BASE, 0xBB); //Daten = 0xBB
30
           SSIDataGet(SSI0_BASE, &dummy);
31
           SSIDataPut(SSI0_BASE, 0xCC); Daten = 0xCC
32
           SSIDataGet(SSI0_BASE, &dummy);
33
34
35
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);            //Deselect the Flash chip
36
37
38
           while(SSIBusy(SSI0_BASE))
39
           {
40
           }
41
42
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
43
44
           //Buffer 1 to Main Memory Page Program with Built-in Erase
45
           SSIDataPut(SSI0_BASE, 0x83);
46
           SSIDataGet(SSI0_BASE, &dummy);
47
           SSIDataPut(SSI0_BASE, 0x00);
48
           SSIDataGet(SSI0_BASE, &dummy);
49
           SSIDataPut(SSI0_BASE, 0x0A);
50
           SSIDataGet(SSI0_BASE, &dummy);
51
           SSIDataPut(SSI0_BASE, 0x00);
52
           SSIDataGet(SSI0_BASE, &dummy);
53
54
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);
55
           while(SSIBusy(SSI0_BASE))
56
                      {
57
                      }
58
59
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
60
          
61
           //Main Memory Page to Buffer 1 Transfer
62
           SSIDataPut(SSI0_BASE, 0x53);
63
           SSIDataGet(SSI0_BASE, &dummy);
64
           SSIDataPut(SSI0_BASE, 0x00);
65
           SSIDataGet(SSI0_BASE, &dummy);
66
           SSIDataPut(SSI0_BASE, 0x0A);
67
           SSIDataGet(SSI0_BASE, &dummy);
68
           SSIDataPut(SSI0_BASE, 0x00);
69
           SSIDataGet(SSI0_BASE, &dummy);
70
71
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);
72
           while(SSIBusy(SSI0_BASE))
73
                      {
74
                      }
75
76
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
77
78
           //Buffer 1 Read (Low Frequency)
79
           SSIDataPut(SSI0_BASE, 0xD1);
80
           SSIDataGet(SSI0_BASE, &dummy);
81
           SSIDataPut(SSI0_BASE, 0x00);
82
           SSIDataGet(SSI0_BASE, &dummy);
83
           SSIDataPut(SSI0_BASE, 0x00);
84
           SSIDataGet(SSI0_BASE, &dummy);
85
           SSIDataPut(SSI0_BASE, 0x0A);
86
           SSIDataGet(SSI0_BASE, &dummy);
87
88
           for(ulindex = 0; ulindex < 5; ulindex++)
89
           {
90
             //lesen der Daten
91
             SSIDataPut(SSI0_BASE, dummy);
92
             SSIDataGet(SSI0_BASE, &ulDataTx[ulindex]);
93
94
           }
95
96
           GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);

von Lattice User (Gast)


Lesenswert?

Mit welcher Frequenz taktest du den SPI Bus?  Wenn kleiner als 33 MHz 
kannst du zum Buffer 1 lesen auch 0xD1 verwenden, dann gibt es den Delay 
nicht.

Was ist der Zweck der Übung?
Update des FPGA bitpatterns, oder allgemeiner Datenspeicher?

von Olli (Gast)


Lesenswert?

Hallo,
in dieser Funktion lege ich doch die clock rate fest nicht, 
SSIConfigSetExpClk, im vorletztem Parameter, laut dem habe ich 1 MHZ 
eingegeben. Du meinst bei D4H wird erst ein Dummy byte gelesen, dann 
erst die Daten, welchen zwecj soll dieses Delay denn haben.

also ich sende per Stellaris über das SPI daten ins Flash und das FPGA 
ruft die dann wieder auf, sind halt konfigurationsdaten.

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> u meinst bei D4H wird erst ein Dummy byte gelesen, dann
> erst die Daten,

Korrekt

Olli schrieb:
> welchen zwecj soll dieses Delay denn haben.

Das Problem bei SPI ist, dass direkt nach dem letzten Addressbit die zu 
lesenden Daten schon bereitstehen müssen. Bei hohen Taktraten schafft 
der Flash das nicht mehr, deswegen das Dummybyte.

Aber 1 MHz ist sehr sehr langsam, da würde ich mich um die 
Optimierungsmöglichkeiten des Atmelflashs nicht kümmern.

Lesen nur mit den Standard JEDEC Command (0x03).

Beim Schreiben kommt man um die Eigenheiten nicht herum, aber man sollte 
immer Blockweise löschen/schreiben, und auch kein Doublebuffering (der 
Atmel hat 2 Buffer) zur Beschleunigung. Dann ist das ganze leichter 
portiebar auf weniger komplexe Flashes.

von Olli (Gast)


Lesenswert?

Hallo,
Ich verstehe nicht so ganz wie so der Ruf von 03H stattfindet. kannst du 
mri anhand eines Beispiels erklären, Im datenblatt heist es ja die 
ersten 12 Bits wählen ja die Page des Main Memory Arrays aus und die 
letten 10 bits wählen des zu startenden bytes in der jeweiligen Page. 
Ich kannmir das grad bildlich nicht vorstellen. die aller ersten 2 bits 
sind das dont cares dann?

sagenw ir mal hab da ein Array

1 1000500009EE33213C0B31A101A931412F0031C2FE
2 100060000384E09330E1FFCF30C10081318108810A
3 100070003201001F32C1000532E1000432A1000E3E
4 100080003261000032810000334118F23362000017
5 10009000000030220000000030A100015060000B81
6 1000A0002C8600000000000000000000000000009E
7 1000B0000000000000000000000000000000000040
8 1000C0000000000000000000000000000000000030
9 1000D0000000000000000000000000000000000020
10 1000E0000000000000000000000000000000000010
11 1000F0000000000000000000000000000000000000
12 1001000000000000000000000000000000000000EF
13 1001100000000000000000000000000000000000DF

soll ich mir das so vorstellen die nummerierung ganz links sind die 
Pages und zur waagerechten die einzelnen Bytes die ich dann auswählen 
kann? oder hab ich da was falsch verstanden, ich hab da anhand von 
Impact das SPI Flash programmiert und will eigentlich nur auslesen was 
jetzt im SPI Flash anliegt.

Dazu die Lese-Routine:
1
GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
2
3
                  SSIDataPut(SSI0_BASE, 0x03);
4
                  SSIDataGet(SSI0_BASE, &dummy);
5
                  SSIDataPut(SSI0_BASE, 0x00);
6
                  SSIDataGet(SSI0_BASE, &dummy);
7
                  SSIDataPut(SSI0_BASE, 0x40);
8
                  SSIDataGet(SSI0_BASE, &dummy);
9
                  SSIDataPut(SSI0_BASE, 0x01);
10
                  SSIDataGet(SSI0_BASE, &dummy);
11
12
13
                  for(ulindex = 0; ulindex < 5; ulindex++)
14
                     {
15
                       SSIDataPut(SSI0_BASE, dummy);
16
                       SSIDataGet(SSI0_BASE, &ulDataTx[ulindex]);
17
                     }
18
19
20
21
22
          GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);            //Deselect the Flash chip

Nach meinem Beispielcode müsste doch heißen,lese aus Page 1 und ab 
Addresse 1.

von Lattice User (Gast)


Lesenswert?

Der Atmelflash ist da etwas kompliziert, da er für jeden Sektor ein paar 
extra Bytes um Fehlerkorrektur zu unterstützen.

Das lässt sich (einmalig) auf Standardgrößen (zb. 512) umstellen, und 
dürfte wohl auch erforderlich sein den FPGA davon zu Booten. (Bei 
Lattice macht das die Programmiersoftware für die Atmel Dataflashes 
selbständig ohne einem darauf hinzuweisen).

Nach der Umstellung kann men bei 0x03 einfach linear die Startaddresse 
übergeben.

von Olli (Gast)


Lesenswert?

Also soll ich erstmal auf die größe 512 umstellen und dann ganz normal 
eine Addresse reinjagen?

wie gesagt hab ein mcs file ins SPI Flash geflasht will nun lesen was i, 
Flash steht, ist dieser Opcode 03H überhaupt dafür geeignet oder soll 
ich wieder erst vom Memory Page ins Buffer transferiern und dann vom 
Buffer lesen.
Danke.

von Lattice User (Gast)


Lesenswert?

Der Opcode 0x03 ist JEDEC Standard, und wird auch vom FPGA zum Booten 
verwendet. Das mit dem Buffering ist eine Spezialität der Atmelflashes 
und dürfte von keiner FPGA Bootlogik unterstützt werden.
Wenn der Flash das intern macht ist das auf jedem Fall transparent.

von Olli (Gast)


Lesenswert?

Habs auf 512 bytes umgestellt, bekomme jedoch immer noch nur 0xff da 
raus,

Unten habe ich ja ein beispiel vom mcs file gezeigt, ne Verständnisfrage 
dazu. So wie ich es verstanden habe ist, wenn ich mit 03H lesen würde, 
müsste mir doch aus dem Atmel Flash, wenn ich die Addr A auslese, die 
dazugehörigen Daten anzeigen oder? Die Zeile eines mcs files sieht ja 
wiefolgt aus, Die ersten 8 zeichen (nach dem :) sind eine Adresse fürs 
ROM, dann kommen 8*2 Bytes Nutzdaten, dann ein Byte Checksumme. Bin da 
gerade richtig durcheinander.

als Beispiel nochmal mcs code:
1
:020000040000FA
2
:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
3
:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
4
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
5
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
6
:10004000FFFFFFFFFFFFAA9930A1000720003161E9
7
:1000500009EE33213C0F31A100C931412F0031C2DB
8
:100060000222809330E1FFCF30C1008131810881CD
9
:100070003201001F32C1000532E1000432A1000E3E
10
:100080003261000032810000334118F23362000017
11
:10009000000030220000000030A10001506000028A
12
:1000A0009AC20000000000000000000000000000F4

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> So wie ich es verstanden habe ist, wenn ich mit 03H lesen würde,
> müsste mir doch aus dem Atmel Flash, wenn ich die Addr A auslese, die
> dazugehörigen Daten anzeigen oder?

Richtig.
Das MCS schreibt nach Adresse 0, also mit 03 00 00 00 und 512 Bytes 
lesen sollte man es zurücklesen können. (Zu beachten: der 04 Record am 
Anfang setzt die höhren Adressbits für die folgenden 00 Records.
http://en.wikipedia.org/wiki/Intel_HEX

Frage, wie kommt das mcs in den Flash?

von Olli (Gast)


Lesenswert?

Hallo,
Über das Xilinx Tool Impact kommt das mcs ins Flash.

Lattice User schrieb:
> (Zu beachten: der 04 Record am
> Anfang setzt die höhren Adressbits für die folgenden 00 Records.


was genau meinst du damit, habe ich nicht verstanden. 04 ist auch ein 
OPcode?

von Olli (Gast)


Lesenswert?

Also abgesehen von dem Thema hätt ich doch gern nochwas gewusst. Ich 
habe da zwei Funktionen einmal Fash_write und eine Flash_read, 
Flash_write schreibt die Daten ins Flash, wenn ich jetzt mit dem 
Debugger über der Funktion steppe ohne in die Funktion reinzugehen 
sendet er richtige Daten die sehe ich auch in meiner VAriable und Oszi, 
wenn ich jedoch jetzt über meine Funktion Flash_read steppe ohne 
reinzusteppen, dann zeigt es mir nichts in meiner Variable an obwohl am 
oszi die richtgen Daten empfangen wurden, wenn ich dann in die Funktion 
reinsteppe und schritt für schritt steppe und aus der Funktion heraus 
komme hat die Variable der Funktion die Daten vorhanden und ich kann die 
dann weiter bearbeiten. Vorher hatte ich den code für schreiben und 
lesen in main, dann hab ich die in 2 Funktionen gepackt, verstehe jetzt 
nicht warum die VAriable keine daten enthält wenn ich über Funktion 
drüber steppe.
In der Schreibfunktion kommen die opcodes 84H und 83H wie weiter oben 
und in Lesefunktion OPcode 53H und D1H.

Meine Funktion:
1
void SFlash_write(unsigned long *Data, unsigned short Len);
2
void SFlash_read(unsigned long *Data, unsigned short Len);

von Lattice User (Gast)


Lesenswert?

Ich nehme mal an, dass Impact die Daten auch zurücklesen kann, und damit 
sichergestellt ist, dass da kein HW Schreibschutz aktiviert ist.


Olli schrieb:
> was genau meinst du damit, habe ich nicht verstanden. 04 ist auch ein
> OPcode?

Siehe hier. Hat mit dem Flash nichts zu tun, aber das Intelhex format 
das im mcs File verwendet wird hatte ursprünglich nur 16bit Adressen.
http://en.wikipedia.org/wiki/Intel_HEX

Olli schrieb:
> In der Schreibfunktion kommen die opcodes 84H und 83H wie weiter oben

Da fehlt noch D7H. Lies mal das Kapitel "Status Register Read" im 
Atmeldatasheet.

Auch beim Lesen über die Buffer kann es nötig sein das Ready bit 
abzufragen.

von PittyJ (Gast)


Lesenswert?

Hm, was sollen wir mit den Funktionsköpfen anfangen?

Ich hätte ja geschrieben:

int SFlash_read(unsigned long *Data, unsigned short &Len);

Dann könnte man noch einen Fehlerstatus und die tatsächlich gelesene 
Länge wieder zurückgeben.

von Olli (Gast)


Lesenswert?

Danke für deine Antwort,
was ich aber nicht verstehe ist, warum alles funktionierte als ich alles 
im main hatte und jetzt in  Funktionen gepackt geht das lesen nicht 
mehr, doch es geht am Oszi sehe ich das alles richtig durchgeführt wird, 
nur meine variable Data hat keine Daten. Jedoch in die Funktion schritt 
für schritt gesteppt geht ja auch. nur drüber steppen nicht. Gut schaue 
ins Datenblatt.

von Olli (Gast)


Lesenswert?

Ich habe weiter oben den gesamten Code angegeben, hab mit den Opcodes 
beschrieben, welcher opcode teil in welche Funktion kommt, um nicht die 
gesamte Funktion nochmal anzugeben.

von Olli (Gast)


Lesenswert?

So hab jetzt nach jedem Command Status Register abfrage hinzugefügt und 
es funktioniert, ich kann drübersteppen und die Daten werden auch 
angezeigt.

Nun bleibt noch, dass ich aus dem Flash, was per Impact geflasht wurde 
nicht richtig zurücklesen kann, wie ist denn das eigentlich zu 
verstehen, wenn ich mit 03H lesen will und einfach eine Addresse angebe, 
muss ich da eigentlich nicht die passende Addresse zum Intel Hex format 
anegeben oder erkennt das Flash seöber dass die Addresse z.B A angefragt 
ist oder muss ich die ganze Addresse angeben nämlich 1000A000 laut 
unterem Intel Hex format:

:1000A0009AC20000000000000000000000000000F4

von Martin M. (capiman)


Lesenswert?

> :1000A0009AC20000000000000000000000000000F4

> http://en.wikipedia.org/wiki/Intel_HEX

Hast Du Dir den obigen Link von Lattice User mal angeschaut?

von Olli (Gast)


Lesenswert?

Hallo,
natürlich habe ich es gelesen, verstehe aber nicht ganz den zusammenhang 
und wie genau ich jetzt dies übersetzen soll.

von Martin M. (capiman)


Lesenswert?

Ohne Gewähr

:1000A0009AC20000000000000000000000000000F4

: 10 00A0 00 9AC20000000000000000000000000000 F4

":"    = Startcode
"10"   = Byte Count
"00A0" = Address
"00"   = Record Type (0x00 = Data Record)
"9AC20000000000000000000000000000" = Data
"F4"   = Checksum


:020000040000FA

: 02 0000 04 0000 FA

":"    = Startcode
"02"   = Byte Count
"0000" = Address
"04"   = Record Type (0x04 = Extended Linear Address Record)
"0000" = Data (wird als obere 16 Bit der 32 Bit Adresse verwendet)
"FA"   = Checksum

-> sagt Dir im Endeffekt nur aus, dass die oberen 16 Bit der 32 Bit 
Adresse auf 0 stehen

von Olli (Gast)


Lesenswert?

danke das du ausfürhlich ausgeführt hast, bis hierhin habe ich es auch 
verstanden, nur wie sage ich jetzt dem Flash dass ich die Daten von der 
Addresse wie im Beispiel:00A0 lesen will. wenn ich jetzt den lese opcode 
mit der Adresse 00A0 schicke, würde das Flash dann richtig anordnen und 
mir die richtige Daten ausgeben, oder gibt er dann die gesamte Zeile 
aus. Mir hakt es am Verständnis der Übersetzung im c code. Es ist mir 
schon klar wie die Zeile zu verstehen ist.

von Martin M. (capiman)


Lesenswert?

Schick doch einfach mal Adresse 0 und lese dann 512 (oder 256?)
Bytes, dann sollte die Adresse 0x00A0 darin enthalten sein.
Die ersten Bytes (4 * 16 + ein paar) werden korrekt auf 0xFF stehen,
dann solltest du etwas sehen, was deinem Hexfile entspricht
und ungleich 0xFF ist.

Im Datenblatt des Flash-Chips steht dann genau,
wie die Adresse umgerechnet wird bzw. was du nach dem Opcode angeben 
musst.
Dort ist z.B. die niedrigste Stelle A9 (oder so), dann musst
du die Adresse um 9 Bits schieben, damit A9 an die Stelle rutscht,
wo du (oder besser der Atmel) sie im Opcode haben willst (will).

von Olli (Gast)


Lesenswert?

Hallo Danke vielmals für deine Hilfe, hat geklappt, hab jetzt 
verstanden, dass die Addresse  00A0 z.B nur beginn der Addresse ist um 
natürlich ein bestimmtes byte auszulesen, muss ich nat. bis zu diesem 
byte die addresse hochzählen. Hat ja wunderbar geklappt, war nur 
irritiert von den ganzen 0xFF s aber gut. Danke nochmal.

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.