Forum: FPGA, VHDL & Co. SPI Flash programmieren


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Olli (Gast)


Lesenswert?

Hallo,
bin dabei das SPI Flash zu über einen uc programmieren, wobei das FPGA 
die Konfigurationen aus dem Flash holt. hab das SPI in dem Uc 
konfiguriert, über einem Oszilloskop sehe ich die Daten ins SPI Flash 
gehen nur beim zurücklesen tu ich nicht das richtige lesen. Soweit ich 
weiß hat das FPGA einen Prog_B Pin als Input, welches für die 
Konfiguration notwendig ist.
Nun, weiß ich nicht ganz genau, wann der auf Low gesetzt werden soll und 
wann High, hab mir das Datenblatt angesehen, werd nicht schlau daraus.

das SPI write sieht so aus
SPI_INIT:
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_GPIOG);
6
7
          GPIOPinConfigure(GPIO_PA2_SSI0CLK);
8
          GPIOPinConfigure(GPIO_PA4_SSI0RX);
9
          GPIOPinConfigure(GPIO_PA5_SSI0TX);
10
                                                              //| GPIO_PIN_3
11
          GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_2);
12
          GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);//
13
          //GPIOPinTypeGPIOOutputOD(GPIO_PORTD_BASE, GPIO_PIN_6);//INIT PIN
14
          GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_7); //PROG_B
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_PORTG_BASE, GPIO_PIN_7, 0);
21
22
         GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_7, 'z'); //'z'
23
         GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS low
1
   GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
2
//------------------------------------------------------------------------------
3
         //Buffer 1 write
4
             SSIDataPut(SSI0_BASE, 0x84);
5
             SSIDataGet(SSI0_BASE, &dummy);
6
             SSIDataPut(SSI0_BASE, 0x00);
7
             SSIDataGet(SSI0_BASE, &dummy);
8
             SSIDataPut(SSI0_BASE, 0x00);
9
             SSIDataGet(SSI0_BASE, &dummy);
10
             SSIDataPut(SSI0_BASE, 0x00); 
11
             SSIDataGet(SSI0_BASE, &dummy);
12
13
          //send Data
14
          for(ulindex = 0; ulindex < Len; ulindex++)
15
            {
16
             SSIDataPut(SSI0_BASE, Data[ulindex]);
17
             SSIDataGet(SSI0_BASE, &dummy);
18
            }
19
20
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);            //Deselect the Flash chip
21
22
             //wait some time
23
             for(i=0; i<30; i++);
24
25
             //Status Register Ready, ready or busy
26
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);
27
             SSIDataPut(SSI0_BASE, 0xD7);
28
             SSIDataGet(SSI0_BASE, &dummy);
29
30
             for(ulindex = 0; ulindex <= o; ulindex++)
31
             {
32
               SSIDataPut(SSI0_BASE, dummy);
33
               SSIDataGet(SSI0_BASE, &SR);
34
               if(SR != 0xAD){
35
               o++;
36
               }
37
             }
38
39
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High
40
41
             while(SSIBusy(SSI0_BASE))
42
             {
43
             }
44
             //wait some time
45
             for(i=0; i<20; i++);                                                                       //Give the flash some time
46
47
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //CS Low
48
49
             //Main Memory page write
50
             SSIDataPut(SSI0_BASE, 0x83);
51
             SSIDataGet(SSI0_BASE, &dummy);
52
             SSIDataPut(SSI0_BASE, 0x00);
53
             SSIDataGet(SSI0_BASE, &dummy);
54
             SSIDataPut(SSI0_BASE, 0x00); //SSIDataPut(SSI0_BASE, 0x0A);
55
             SSIDataGet(SSI0_BASE, &dummy);
56
             SSIDataPut(SSI0_BASE, 0x00);
57
             SSIDataGet(SSI0_BASE, &dummy);
58
59
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High
60
61
             //wait some time
62
             for(i=0; i<20; i++);
63
64
             //Status Register Ready, ready or busy
65
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS Low
66
             SSIDataPut(SSI0_BASE, 0xD7);
67
             SSIDataGet(SSI0_BASE, &dummy);
68
69
             for(ulindex = 0; ulindex <= o; ulindex++)
70
             {
71
               SSIDataPut(SSI0_BASE, dummy);
72
               SSIDataGet(SSI0_BASE, &SR);
73
               if(SR != 0xAD){
74
               o++;
75
               }
76
             }
77
78
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High

Ist es so richtig, oder muss es anders initialisiert werden??

von pks (Gast)


Lesenswert?

Mir ist Dein Aufbau noch nicht ganz klar.
Das FPGA soll sich aus dem Flash selbst konfigurieren?
Was für ein FPGA überhaupt?

Olli schrieb:
> ...nur beim zurücklesen tu ich nicht das richtige lesen.

Was man nicht alles tun tut :-)

Wer liest denn da? Der UC?

von Olli (Gast)


Lesenswert?

Also ich habe einen bootloader so umprogrammiert, sodass ich entweder 
das interne Flash von einem Mikrocontroller flashen kann oder eben ein 
ext. Flash, was Parallel zu einem FPGA angeschlossen ist.

