Forum: PC-Programmierung Flash QSPI write: pages?


von olpo (Gast)


Lesenswert?

Hallo,

ich schreibe gerade einen Flash qspi Treiber, der auf anderen Code 
basiert.
Ich moechte die Write Funktion davon benutzen, nur wird da irgendwas von 
pages geschrieben, das ich nicht verstehe.
1
 /*
2
* This function writes to the  serial Flash connected to the QSPI interface.
3
* All the data put into the buffer must be in the same page of the device with
4
* page boundaries being on 256 byte boundaries.
5
*
6
* @param  Address contains the address to write data to in the Flash.
7
* @param  ByteCount contains the number of bytes to write.
8
* @param  Command is the command used to write data to the flash. QSPI
9
*    device supports only Page Program command to write data to the
10
*    flash.
11
* @param  Pointer to the write buffer (which is to be transmitted)
12
*/

Also, ich moechte einen uint32_t buffer unbestimmter Groesse in Flash 
schreiben.
Was muss ich da mit den Pages beachten?
Oder kann ich meine Flash-Write Funktion einfach so aufrufen:
1
write( addr, buf_size, WRITE_CMD, buffer);

In den Beispielcode wird so aufgerufen:
1
/*
2
 * Number of flash pages to be written.
3
 */
4
#define PAGE_COUNT    32
5
6
  /*
7
   * Write the data in the write buffer to the serial Flash a page at a
8
   * time, starting from TEST_ADDRESS
9
   */
10
  for (Page = 0; Page < PAGE_COUNT; Page++) {
11
    FlashWrite((Page * Flash_Config_Table[FCTIndex].PageSize) + ADDRESS,
12
      Flash_Config_Table[FCTIndex].PageSize, WRITE_CMD, WriteBuffer);
13
  }

Danke

von abac (Gast)


Lesenswert?

olpo schrieb:
> Also, ich moechte einen uint32_t buffer unbestimmter Groesse in Flash
> schreiben.
> Was muss ich da mit den Pages beachten?

Folgende Gedankenstütze hilft:
 - Das Lesen ist meist völlig frei
 - Schreiben und Löschen geht nur in - nach im Datenblatt 
vorgeschriebenen - Blöcken

von olpo (Gast)


Lesenswert?

Was ist mit FlashErase().
Kann die denn auch nur in Page-Groessen erasen?

von Peter (Gast)


Lesenswert?

olpo schrieb:
> Was ist mit FlashErase().
> Kann die denn auch nur in Page-Groessen erasen?

Wenn du verrätst welchen Baustein du genau verwendest bzw. ein 
Datenblatt anhängst, kann man das nachschauen.

von olpo (Gast)


Lesenswert?

Es ist ein Spansion S25FL.

von olpo (Gast)


Lesenswert?

Es ist ein Spansion S25FL.

Bei FlashErase geht es ploetzlich um Sections?
Wad'n dad schon wieder?
1
  FlashErse()
2
...
3
/*
4
   * Calculate no. of sectors to erase based on byte count
5
   */
6
  NumSect = ByteCount/(Flash_Config_Table[FCTIndex].SectSize) + 1;
7
8
  /*
9
   * If ByteCount to k sectors,
10
   * but the address range spans from N to N+k+1 sectors, then
11
   * increment no. of sectors to be erased
12
   */

Wie soll ich denn da einen vernueftigen Schreibvorgang machen, der mir 
nicht andere Daten ueberschreibt?

von Christian R. (supachris)


Lesenswert?

Schau halt mal ins Datenblatt. Jeder Flash Speicher ist in Pages, 
Sectors, Blocks usw. aufgeteilt. Bei jedem etwas anders. Die meisten SPI 
Flashes haben 256 Byte große Pages, gelöscht werden muss aber in 
Sektoren, meist 4k oder gar 64k groß.
Du musst die Daten vorher halt auslesen und dann wieder schreiben, wenn 
du nur ein paar Pages oder gar Bytes ändern willst.
Für Byte-Write nimmt man EEPROM. Adesto DataFlash ist noch so ein 
Zwischending, da sind die zu löschenden Bereiche kleiner. Die sind aber 
außer zu sich selbst zu nix anderem kompatibel.

von olpo (Gast)


Lesenswert?

Gut danke.
Ich habe leider kein EEPROM.

Kann mir noch jemand etwas zu der Read-Funktion sagen?
1
/******************************************************************************
2
*
3
* This function performs an I/O read.
4
*
5
* @param  Address contains the address of the first sector which needs to
6
*      be erased.
7
* @param  ByteCount contains the total size to be erased.
8
* @param  Command is the command used to read data from the flash. Supports
9
*       normal, fast, dual and quad read commands.
10
* @param  Pointer to the write buffer which contains data to be transmitted
11
* @param  Pointer to the read buffer to which valid received data should be
12
*       written
13
*
14
* @return  none.
15
*
16
* @note    None.
17
*
18
******************************************************************************/
19
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command,
20
        u8 *WriteBfrPtr, u8 *ReadBfrPtr)

Warum braucht der einen Write-Buffer?
Und was will er da erasen?


Danke.

von abe (Gast)


Lesenswert?

olpo schrieb:
> Warum braucht der einen Write-Buffer?
> Und was will er da erasen?

Meine Güte.. du hast doch den Quellcode vor dir.. liest doch einfach 
nach was er macht?

von abe69 (Gast)


Lesenswert?

olpo schrieb:
> Warum braucht der einen Write-Buffer?
> Und was will er da erasen?

