Forum: PC Hard- und Software FATFS f_lseek für den schnellen Zugriff beim lesen


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 rsc (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Hallo Community,

ich habe zu einem 4Gbit NAND Flash auf dem PIC32 die FATFS von elm chan 
implementiert. Ich kann Dateien lesen, schreiben und löschen. Allerdings 
dauert das Ganze beim Lesen von 37kByte ca. 945ms. Um das zu 
beschleunigen, wollte ich die f_lseek Funktion nutzen, um das Laden der 
FAT Struktur zu umgehen und so ca. 700ms einzusparen.

Im ersten Schritt Schreibe ich die Daten vom USB Stick in den NAND 
Flash. Da tritt das Problem auf. Ohne die f_lseek Funktion funktioniert 
alles problemlos. Mit f_lseek Funktion sobald die Datei Größer als 
0x8000 ist, werden die restlichen Bytes verworfen. Hierzu der Code:

DWORD clmt[SZ_TBL] = { 0 }; // Cluster link map table buffer
uint32_t gu32_Offset = 0UL;

// read source file and write it to the destination path
static
uint32_t u32_UsbExchangePage_CopyFile(  const uint8_t _cu8_DiskDrive, 
//!< [in]   |peripheral hard disk drive nr
                                        char* _pu8a_SrcPath, 
//!< [in]   |source path to copy
                                        char* _pu8a_DstPath, 
//!< [in]   |destination path
                                        uint32_t *const 
_pu32_TxCountBytes      //!< [out]  |count of bytes written
                                        )
{
    uint32_t u32_ErrorCode = (uint32_t)e_NO_ERROR;
    ts_FATFS fs;           // Filesystem object
    ts_FIL fil;            // File object
    char u8a_SrcBuf[4096]; // read buf
    size_t nbytes;          // max. read bytes to local buf
    uint32_t u32_BytesToRead; // bytes to read from USB MSD
    uint32_t u32_BytesWritten = 0; // written bytes
    int32_t s32_ReadBytes; // read bytes from USB MSD or error if -1 
(SYS_FS_RES_FAILURE)
    SYS_FS_HANDLE handle; // file handle
    SYS_FS_RESULT e_Result; // microchip FATFS error code
    UINT bw;            // Bytes written
    long fileSize; // file size in bytes
    char u8a_Drive[3]; // directory on a drive
    //DWORD clmt[SZ_TBL] = { 0 }; // Cluster link map table buffer
    uint32_t u32_Offset2 = 0UL; // = gu32_Offset;

    sprintf(u8a_Drive, "%1d:", _cu8_DiskDrive);

    handle = SYS_FS_FileOpen(_pu8a_SrcPath, (SYS_FS_FILE_OPEN_READ));
    if ( handle != SYS_FS_HANDLE_INVALID )
    {
        fileSize = SYS_FS_FileSize(handle); // anzahl zeichen im file
        if ( fileSize != SYS_FS_RES_FAILURE )
        {
            if ( fileSize > U32_FATFS_FILE_MAX_SIZE ) u32_ErrorCode = 
(uint32_t)e_ERROR_FATFS_FILE_SIZE;
            else
            {
                e_Result = ffs_f_mount(&fs, u8a_Drive, 0); // Gives a 
work area to the drive
                if ( e_Result != e_NO_ERROR ) u32_ErrorCode = 
((uint32_t)e_ERROR_FATFS_FR_OK) | e_Result;
                else
                {
                    e_Result = ffs_f_open(&fil, _pu8a_DstPath, 
d_FA_OPEN_APPEND | d_FA_WRITE); // Create a file as new
                    if ( e_Result != e_NO_ERROR ) u32_ErrorCode = 
((uint32_t)e_ERROR_FATFS_FR_OK) | e_Result;
                    else
                    {
                        nbytes = sizeof(u8a_SrcBuf); // max. byte anzahl 
im localen puffer, letztes byte ist '\0'
                        u32_BytesToRead = (uint32_t)fileSize; // anzahl 
der insgesamt zu lesender bytes

                        // create table for fast seek mode
                        //e_Result = ffs_f_lseek(&fil, gu32_Offset); // 
offs1 read/write operation
                        e_Result = ffs_f_lseek(&fil, 0); // offs1 
read/write operation
                        if ( e_Result != e_NO_ERROR ) u32_ErrorCode = 
(uint32_t)e_ERROR_FATFS_FR_OK | e_Result;
                        else
                        {
                            fil.cltbl = clmt; // Enable fast seek mode 
(cltbl != NULL)
                            clmt[0] = SZ_TBL; // Set table size
                            u32_Offset2 = u32_BytesToRead; // offset for 
next write

                            e_Result = ffs_f_lseek(&fil, 
d_CREATE_LINKMAP); // Create CLMT
                            if ( e_Result != e_NO_ERROR ) u32_ErrorCode 
= (uint32_t)e_ERROR_FATFS_FR_OK | e_Result;
                        }

                        do
                        {
                            if ( u32_BytesToRead > nbytes ) 
u32_BytesToRead -= nbytes; // anzahl weiter zu lesender bytes 
decrementieren
                            else nbytes = (size_t)u32_BytesToRead; // 
anzahl der restlichen zu übetragenden bytes wenn nbytes < als 
sizeof(Src_Buf)
                            s32_ReadBytes = SYS_FS_FileRead(handle, 
u8a_SrcBuf, nbytes);
                            if ( (e_Result != SYS_FS_RES_SUCCESS) || 
(s32_ReadBytes == -1) ) u32_ErrorCode = 
(uint32_t)e_ERROR_USB_FILE_READ_FILE_FAILED;
                            else
                            {
                                e_Result = ffs_f_write(&fil, u8a_SrcBuf, 
nbytes, &bw); // Write a message
                                if ( e_Result != e_NO_ERROR ) 
u32_ErrorCode = ((uint32_t)e_ERROR_FATFS_FR_OK) | e_Result;
                                else u32_BytesWritten += (uint32_t)bw;
                            }

                            Nop();
                        } while ( (nbytes == sizeof(u8a_SrcBuf)) && 
(u32_ErrorCode == (uint32_t)e_NO_ERROR) );

                        if ( e_Result == e_NO_ERROR ) e_Result = 
ffs_f_lseek(&fil, u32_Offset2);

                        *_pu32_TxCountBytes = u32_BytesWritten;

                        if ( u32_ErrorCode != (uint32_t)e_NO_ERROR ) 
(void)ffs_f_close(&fil); // Close the file
                        else e_Result = ffs_f_close(&fil);
                    }

                    if ( u32_ErrorCode != (uint32_t)e_NO_ERROR ) 
(void)ffs_f_mount(0, u8a_Drive, 0); // Unregister work area
                    else e_Result = ffs_f_mount(0, u8a_Drive, 0); // 
Unregister work area
                }
            }

            if ( u32_ErrorCode != e_NO_ERROR ) 
(void)SYS_FS_FileClose(handle);
            else e_Result = SYS_FS_FileClose(handle);
        }

        else u32_ErrorCode = (uint32_t)e_ERROR_USB_FILE_SIZE;
    }

    else u32_ErrorCode = (uint32_t)e_ERROR_USB_FILE_OPEN_FAILED; // File 
open failed.

    return u32_ErrorCode;
}

Hat jemand ähnliche Erfahrungen gemacht? Was mache ich hier falsch?

Mit freundlichen Grüßen
rsc

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.