Wenn ausgewählt wird, dass das ext. Flash geflasht werden soll, wird 
dann das SPI über GPIO initialisiert und die Daten werden von einer 
binary file ins SPI Flash geladen. Das binary File habe ich aus einer 
.mcs file erstellt.

Nun das schreiben funktioniert soweit, aber ich glaube, dass wenn ich 
schreiben tue, dass das Flash die Daten nicht abspeichert, da das Prog_B 
Pin nicht richtig gesetzt wird, oder wie auch immer.

Meine Frage ist nur, wie und wann soll das Prog_B richtig gesetzt 
werden.
Wann kann das SPI Flash denn konfiguriert werden, solange es low ist, 
oder muss ein low -> high erfolgen, damit es richtig konfiguriert wird.

von Olli (Gast)


Lesenswert?

Es ist ein Spartan 3E, und der Mikrocontroller ist ein von Stellaris 
LM3S9B96. Ja Der FPGA holt sich die Daten aus dem SPI Flash.

von Christian R. (supachris)


Lesenswert?

Der SPI Flash kann immer beschrieben und gelesen werden, wenn der 
Spartan da nicht aktiv drauf rum klimpert. Und das macht er nur während 
er sich die Konfig aus dem Flash zieht (wenn Master SPI als BootMode 
gewählt ist). Nachher kannst/musst du die SPI Pins hochohmig setzen (im 
FPGA Design), dmait der µC drauf zugreifen kann. Das PROG_B hat damit 
erst mal gar nichts zu tun. Mit einem Low-Impuls auf PROG_B kannst du 
den FPGA veranlassen, neu zu starten.

von Olli (Gast)


Lesenswert?

Also, erst wenn ich Prog_B auf low setze kann ich in das SPI Flash 
schreiben sonst nicht, ausserdem, wird doch das INIT_B doch erst nachdem 
Prog_B initialisiert, also brauch ich doch das Prog_B Pin.

Im Datenblatt steht:

Drive PROG_B Low and
release to reprogram
FPGA. Hold PROG_B to
force FPGA I/O pins into
Hi-Z, allowing direct
programming access to
SPI Flash PROM pins.

also muss doch der Prog_B Pin solange low sein, bis das SPI Flash 
programmiert wird???

von Christian R. (supachris)


Lesenswert?

Na das geht auch. Solange PROG_B low ist, ist der FPGA im Wartezustand 
und macht alle Pins hochohmig. Dann kannst du auch auf den SPI Flash 
zugreifen. Und wie soll eigentlich Schreiben funktionieren ohne lesen zu 
können? Du musst ja immerzu das Statusregister pollen, um herauszufinden 
ob das Schreiben/Löschen fertig ist. Wenn du im Laufenden Betrieb des 
FPGA auch auf den Flash vom µC zugreifen willst, musst du im FPGA Design 
dafür sorgen dass die Pins als Eingang oder hochohmig geschaltet sind.

von Olli (Gast)


Lesenswert?

Ja die Status abfrage tu ich ja nach jedem senden, bis er fertig ist mit 
dem Schreiben.

Das Flash des uc tu ich ja mit dem uc Flashen, die Sache ist die, dass 
der uc das ext. Flash flashen soll.

Leider tut er aber nicht in das SPI Flash schreiben, dass versteh ich 
nicht. Prog_B wird auf Low gesetzt und dann schreibe ich ins Flash. Dann 
wird Prog_B durch den reset wieder auf High gesetzt.

von pks (Gast)


Lesenswert?

Wie verfizierst Du denn, dass die Daten nicht ins Flash geschrieben 
werden? Liest Du den Inhalt mit dem uc aus?

von Lattice User (Gast)


Lesenswert?

Das hier kann vom Compiler wegoptimiert werden.
1
             //wait some time
2
             for(i=0; i<20; i++);

Wie hast du festgestellt dass der Flash nicht geschrieben wird?
Zurücklesen?
oder FPGA Bootet nicht?

Was mir sonst noch auffällt:
1
          //send Data
2
          for(ulindex = 0; ulindex < Len; ulindex++)
3
            {
4
             SSIDataPut(SSI0_BASE, Data[ulindex]);
5
             SSIDataGet(SSI0_BASE, &dummy);
6
            }
Ist "Len" die Gesamtlänge des Bitstreams?
Wenn ja, dann passt es garantiert nicht in den Buffer des Flashs (ist 
doch ein Atmel?)

von Olli (Gast)


Lesenswert?

@pks
Ja ich lese den Inhalt mit dem uc aus. Hab eine Routine geschrieben, 
über eine Kommandozeile wird eine Addresse eingegeben und mit dieser 
Addresse entscheide ich ob das int. oder ext. Flash geflasht werden 
soll.

Ja also, wenn ich das Flash auslese, sind da nicht die richtigen Daten 
da. Z.B. wenn ich jetzt mit dem Xilinx USB flashe (mit Impcat) und dann 
zurücklese, dann lese ich die richtigen Daten zurück. Nur wenn ich jetzt 
direkt das SPI auf meine Art Flashe geht das leider noch nicht, obwohl 
auf den Dateneingangs Pin die richtigen Daten anliegen, schreibe.