Meine Güte.. du hast doch den Quellcode vor dir.. liest doch einfach 
nach was er macht?

von olpo (Gast)


Lesenswert?

Also, man kann nicht sagen, daß bei einem Read auf ein Flash irgendwas 
gelöscht wird?


Hier noch die Funktion, falls da jemand etwas bekannt vorkommt, wäre es 
nett, wenn er seine Gedanken mit mir teilt.
1
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command,
2
        u8 *WriteBfrPtr, u8 *ReadBfrPtr)
3
{
4
  u32 RealAddr;
5
  u32 RealByteCnt;
6
  u32 BankSel;
7
  u32 BufferIndex;
8
  u32 TotalByteCnt;
9
  u8 ShiftSize;
10
11
  /*
12
   * Retain the actual byte count
13
   */
14
  TotalByteCnt = ByteCount;
15
16
  while(((signed long)(ByteCount)) > 0) {
17
18
    /*
19
     * Translate address based on type of connection
20
     * If stacked assert the slave select based on address
21
     */
22
    RealAddr = GetRealAddr(QspiPtr, Address);
23
24
    /*
25
     * Select bank
26
     */
27
    if(Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
28
      BankSel = RealAddr/SIXTEENMB;
29
      SendBankSelect(QspiPtr, WriteBfrPtr, BankSel);
30
    }
31
32
    /*
33
     * If data to be read spans beyond the current bank, then
34
     * calculate RealByteCnt in current bank. Else
35
     * RealByteCnt is the same as ByteCount
36
     */
37
    if((Address & BANKMASK) != ((Address+ByteCount) & BANKMASK)) {
38
      RealByteCnt = (Address & BANKMASK) + SIXTEENMB - Address;
39
    }else {
40
      RealByteCnt = ByteCount;
41
    }
42
43
44
    /*
45
     * Setup the write command with the specified address and data for the
46
     * Flash
47
     */
48
    WriteBfrPtr[COMMAND_OFFSET]   = Command;
49
    WriteBfrPtr[ADDRESS_1_OFFSET] = (u8)((RealAddr & 0xFF0000) >> 16);
50
    WriteBfrPtr[ADDRESS_2_OFFSET] = (u8)((RealAddr & 0xFF00) >> 8);
51
    WriteBfrPtr[ADDRESS_3_OFFSET] = (u8)(RealAddr & 0xFF);
52
53
    if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
54
        (Command == QUAD_READ_CMD)) {
55
      RealByteCnt += DUMMY_SIZE;
56
    }
57
    /*
58
     * Send the read command to the Flash to read the specified number
59
     * of bytes from the Flash, send the read command and address and
60
     * receive the specified number of bytes of data in the data buffer
61
     */
62
    XQspiPs_PolledTransfer(QspiPtr, WriteBfrPtr,
63
        &(ReadBfrPtr[TotalByteCnt - ByteCount]),
64
        RealByteCnt + OVERHEAD_SIZE);
65
66
    /*
67
     * To discard the first 5 dummy bytes, shift the data in read buffer
68
     */
69
    if((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
70
          (Command == QUAD_READ_CMD)){
71
      ShiftSize = OVERHEAD_SIZE + DUMMY_SIZE;
72
    }else{
73
      ShiftSize =  OVERHEAD_SIZE;
74
    }
75
76
    for(BufferIndex = (TotalByteCnt - ByteCount);
77
        BufferIndex < (TotalByteCnt - ByteCount) + RealByteCnt;
78
        BufferIndex++) {
79
      ReadBfrPtr[BufferIndex] = ReadBfrPtr[BufferIndex + ShiftSize];
80
    }
81
82
    /*
83
     * Increase address to next bank
84
     */
85
    Address = (Address & BANKMASK) + SIXTEENMB;
86
    /*
87
     * Decrease byte count by bytes already read.
88
     */
89
    if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
90
        (Command == QUAD_READ_CMD)) {
91
      ByteCount = ByteCount - (RealByteCnt - DUMMY_SIZE);
92
    }else {
93
      ByteCount = ByteCount - RealByteCnt;
94
    }
95
96
  }
97
98
}

von abe69 (Gast)


Lesenswert?

1
    /*
2
     * Setup the write command with the specified address and data for the
3
     * Flash
4
     */
5
    WriteBfrPtr[COMMAND_OFFSET]   = Command;
6
    WriteBfrPtr[ADDRESS_1_OFFSET] = (u8)((RealAddr & 0xFF0000) >> 16);
7
    WriteBfrPtr[ADDRESS_2_OFFSET] = (u8)((RealAddr & 0xFF00) >> 8);
8
    WriteBfrPtr[ADDRESS_3_OFFSET] = (u8)(RealAddr & 0xFF);
9
10
    if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
11
        (Command == QUAD_READ_CMD)) {
12
      RealByteCnt += DUMMY_SIZE;
13
    }
14
    /*
15
     * Send the read command to the Flash to read the specified number
16
     * of bytes from the Flash, send the read command and address and
17
     * receive the specified number of bytes of data in the data buffer
18
     */
19
    XQspiPs_PolledTransfer(QspiPtr, WriteBfrPtr,
20
        &(ReadBfrPtr[TotalByteCnt - ByteCount]),
21
        RealByteCnt + OVERHEAD_SIZE);

Dort ist klar beschrieben, was der WriteBfrPtr macht. Lies dazu noch das 
Datenblatt des Flashs und alles wird sofort klar.

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.