ATMEL: Accelerate multi write file

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# Accelerate multi write file
[Examples]

Overview
  The routines file_getc() and file_putc() are too slow to transfer many data.
  The file_read_buf() and file_write_buf() are developed to transfer many data between the RAM and file on a memory.
  This routines optimize the transfer and if a DMA exists between RAM and memory then it is used.
  The file_read() and file_write() are developed to transfer many data between a file and another memory or a specific interface.
  This routines don't transfer data, but provide an information on the disk segment corresponding to the file.
  Overside, it is not necessary to transfer data in the RAM and the chip can use a DMA between two disks to save time.
  In case of many "file_write_buf() or file_putc()" call (e.g. log file), the execution may be slow because the number of write access on the disk is important. So, the following section gives a solution to accelerate the execution and reduces the number of write access.
  Also, it is important to know that FAT time creation depends of FAT type used. The allocation in FAT is more fast on FAT (FAT12,FAT16) than FAT32. If you have a disk size < 2GB then you can force the type FAT when you call nav_drive_format(FS_FORMAT_FAT).
  Also, you can call nav_checkdisk_disable() before many file IN/OUT routines access.
  Because the "test unit ready" routine can reduce the speed of IN/OUT routines.

Examples

If you write many data in a file and you split the write access (e.g. log file), then it may be interresting to prealloc once the space in file (FAT table).

This example is the usual sequence to fill a file :

    // File fill >1MB
    #define  FILL_FILE_NB_WRITE   855L
    #define  FILL_FILE_BUF_SIZE   120L

    Bool fill_file( void )
    {
       const UNICODE _MEM_TYPE_SLOW_ name[50]={'l','o','g','.','b','i','n',0};
       U16 u16_nb_write;

       memset( g_trans_buffer , 0x55 , FILL_FILE_BUF_SIZE );

       if( !nav_drive_set(LUN_DISK))    // Enter in disk
          return FALSE;
       if( !nav_partition_mount())      // Mount partition of disk
          return FALSE;

       if( !nav_file_create( (const FS_STRING) name )) // Create file
          return FALSE;
       if( !file_open(FOPEN_MODE_W))    // Open file in write mode with force file size 0
          return FALSE;

       for( u16_nb_write=0; u16_nb_write<FILL_FILE_NB_WRITE; u16_nb_write++ )
       {
          // HERE, at each write file, a allocation in FAT area is run
          // so, if you have many buffer to write the execution may be slow.
          if( !file_write_buf( g_trans_buffer , FILL_FILE_BUF_SIZE ))
          {
             file_close();
             return FALSE;
          }
       }
       file_close();
       return TRUE;
    }

This example allow to accelerate write access with a prealloc routine :

    // File fill >1MB
    #define  FILL_FILE_NB_WRITE   855L
    #define  FILL_FILE_BUF_SIZE   120L

    Bool fill_file_fast( void )
    {
       const UNICODE _MEM_TYPE_SLOW_ name[50]={'l','o','g','_','f','a','s','t','.','b','i','n',0};
       _MEM_TYPE_SLOW_ Fs_file_segment g_recorder_seg;
       U16 u16_nb_write;

       memset( g_trans_buffer , 0x55 , FILL_FILE_BUF_SIZE );

       if( !nav_drive_set(LUN_DISK))    // Enter in disk
          return FALSE;
       if( !nav_partition_mount())      // Mount partition of disk
          return FALSE;

       if( !nav_file_create( (const FS_STRING) name )) // Create file
          return FALSE;
       if( !file_open(FOPEN_MODE_W))    // Open file in write mode and forces the file size to 0
          return FALSE;

       // Define the size of segment to prealloc (unit 512B)
       // Note: you can alloc more in case of you don't know total size
       g_recorder_seg.u16_size = (FILL_FILE_NB_WRITE*FILL_FILE_BUF_SIZE + 512L)/512L;

       // ****PREALLLOC****** the segment to fill
       if( !file_write( &g_recorder_seg ))
       {
          file_close();
          return FALSE;
       }

       // Check the size of segment allocated
       if( g_recorder_seg.u16_size < ((FILL_FILE_NB_WRITE*FILL_FILE_BUF_SIZE + 512L)/512L) )
       {
          file_close();
          return FALSE;
       }

       // Close/open file to reset size
       file_close();                    // Closes file. This routine don't remove the previous allocation.
       if( !file_open(FOPEN_MODE_W))    // Opens file in write mode and forces the file size to 0
          return FALSE;

       for( u16_nb_write=0; u16_nb_write<FILL_FILE_NB_WRITE; u16_nb_write++ )
       {
          // HERE, the file cluster list is already allocated and the write routine is more fast.
          if( !file_write_buf( g_trans_buffer , FILL_FILE_BUF_SIZE ))
          {
             file_close();
             return FALSE;
          }
       }
       file_close();
       return TRUE;
    }

Statistic

A FAT32 has need to write more (x4) sectors in FAT table than FAT16 for the same file size and same disk size.

Create a file of 100.2KB (buffer 120B * nb write 855) on a disk 256MB (FAT16-cluster 4KB):

- with fill_file() , the write access on a same sector in FAT is 50 maximum and 25 average.
- with fill_filefast(), the write access on a same sector in FAT is 2 maximum and 1 average.

Create a file of 1.1MB (buffer 120B * nb write 10000) on a disk 256MB (FAT16-cluster 4KB):

- with fill_file() , the write access on a same sector in FAT is 255 maximum and 147 average.
- with fill_filefast(), the write access on a same sector in FAT is 2 maximum and 1 average.