Das Flash hat ja 4096 pages und pro page 512 bytes, LEN ist dann die 
Länge einer Page und ich sende dann pageweise an das SPI Flash, Addresse 
ist ja null, inkrementieren tut er ja dann selbst. ullindex ist 512 
bytes, das sollte doch passen oder nicht??

von Lattice User (Gast)


Lesenswert?

Olli schrieb:

> Das Flash hat ja 4096 pages und pro page 512 bytes, LEN ist dann die
> Länge einer Page und ich sende dann pageweise an das SPI Flash, Addresse
> ist ja null, inkrementieren tut er ja dann selbst.

Hmm, nein.
1
             //Main Memory page write
2
             SSIDataPut(SSI0_BASE, 0x83);
3
             SSIDataGet(SSI0_BASE, &dummy);
4
             SSIDataPut(SSI0_BASE, 0x00);
5
             SSIDataGet(SSI0_BASE, &dummy);
6
             SSIDataPut(SSI0_BASE, 0x00); //SSIDataPut(SSI0_BASE, 0x0A);
7
             SSIDataGet(SSI0_BASE, &dummy);
8
             SSIDataPut(SSI0_BASE, 0x00);
9
             SSIDataGet(SSI0_BASE, &dummy);

Schreibt alle deine Buffer auf Page 0.

von Christian R. (supachris)


Lesenswert?

Hast du vielleicht außerdem das Bit- und Byte Swapping von Xilinx 
vergessen?

von Holger H. (holger-h-hennef) Benutzerseite


Lesenswert?

Olli schrieb:
> Ist es so richtig, oder muss es anders initialisiert werden??
Ja wenn sich das SPI-FProm im sleep mode ist, ist ohne spez.
SPI wake Command via MCU nichts auszulesen.
Tip:
Hast du mal das Daten-Blatt vom SP-AT25DF041A gelesen?.
Dieses SPI-Prom hat den Fast-Load Mode.
Das SPI-Prom sollte auch zum jeweiligen FPGA passen.
-----------------------------------------------------------------------
Hint:
B_PROG ist evtl. der /CS bzw SlaveSel Pin für SPI-FProm.
########################################################################
Lattice hat ein neues iCE40 Ref-DesignBoard mit Doku.
Die auf der Homepage hinterlegt ist.

(bzw. Digilent ADEPT Software (SPI-PROM-Modul) loader )
Da ist eine MCU AT90USB162 und das SPI-Flash-Prom und das FPGA iCE40
verbaut.
So hast du ein Ref-Design mit den Infos zum Config
via SPI-Prom-->iCE40FPGA.
########################################################################
http://www.latticesemi.com/documents/TN1204.pdf
 Aus dem MachXO2 SPI Design
 Wichtiges zu /CS des SPI-PROMS--via ext. Pull-UP.
1
Seit: 14/15 
2
Some SPI PROM manufacturers require the chip select input of the PROM ramp in unison to the PROMs VCC rail.
3
The CSSPIN pin, by default, has a weak pull-down resistor internally. Adding a 4.7K to 10K ohm pull-up resistor to
4
the CSSPIN pin on the MachXO2 is recommended.
5
SI/SISPI: The SI/SISPI is a dual function bi-directional pin. The direction depends upon whether a Master or Slave
6
mode is active. The SI/SISPI is an input data pin when using the Slave SPI mode and is an output data pin when
7
using the Master SPI mode. In Master SPI mode, the MachXO2 drives SI/SISPI until all configuration data bytes
8
have been loaded, at which time the SI/SISPI enters a high impedance state.

von Holger H. (holger-h-hennef) Benutzerseite


Lesenswert?

Hier noch das SPI Prom FPGA-Config.
Der SPI-CLK hat einen ext.Pull-Up, somit ist das FPG-SPI_Master.
SPI CLOCK-Phase & SPI-CLK-POL beachten.
Link:
http://www.latticesemi.com/documents/TN1248.pdf

Viel Erfolg.

Gruss Hilger.

von Olli (Gast)


Lesenswert?

Lattice User schrieb:
> Schreibt alle deine Buffer auf Page 0.

wie jetzt, soll das heißen, dass die Page 0 immer wieder überschrieben 
wird und somit nur die Page 0 beschrieben wird??. Das erklärt dann auch 
warum es nicht funktioniert, bisher. Heißt das, dass ich die pages in 
einer Schleife hochzählen muss??

Was genau ist das Bit- und Byte Swapping von Xilinx ??

von Christian R. (supachris)


Lesenswert?

Natürlich musst du die Pages hochzählen, bzw. die Startadressen korrekt 
schreiben.

Xilinx hat da extrem doofe Sachen.

Bit-Swapping:

