This API section outlines a very simple set of operations that permit an AVR application to read sector by sector, or to write sector by sector from/to a file.
A file open for sector I/O reading only, uses the FCB_Type file control block.
A file open for sector writes, uses the WCB_Type file control block.
The sector buffer, uses type Block_512.
type Block_Type is array(Unsigned_16 range <>) of Unsigned_8; for Block_Type'Component_Size use 8; for Block_Type'Alignment use 4; subtype Block_512 is Block_Type(0..511); type FCB_Type is private; type WCB_Type is limited private;
procedure Open_File(File : out FCB_Type; Dir_Entry : Dir_Entry_Type; OK : out Boolean); procedure Open_File(File : out FCB_Type; Dir : in out DCB_Type; Name : String; OK : out Boolean); procedure Rewind_File(File : in out FCB_Type); procedure Read_File(File : in out FCB_Type; Block : out Block_512; Count : out Unsigned_16; OK : out Boolean); procedure Reread_File(File : in out FCB_Type; Block : out Block_512; Count : out Unsigned_16; OK : out Boolean); procedure Close_File(File : in out FCB_Type);
procedure Open_File(File : out WCB_Type; Dir : in out DCB_Type; Name : String; OK : out Boolean); procedure Create_File(File : out WCB_Type; Dir : in out DCB_Type; Name : String; OK : out Boolean); procedure Write_File(File : in out WCB_Type; Block : in out Block_512; Count : Unsigned_16; OK : out Boolean); procedure Rewrite_File(File : in out WCB_Type; Block : in out Block_512; Count : Unsigned_16; OK : out Boolean); procedure Sync_File(File : in out WCB_Type; OK : out Boolean); procedure Close_File(File : in out WCB_Type; OK : out Boolean);
This section documents operations involving the FCB_Type file control block. These procedures permit sequential sector by sector reading of existing files.
The following procedures open the file found in directory entry Dir_Entry or the file named Name in directory tracked by Dir. The file control block is returned when argument OK is returned as True. The file system object must be a "file" to be successful.
procedure Open_File(File : out FCB_Type; Dir_Entry : Dir_Entry_Type; OK : out Boolean); procedure Open_File(File : out FCB_Type; Dir : in out DCB_Type; Name : String; OK : out Boolean);
To re-read a file without having to close and reopen it, use the Rewind_File procedure. The argument File must be opened for reading. This operation always succeeds at reposition to the start of the file.
procedure Rewind_File(File : in out FCB_Type);
The Read_File procedure sequentially reads and returns up to 1 sector's worth of data into receiving buffer argument Block. The actual number of bytes may be less than 512 for the last sector of the file. The byte count is returned in argument Count. OK is returned as True, if there was any data read. The sector pointer is advanced after the call succeeds.
OK is returned False if an error or end-of-file is encountered.
Procedure Reread_File re-reads the last successfully read sector by Read_File. It is an error to call Reread_File without a prior Read_File call.
procedure Read_File(File : in out FCB_Type; Block : out Block_512; Count : out Unsigned_16; OK : out Boolean); procedure Reread_File(File : in out FCB_Type; Block : out Block_512; Count : out Unsigned_16; OK : out Boolean);
The Close_File call marks the file control block as invalid, to prevent any accidental re-use of the object File.
procedure Close_File(File : in out FCB_Type);
The following operations allow an application to write data sequentially to files, sector by sector.
This procedure opens an existing file named Name in directory Dir to be overwritten. If successful, any prior file contents are immediately released and the write control block is positioned to write it's first sector. The specified Name must be an existing file. OK is returned when the open is successful.
procedure Open_File(File : out WCB_Type; Dir : in out DCB_Type; Name : String; OK : out Boolean);
The following procedure permits the AVR application to create a new file in the directory tracked by argument Dir. The new file is named according to argument Name and must obey DOS 8.3 naming standards. If the file is created successfully, OK is set to True.
Note that OK can be returned as False, if the named file already exists.
procedure Create_File(File : out WCB_Type; Dir : in out DCB_Type; Name : String; OK : out Boolean);
The following APIs allow an application to write files sequentially.
procedure Write_File(File : in out WCB_Type; Block : in out Block_512; Count : Unsigned_16; OK : out Boolean); procedure Rewrite_File(File : in out WCB_Type; Block : in out Block_512; Count : Unsigned_16; OK : out Boolean);
The Rewrite_File procedure allows the application to rewrite the block just written by Write_File. It is an error to call it, if no prior Write_File was performed.
The Sync_File procedure is designed for use by data logging applications. Normally a file's size is not updated in the directory until the file is '''closed'''. If a data logging application is interrupted by a failure and no close was performed on the file being written, the FAT directory entry will still indicate that the file is zero bytes in length. This is disastrous if several days of data was collected.
To mitigate this problem, the application may invoke the Sync_File procedure to force the directory entry update (as if the file was closed). The argument File does remain open however, allowing future writes to further add to the log file.
procedure Sync_File(File : in out WCB_Type; OK : out Boolean);
This operation performs the functions done by Sync_File, as well as to mark the file control block as invalid. This prevents any accidental use of it in the application. OK is returned as True if the close was successful.
procedure Close_File(File : in out WCB_Type; OK : out Boolean);
The following example creates a file named MYFILE.DAT in the root directory, and writes some content to it, sector by sector. When the write loop ends, the file is closed.
For AVR platforms with 1K RAM, it is important to delay declaring your sector buffer until you actually need it. Operations like Create_File, for example, will need to internally use a sector buffer. For this reason, the buffer Block is not declared until we reach the write loop and then it is immediately released.
with Interfaces; with FATFS; use Interfaces; use FATFS; procedure Create is D : DCB_Type; -- Directory Control Block F : WCB_Type; -- Write Control Block OK : Boolean; -- Success/Failure flag begin Open_Dir(D,OK); -- Open root dir pragma Assert(OK); Create_File(F,D,"MYFILE.DAT",OK); -- Create new file in root dir pragma assert(OK); declare Block : Block_512; -- Sector buffer (512 bytes) begin loop Write_File(F,Block,Block'Length,OK); -- Write one sector from Block pragma Assert(OK); exit when ...; end loop; end; Close_File(F,OK); -- Close file Close_Dir(D); -- Close DCB end Create;
This program is identical to Example 1, except that Open_File is called instead of Create_File:
with Interfaces; with FATFS; use Interfaces; use FATFS; procedure Rewrite_File is D : DCB_Type; -- Directory Control Block F : WCB_Type; -- Write Control Block OK : Boolean; -- Success/Failure flag begin Open_Dir(D,OK); -- Open root dir pragma Assert(OK); Open_File(F,D,"MYFILE.DAT",OK); -- Open existing file in root dir pragma assert(OK); declare Block : Block_512; -- Sector buffer (512 bytes) begin loop Write_File(F,Block,Block'Length,OK); -- Write one sector from Block pragma Assert(OK); exit when ...; end loop; end; Close_File(F,OK); -- Close file Close_Dir(D); -- Close DCB end Rewrite_File;
Example 3 opens the file created/written by examples 1 or 2. The file is read one sector (max) at a time. The read loop exits when OK is returned as False. False indicates that an end-file condition or an I/O error occurred.
As in the prior examples, for 1K RAM AVR platforms, delay the declaration of your sector buffer until you actually need it and then release it immediately when no longer required.
with Interfaces; with FATFS; use Interfaces; use FATFS; procedure Example_3 is D : DCB_Type; -- Directory control block F : FCB_Type; -- File control block Count : Unsigned_16; -- Byte count OK : Boolean; -- Success/Failure flag begin Open_Dir(D,OK); -- Open root directory pragma Assert(OK); Open_File(F,D,"MYFILE.DAT",OK); -- Open MYFILE.DAT in root directory pragma assert(OK); Close_Dir(D); -- DCB no longer required declare Block : Block_512; -- 512 byte sector buffer begin loop Read_File(F,Block,Count,OK); -- Read 1 sector's worth exit when not OK; -- exit when EOF/Error -- Do something with Block(0..Count-1) end loop; end loop; Close_File(F); -- Close file end Example_3;