Bei Xilinx Spartan 3 ist D0 das MSB. Wenn du jetzt mit den Xilinx Tools 
den Flash beschreibst, wird das alles korrekt geswapt. Wenn du aber mit 
einem externen Tool was machst, musst du aufpassen, denn vom Bit-File 
ins MCS File gibts bei SPI Flash einen Bitswap, da werden pro Byte alle 
Bits gedreht, also D0 wird D7, D1 wird D6 usw.
Am besten siehst du das am Header, der muss dann mit AA 99 55 66 
beginnen. Und so stehts dann auch im SPI Flash. Wenn du das Bit Swapping 
drin hast, weil das MCS File für einen Platform Flash oder einen BPI 
Flash erstellt ist, ist der Header 99 55 66 AA.

Siehe UG628, Seite 271.

Byte-Swapping:

Wenn du den Flash 8 Bit Weise beschreibst, ist das kein Thema. Wenn du 
aber z.B. einen 16 Bit Prozessor hast, und beim Schreiben gleich immer 
16 Bit an den SPI Flash schickst, musst du vorher die Bytes tauschen, 
sonst steht das HighByte im LowByte und umgekehrt.

von Olli (Gast)


Lesenswert?

Also das heißt byte Addresse kann immer bei null bleiben jedoch die 
Pageaddressen muss ich hochzählen sozusagen.

Ne also wenn ich das mcs file umgesetzt habe, steht immer noch im Header 
AA 99 55 die richtige reihenfolge und auf dem Oszi angesehen, stimmt es 
auch wieder. Ich schicke immer 8-bits zum Flash.

von Olli (Gast)


Lesenswert?

So habs nun Umgesetzt, hoffe es ist richtig so:

1
uint16_t page = 0x0;
2
  uint16_t byte = {0};
3
  uint8_t addressfield[3];
4
5
  page &= 0xfff;
6
  byte &= 0x1ff;
7
8
  page++;
9
10
   GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //Select the Flash chip
11
        
12
 //Buffer 1 write
13
             SSIDataPut(SSI0_BASE, 0x84);
14
             SSIDataGet(SSI0_BASE, &dummy);
15
             SSIDataPut(SSI0_BASE, 0x00);
16
             SSIDataGet(SSI0_BASE, &dummy);
17
             SSIDataPut(SSI0_BASE, 0x00);
18
             SSIDataGet(SSI0_BASE, &dummy);
19
             SSIDataPut(SSI0_BASE, 0x00); //SSIDataPut(SSI0_BASE, 0x0A);
20
             SSIDataGet(SSI0_BASE, &dummy);
21
22
          //send Data
23
          for(ulindex = 0; ulindex < Len; ulindex++)
24
            {
25
             SSIDataPut(SSI0_BASE, Data[ulindex]);
26
             SSIDataGet(SSI0_BASE, &dummy);
27
            }
28
29
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);            //Deselect the Flash chip
30
31
             //wait some time
32
             for(i=0; i<30; i++);
33
34
             //Status Register Ready, ready or busy
35
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);
36
             SSIDataPut(SSI0_BASE, 0xD7);
37
             SSIDataGet(SSI0_BASE, &dummy);
38
39
             for(ulindex = 0; ulindex <= o; ulindex++)
40
             {
41
               SSIDataPut(SSI0_BASE, dummy);
42
               SSIDataGet(SSI0_BASE, &SR);
43
               if(SR != 0xAD){
44
               o++;
45
               }
46
             }
47
48
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High
49
50
             while(SSIBusy(SSI0_BASE))
51
             {
52
             }
53
             //wait some time
54
             for(i=0; i<20; i++);                                                                       //Give the flash some time
55
56
             addressfield[0] = (uint8_t) (page >> 3);
57
             addressfield[1] = (uint8_t) (page << 1) | (uint8_t) (byte >> 8);
58
             addressfield[2] = (uint8_t) (byte & 0xff);
59
60
61
62
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0);            //CS Low
63
64
             //Main Memory page write
65
             SSIDataPut(SSI0_BASE, 0x83);
66
             SSIDataGet(SSI0_BASE, &dummy);
67
68
             for(i=0; i<3; i++){
69
70
               SSIDataPut(SSI0_BASE, addressfield[i]);
71
               SSIDataGet(SSI0_BASE, &dummy);
72
73
             }
74
75
             GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High

Hier hab ich zwar mit Opcode 84h und 83h realisiert, werde jedoch zu 82h 
umsteigen, da alles in einem Befehl passiert.

Verständnisfrage: kann ich einfach so machen, wie oben, dass ích die 
page einfach hochzähle nachdem ein bitstream gesendet wurde und das 
nächste bitstream kommt, oder kann man das auch besser realisieren, die 
Page wird ja nicht mitgesendet, deshalb versteh ich nicht ganz, wie 
genau er dann hochzählen soll. Vielleicht kann mir einer eine bessere 
Idee vorschlagen.

von Christian R. (supachris)


Lesenswert?

Olli schrieb:
> Verständnisfrage: kann ich einfach so machen, wie oben, dass ích die
> page einfach hochzähle nachdem ein bitstream gesendet wurde und das
> nächste bitstream kommt,

Hä? Wo denn jetzt mehrere Bitstreams? Wie so ein Flash programmiert 
wird, steht eindeutig im Datenblatt des Flash Chips. Was hat das mit 
Bitstreams zu tun?

von Olli (Gast)


Lesenswert?

Nagut hab mich falsch ausgedrückt. Was ich aber nicht verstehe ist, wie 
genau soll ich jeztzt die pages hochzählen, die pages werden ja nicht 
vom host vorgegeben. kannst du mir ne Idee geben wie ich das realisieren 
kann. Es wird nicht laut dem obigen code hochgezählt folglich wird nur 
in der page 0 alles reingeschrieben. Bin sehr dankbar wenn mir einer 
hier helfen kann, bin fast fertig, nur das mit dem Flash klappt nicht so 
ganz.

von Christian R. (supachris)


Lesenswert?

Du musst anhand des Datenblattes rausfinden, wie groß eine Page ist, wie 
groß ein Sektor ist usw. und dann dementsprechend einen 
programmier-Algoritmus entwickeln. Der Flash kann sektor- block- oder 
pageweise gelöscht werden (wenn man kein Mass-Erase machen will) und 
page-weise beschrieben werden. Hochzählen musst du eigentlich nur die 
Start-Adressen, aber du musst dem Flash das halt häppchenweise 
schreiben, die Page-Grenzen dabei beachten. Die unteren 8 Bit werden vom 
Flash ausmaskiert, wenn der z.B. 256 Byte Page-Größe hat.

von pks (Gast)


Lesenswert?

Ich versteh das Problem nicht ganz. Nächste Adresse = aktuelle Adresse + 
Page Size...

von Olli (Gast)


Lesenswert?

Die Page habe ich auf die größe von 512 bytes festeingestellt, dass kan 
man bei dem Flash zwischen 528 oder 512 bytes einstellen.
Warum denn das, das Flash hat 4096 pages, bei den einem Flash file 
ergeben sich 2081 pages. folglich ist die Startaddresse der page 0 
anschließend bis 2081.

in einer endlosschelife wird auf einen Interrupt gewartet, sobald die 
ersten daten mit 512 bytes gesendet werden, wird der Interrupt ausgelöst 
und die Programmierung erfolgt anhand folgender abfrage:
1
 SFlash_Init();
2
//---------------modified for ext. Flash-------------------------------------------------
3
            switch(bl_GetDeviceType(ulStart))
4
            {
5
              case DEVICE_EXTERNAL_FLASH:
6
              {
7
                if(usUsed < 10){
8
                  break;
9
                }
10
                else{
11
12
                  SFlash_write((unsigned char*)g_pcDFUWrite , usUsed);
13
//                  counter += usUsed;
14
                  //SFlash_read((unsigned long*)Data , usUsed);
15
                }
16
                  break;
17
18
              }
19
20
              case DEVICE_INTERNAL_FLASH:
21
              {
22
                  BL_FLASH_PROGRAM_FN_HOOK(ulStart, g_pcDFUWrite, usUsed);
23
                  break;
24
              }
25
            }

dann geht er ja ieder in der endlosschelife, nachdem das erste page 
programmiert wurde und wartet auf die nächsten Daten.usUsed sind die 512 
bytes und g_pcDFUWrite sind die Daten.SFlash_write habe ich ja weiter 
oben angegeben

von Lattice User (Gast)


Lesenswert?

Interner Flash?
Könnte es sein, dass du das ganze mit dem interen Flash des LM3S9B96 
verschwurbelt und dich damit ziemlich gründlich vergaloppiert hast?

Übrigens dein page++ steht an der falschen Stelle.

von Olli (Gast)


Lesenswert?

ja hab das gemerkt habs verbessert und in der funktion eingebaut, jeztt 
funktioniert auch das hochzählen. Ne andere Frage, die Byteaddressen 
muss ich aber nicht hochzählen, da brauch ich ja nur die Startaddresse 
festlegen, also kann ich die unteren 9 bits immer auf null lassen oder?

von Christian R. (supachris)


Lesenswert?

Beim Schreiben bist du an die Page gebunden, da musst du immer am 
Page-Anfang anfangen, laut Datenblatt wird die Byte-Adresse innerhalb 
der Page ignoriert. Jedenfalls hatte ich mal schnell beim AT45DB081D 
reingeguckt. Da stehts ja eindeutig drin.

von Olli (Gast)


Lesenswert?

Ja gut, die ersten 12 bis sind ja um die einzelnen Pages auszuwählen, 
aber doch nicht für die Startaddresse der pages, ich gehe davon aus, 
dass wenn ich die einzelnen Pages erhöhe, dass er immer von Anfang 
anfängt reinzuprogrammieren. Bis gestern habe ich zwar geschafft, dass 
ich jetzt auch noch richtige Daten der einzelnen Pages zurücklesen kann, 
destotrotz funktioniert es nicht, dass das FPGA richtig konfiguriert 
ist. Hab mal testhalber das DONE PIn das INIT_B PIn und das Prog_B Pin 
am Oszi ausgegeben, wenn ich jetzt über Impact und dem USB programmer 
das SPI Flash programmiere, dann sehe ich, wie die DONED und INIT_B und 
Prog_B Pin auf low gehen und wenn das Flashen fertig ist, gehen die Pins 
am Ende wieder auf High, und wenn DONE auf High geht, heißt doch, dass 
der FPGA richtig konfiguriert wurde. Jedoch wenn ich jeztzt auf meiner 
Atr Flashe, tue ich ja einmal den Prog_B Pin selbst auf Low setzen und 
am Ende auf High setzen. jedoch das DONE Pin bleibt immer bei LOW, sowie 
das INIT_B Pin. Die gehen nicht auf high, davon gehe ich aus, dass der 
FPGA nicht konfiguriert wurde, obwohl das SPI Flash richtig programmiert 
wurde. Was kann ich denn jetzt tun, sollen diese PIN Pageweise auf low 
und high gesetzt werden oder sollen die PINS während des gesamten 
Prozesses auf low sein und am Ende auf High gehe, das habe ich auch 
nicht ganz verstanden.

von pks (Gast)


Lesenswert?

Olli schrieb:
> oder sollen die PINS während des gesamten
>
> Prozesses auf low sein und am Ende auf High gehe
Ja

Weiter oben hat jemand beschrieben, dass die Daten eventuell noch 
gedreht werden müssen. Hast Du das mal geprüft?

von Olli (Gast)


Lesenswert?

Also wenn ichs auf dem Oszi es betrachte, dann sehe ich die Daten in der 
richtigen Reihenfolge. wenn im file steht AA 99 30 ... dann sehe ich 
genauso auch am oszi und nicht irgendwie verdreht, sowieso tu ich immer 
8 bit reinschreiben.

von Lattice User (Gast)


Lesenswert?

Olli schrieb:
> Was kann ich denn jetzt tun, sollen diese PIN Pageweise auf low
> und high gesetzt werden oder sollen die PINS während des gesamten
> Prozesses auf low sein und am Ende auf High gehe, das habe ich auch
> nicht ganz verstanden.

Nein. Das FPGA weiss von den Pages nichts. Das sendet einfach einen 0x03 
oder 0x0B mit einer festen Startaddresse (typischerweise) und liest das 
Flash in einem Rutsch aus.

Das Auslesen in einem Rutsch geht nur wenn die Pagesize auf 512 Bytes 
eingestellt ist. Factorydefault sind aber die 528 Bytes. Das muss 
einmalig bei der Inbetriebnahme umgestellt werden. Normalerweise macht 
das der Xilinx Programmer (Impact?) automatisch wenn er einen Atmelflash 
erkennt, ohne dass du das mitkriegst.

Das pageweise Programmieren ist übrigens eine Spezialität der Atmel 
Dataflashes, bei anderen Herstellern sieht das anders aus.

von Christian R. (supachris)


Lesenswert?

Init_B muss aber einige µs nachdem du Prog_B wieder auf High gesetzt 
hast, auch auf High gehen, signalisiert damit, dass das FPGA intern 
alles gelöscht hat und bereit zur Konfig ist (in deinem Fall müsste dann 
der Zugriff auf das SPI Flash erfolgen). Lies doch mit Impact mal das 
File aus und vergleiche es mit dem ursprünglichen.

von Olli (Gast)


Lesenswert?

So, Danke für euere Hilfe, es klappt wie es klappen sol, hab das Flash 
gelöscht und seitdem funktioniert es, die Pins kommen dann auch auf High 
nach dem Ende.
Ja hab die Pagegröße auf 512 bytes umgeändert. Das mit dem Init_B Pin 
muss ich noch überprüfen, ich denk mal dass ich den selbst auf High 
setzen werde. Komischerweise, ist der INIt_B Pin dden Ganzen prozess 
lang auf low, am ende mach ich ein reset und dann gehen auch alle Pins 
auf High. Aber es funktioniert. Danke nochmal an alle.

von Christian R. (supachris)


Lesenswert?

Dann fehlt vielleicht der Pull-Up Widerstand an Init_B.
Natürlich musst du den Flash erst löschen, bevor du ihn beschreiben 
kannst.

von Lattice User (Gast)


Lesenswert?

Christian R. schrieb:
> Natürlich musst du den Flash erst löschen, bevor du ihn beschreiben
> kannst.

Das sollte der von Olli verwendete Befehl 0x83 eigentlich automatisch 
machen. Also muss er da noch einen anderen Bug haben.

von Olli (Gast)


Lesenswert?

Sagen wir so, der Init_B Pin geht ja paar us später auf High sobald 
Prog_B auf High geht, dann ist es ja in ordnung, nach dem das Flash 
komplett programmiert wird, geht ja Prog_B high und paar us später, habs 
mit oszi geshen geht auch INIT_B auf high. Somit klappts.

Ich hätte da doch noch eine Frage. Da ich jetzt die .dll fertig habe, 
muss ich die jetzt im Windows Verzeichnis unter system32 mit der 
vorhandenen ersetzen um natürlich direkt mit der Konsolenanwendung 
benutzen zu können??

von Christian R. (supachris)


Lesenswert?

Olli schrieb:
> Ich hätte da doch noch eine Frage. Da ich jetzt die .dll fertig habe,
> muss ich die jetzt im Windows Verzeichnis unter system32 mit der
> vorhandenen ersetzen um natürlich direkt mit der Konsolenanwendung
> benutzen zu können??

Welche DLL auf einmal?

von Olli (Gast)


Lesenswert?

Am Anfang habe ich doch geschrieben, dass ich einmal das ext. Flash 
flashen will und einmal das interne eines Mikrocontrollers, dies soll 
über die Konsolenanwendung möglich sein, folglich, habe ich den pc 
seitigen code (hab da einen dfu programmer entwickelt, welches über eine 
USB Schnittstelle und einer binary datei das ext. Flash programmiert. ) 
so verändert, dass ich beide Flashs programmieren kann.
Der Endtest ist natürlich der, dass ich über die Konsolenanwendung 
teste.

von Olli (Gast)


Lesenswert?

Soda bin ich wieder, keine Sorge es läuft alles, wollte jedoch 
nachfragen, wie genautu ich das Flash löschen. Habs einmal mit Chip 
erase probiert und einmal page erase, beim letzteren bin ich mir nicht 
sicher wie ich die einzelnen pages ansprechen soll die gelöscht werden 
sollen.
Allgemein dazu, muss das Prog_B Pin beim löschen auch auf low dann High 
gesetzt werden oder kann man hier ohne diesen prog Pin löschen:

Chip Erase:

1
//-----------Chip erase
2
  GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS Low
3
    SSIDataPut(SSI0_BASE, 0xC7);
4
    SSIDataGet(SSI0_BASE, &dummy);
5
    SSIDataPut(SSI0_BASE, 0x94);
6
    SSIDataGet(SSI0_BASE, &dummy);
7
    SSIDataPut(SSI0_BASE, 0x80);
8
    SSIDataGet(SSI0_BASE, &dummy);
9
    SSIDataPut(SSI0_BASE, 0x9A);
10
    SSIDataGet(SSI0_BASE, &dummy);
11
  GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High

oder

Page erase:
1
addressfield[0] = (uint8_t) (page >> 7);
2
  addressfield[1] = (uint8_t) (page << 1) | (uint8_t) (byte >> 8);
3
  addressfield[2] = (uint8_t) (byte & 0xff);
4
5
  GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, 0); //CS Low
6
  SSIDataPut(SSI0_BASE, 0x81);
7
  SSIDataGet(SSI0_BASE, &dummy);
8
9
  for(t=0; t<4096; t++){
10
    page++;
11
    for(i=0; i<3; i++){
12
13
      SSIDataPut(SSI0_BASE, addressfield[i]);
14
      SSIDataGet(SSI0_BASE, &dummy);
15
16
    }
17
  }
18
  GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //CS High
19
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_7, GPIO_PIN_7); //Prog_B High

was meint ihr, mach ich da was falsch?? Bei PAge erase, da zählt er 
glaub ich die Pages nicht hoch.
Bei SPI_write hat das hochzählen funktioniert, da halt beim jeden senden 
der Daten hochgezählt wurde.

Mein Hauptprblem ist, wenn ich z.B gerade flashe und in der Mitte 
aufhöre,  dann den chip resette dann geht zwar Prog_B wieder auf High 
aber die anden Pins INIT_B und Done bleiben auf low, d.h. Flash wurde 
nicht gelöscht.

von Christian R. (supachris)


Lesenswert?

Olli schrieb:
> Mein Hauptprblem ist, wenn ich z.B gerade flashe und in der Mitte
> aufhöre,  dann den chip resette dann geht zwar Prog_B wieder auf High
> aber die anden Pins INIT_B und Done bleiben auf low, d.h. Flash wurde
> nicht gelöscht.

Logisch, weil der BitStream des FPGA dann nicht oder nicht vollständig 
im Flash ist. Auch wenn der Chip gelöscht ist, wird das Done auf Low 
bleiben. Mit dem Löschen hat das PROG_B erst mal gar nichts zu tun, 
sondern das schaltet offenbar in deinem Fall den Flash erst mal so frei, 
dass der µC drauf zugreifen kann. Natürlich kannst du auch das Page- 
oder Sector Erase verwenden, musst halt dann die Adressen mit 
hochzählen, bzw. vor dem Schreiben der Page mit der gleichen Adresse 
erst mal das Lösch Kommando auslösen und warten bis es fertig ist.

von Olli (Gast)


Lesenswert?

Ahh ok.
d.h. vor dem Schreiben der Page jedesmal erst 0x81h senden, dann erst 
die Pageaddresse? Also die for schelife mit t<4096 kann ich dann auch 
über das löschkommando setzen, dass es vor jeder Page das löschkommando 
schickt.

So wie ich die page hochzähle glaub ich ist es nicht richtig, da es 
weder im debugger hochzählt noch sehe ich das auf dem oszi, also immer 
null heißt immer die erste Page, wie zähle ich richtig hoch.

von Olli (Gast)


Lesenswert?

Hab das Block Erase ausgewählt, da erstens mal das chip erase für 
meinen chip nicht funktioniert, steht im Datenblatt, dass nicht für alle 
controller die gedacht ist. So wenn ich jetzt das Flash lösche, dann tut 
er zwar dies, aber am Ende, wenn das Prog_B pin high geht, bleibt der 
DONE PIn auf low, sowie der INIT_B Pin, somit klappt es nicht komplett. 
Die Frage stellt sich, warum geht der DONE PIn nicht auf high. Zum 
testen habe ich mir die einzelnen Pins am Oszi angeschaut wenn ich jetzt 
die Spannungsversorgung aus und dann wieder einschalte, dann sehe ich 
für kurze Zeit, dass das DONE Pin auf high geht , aber dann wieder auf 
low und währenddessen ist das INIT_B Pin auf low, das geht gar nicht auf 
High. Bim am Ende mit meinem Latein. Hab mit Impact das Flash 
ausgelesen, das Flash wird komplett gelöscht, das funktioniert aber weil 
der DONE Pin nicht auf high geht, weiß das FPGA Nicht das es 
konfiguriert ist, hänge jeztzt hier, fest, ansonsten hab ich alles was 
ich wollte.

Vielleicht kann mir einer nen guten Tip geben. Danke.

von Christian R. (supachris)


Lesenswert?

Das ist doch die völlig verkehrte Richtung. Beim Master SPI Mode am FPGA 
ist der FPGA der Master und lädt sich seinen Bitstream aus dem SPI 
Flash. Erst wenn der komplett und fehlerfrei im FPGA ist, dann setzt der 
FPGA das DONE auf High. DONE ist ein Ausgang des FPGA. Wenn du jetzt das 
Flash löschst, und dann PROG_B high gehen lässt, kann der FPGA jat gar 
keinen Bitstream laden, also kommt der DONE Pin nie hoch. Sobald du 
PROG_B low setzt wird das FPGA gelöscht und ist ab da nicht mehr 
konfiguriert. Da muss es erst wieder geladen werden oder als Master sich 
selbst laden (aus dem Flash). Komisch ist aber, dass INIT_B niht auf 
high geht, der muss eine Weile nach der Low-High Flanke vom PROG_B auf 
High gehen um zu signalisieren dass der FPGA jetzt komplett 
zurückgesetzt ist und auf eine Konfig wartet, bzw. im Master Mode mit 
der Konfig beginnt. Schau doch mal in den Konfiguration User Guide.

von Holger H. (holger-h-hennef) Benutzerseite


Angehängte Dateien:

Lesenswert?

Olli schrieb:
> Vielleicht kann mir einer nen guten Tip geben. Danke.
Im Anhang zip-File. Phython *.py Script Bit-File lesen.
Und das SPI-ROM -Dumpen mit z.B dem VHDL-Code aus dem Zip-File.
(Anpassen der Pinne- via *.UCF  )
###########################################################
Ich poste noch den Source-Code für den Atmel SPI 25
(SP-AT25DF041A) bzw. SPI Mode-0 bzw. (Mode-3 ??? ) via /CS
Vor dem eigentlichen Löschen muss da noch eine Sequenz davor gemacht 
werden.

Handbuch:
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_1/devref.pdf
Page# 255 ..Chapter 17....Bit-File swap Bit-Vector..+ Word-Byte swap..
Nach dem PROMGen LOFI Prinzip. Pipe Last-Out-->... -->Pipe First In.
######################################################################## 
###
Link:
http://www.xilinx.com/support/documentation/user_guides/ug332.pdf
(private ISC_DNA command)
Im Anhang Bild mit Pinne M0 Pin#69 = HIGH,  Pin#60 M1_M2 ist der FPGA 
Chip auch als Slave zu
schalten. Und wird via externer MCU mit dem Bit-Stream geladen.

Gruss Holger.

von Holger H. (holger-h-hennef) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hier der Anhang mit dem *.py script für das Bit-File.
Fazit:
Der Done-Pin ist der Monitor das der FPGA Chip
das Bit-Stream via ext. SPI-PROM akzepiert hat.
(Bit-Stream-CRC).
Du hast ja auch das Bit-File via Hilfe von Impact u.JTAG durch den
"FPGA Hardened-SPI Kernel " in das externe SPI-Prom geschrieben.
Damit ist das Tamper-Sicher mit der -Inique-FPGA.SerienID#
und dem SPI-Prom.Chip_ID# verheiratet. bingo|>
(private ISC_DNA command)
Gruss Holger.

von Olli (Gast)


Lesenswert?

Danke für deine ausführliche Antwort, jedoch läuft bei mir alles 
bereits. Was ich lediglich tue ist, dass ich erst das Gesamte Flash 
lösche aber die Pins nicht auf high setze dann program miere ich das 
Flash, anschließend setze ich den Prog_B Pin auf high, dann kann der 
FPGA auch sich konfigurieren .

Aber trotzdem Danke nochmal an alle die mich unterstützt haben.

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.