FULL-C: SD card functions

FULL-C

SD Karta

Všechny SDS Druhé Produktové Řady, umožňují přístup k souborům na připojené SD Kartě. Typicky je použita SD karta formátu MicroSD, vložená do držáku umístěném v modulu SDS.

Každý produkt SDS má držák umístěn na patřičném místě, pro detaily se podívejte na návod k vašemu SDS.

Po vložení je SD karta automaticky detekována (vložení do držáku), připravena k použití (mount) a je z ní načten FAT/FAT32/exFAT souborový systém, a finálně je spočteno volné místo na kartě (to může několik sekund trvat, ale výsledkem je přesný údaj, který potřebujeme aby byl přesný). Podpora pro LFN je zabudována (pozor - jen do maximální délky celého textu 254 znaků).

Omezení na celkovou velikost SD karty zde prakticky není. Informace o SD kartě naleznete (pokud se ji povedlo připojit) na webovém rozhraní (stránka "FULL-C status").

SD kartu sice lze kdykoliv z držáku vyjmout, ale pokud se tak stane za provozu kdy se zrovna s obsahem karty pracuje, velmi pravděpodobně dojde k poškození obsahu karty.

Při výpadku napájení (pokles pod bezpečnou mez) provede SDS automatické odpojení karty a zamezí případným dalším zápisům na tuto kartu (dokud se napětí nevrátí nad vhodnou úroveň), tím SDS brání poškození obsahu karty.

FULL-C přistupuje k SD kartě prostřednictvím funkcí a některých get-indexů.

SD karta má v rámci výrobku SDS více možných a sdílených využití. Nejzajímavější je možnost kombinace FULL-C programu a webového serveru SDS, kdy SDS zobrazuje webové stránky ze SD karty, přičemž FULL-C program má možnost tyto soubory změnit dle potřeby (např. postupné doplňování změřených hodnot).


Vybrané indexy

Zde je výběr jednotlivých indexů, které souvisejí s použitím SD karty. Úplný seznam všech indexů je na jiné stránce: FULL-C set and get.


-----------+---------+------+----------------------------------------------
  index    | i\u\f\a | směr |  popis 
-----------+---------+------+----------------------------------------------
 3800      | u32     |  GET |  PVD Active - main power failure detected
 3800      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3801      | u32     |  GET |  PVD Was Active - this flag is only cleared by reading this index 3801
 3801      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3850      | u32     |  GET |  SD Card - fully mounted and useable
 3850      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3851      | i32     |  GET |  latest file i/o error code
 3851      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3852      | u32     |  GET |  SD Card - Block Size in bytes (typically 512)
 3852      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3853      | u32     |  GET |  SD Card - CardType
 3853      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3854      | u32     |  GET |  SD Card - CID - ProductSN
 3854      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3855      | u32     |  GET |  statistic counter: SDC all init attempts (= successful + failed)
 3855      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3856      | u32     |  GET |  statistic counter: SDC failed init attempts
 3856      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3857      | u32     |  GET |  SD Card - Total Sector Count in KiB (size of the card)
 3857      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3858      | u32     |  GET |  statistic counter: SDC sector reads
 3858      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3859      | u32     |  GET |  statistic counter: SDC sector writes
 3859      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3860      | u32     |  GET |  statistic counter: SDC sector r/w failures
 3860      |         |  SET |  n/a (read-only)
-----------+---------+------+--
 3861      | u32     |  GET |  actual number of opened files (at this moment)
 3861      |         |  SET |  n/a (read-only)
-----------+---------+------+--


PVD

Modul SDS hlídá své napájení a při jeho poklesu (např. výpadek zdroje který napájí modul SDS) vyhlásí chvíli před úplným vypnutím signál PVD-Active. Na základě tohoto signálu SDS například uzavře práci s SD kartou atd. - a FC program má možnost o tom být také informován, právě prostřednictvím daných položek.


Stav SD Karty

SD kartu lze používat jen pokud je plně připojena (mounted) - což se FC program může dovědět z indexu 3850. Volání funkcí pro práci se soubory selže chybou NO_SD_CARD pokud není karta připravena k použití - proto je vhodné napsat FC program tak, aby se soubory na kartě začal pracovat až bude index 3850 hlásit že je karta připravena.

Každá SD karta interně pracuje s bloky o velikost sektoru, a takový sektor může mít různou velikost. Typicky je to 512 bajtů. Aktuální velikost sektoru lze zjistit z indexu 3852. V současné době SDS podporuje jenom a pouze SD karty, které mají své sektory právě o pevné velikosti 512 bajtů, jiné typy karet nejsou podporovány.

Typ SD karty je uveden v indexu 3853. Jednotlivé možné hodnoty jsou:

hodnota | význam
--------+----------------------------
      0 | SD CARD V1.1
      1 | SD CARD V2.0
      2 | High Capacity SD CARD
      3 | Multimedia Card
      4 | Secure Digital IO Card
      5 | High Speed Multimedia Card
      6 | Secure Digital IO Combo Card
      7 | High Capacity MMC Card

Pokud náhodou nebude vaše SD karta v modulu SDS pracovat, zkontrolujte, je-li její typ správný (údaj je uveden i na webové administraci)


Informace o SD kartě

Celková velikost - kapacita - SD karty je k dispozici v indexu 3857. Jedná se o údaj celkové kapacity (výrobní velikost karty, na které není cokoliv nahráno)- pozor, aktuální volné místo je už jiný údaj.

Hodnota kapacity je v jednotkách KiB - pozor na to!

Po dobu provozu SDS (od resetu/zapnutí) je počítáno, kolikrát se SDS modul pokusil o připojení SD karty (mount). Všechny pokusy (ať úspěšné, nebo neúspěšné), jsou sečteny v indexu 3855.

Neúspěšné pokusy jsou sčítány do indexu 3856. Ideálně by zde vždy měla být hodnota nula - pokud ne, musíte zjistit proč a problém odstranit.


Statistiky

Každý zápis na SD kartu pomalu snižuje její životnost (je to dáno typem paměťi v SD kartě, opotřebovává se). Proto poskytuje SDS statistická počítadla, aby byl k dispozici přehled o využití SD karty.

Při výměně SD karty za jinou (tedy s jiným identifikačním sériovým číslem) jsou tato počítadla vynulována. Pokud je stejná karta stále použita, počítadla zůstávají (nulují se pak už jen resetem zařízení SDS).

Vznikne-li chyba při čtení či zápisu do sektoru, je zvýšena hodnota v indexu 3860.


Aktuální práce se soubory

Index 3851 svou hodnotou ukazuje poslední chybu (nebo 0 byl-li to úspěch a ne chyba) po volání poslední funkce pro přístup k souborům či SD kartě. Většina funkcí svou chybu (či úspěch) vrací ihned v rámci návratové hodnoty funkce; nicméně tento údaj je vždy uchován a je k dispozici právě v tomto indexu pro případné pozdější zpracování. Každé nové volání funkce pro práci se soubory či SD kartou tuto hodnotu přepisuje.

Protože SDS má limit na celkové množství právě otevřených souborů, dává k dispozici aktuální informaci o tom, kolik souborů je v okamžiku dotazu na hodnotu indexu 3861 k dispozici. Protože soubory otevírá nejenom váš FC program, ale i jiné části SDS (např. když si je zobrazujete přes webového rozhraní SDS), může se stát, že se celkové množství vyčerpá. Proto je vždy vhodné v FC programu kontrolovat tento údaj, a pokoušet se otevřít soubor až když je tam volná možnost.


Funkce pro práci se soubory

FULL-C dává k dispozici následující funkce, pro přístup k souborům a složkám (adresářům) na připojené SD kartě.

         int file_open(unsigned int * p_file_handle, char * file_path, char * open_mode);
         int file_close(unsigned int * p_file_handle);

         int file_read(unsigned int file_handle, void * buffer, unsigned int bytes_to_read, unsigned int * bytes_read);
         int file_write(unsigned int file_handle, void * buffer, unsigned int bytes_to_write, unsigned int * bytes_written);
         int file_sync(unsigned int file_handle);

         int file_lseek(unsigned int file_handle, uint64_t new_position);
    uint64_t file_tell(unsigned int file_handle);
         int file_eof(unsigned int file_handle);

         int file_truncate(unsigned int file_handle);
         int file_expand(unsigned int file_handle, uint64_t new_size, unsigned int op_mode);
    uint64_t file_size(unsigned int file_handle);
         int file_error(unsigned int file_handle);

         int file_stat(char * file_path, void * existing_file_stat_structure);
 
         int file_unlink(char * file_path);

         int file_rename(char * file_path_from, char * file_path_to);

         int file_mkdir(char * file_path);

        void SDS_disable_sdc(unsigned int key);


Poznámka: pro použití těchto funkcí potřebujete firmware s verzí FULL-C číslo 0x0A nebo novější.

Pouze funkce file_open() a file_close() požadují jako první parametr ukazatel na proměnnou, která drží číselný identifikátor souboru (file handle). Všechny ostatní funkce už pak pracují přímo s hodnotou této proměnné (nikoliv s ukazatelem na ni). Dejte si na to pozor !


Popis funkcí pro práci s SD kartou

Všechny funkce v případě chyby či neúspěchu, buď přímo vracejí chybovou hodnotu, a vždy nastavují tuto hodnotu do indexu 3851 (viz výše). FULL-C program musí být napsán tak, aby je vždy kontroloval, a správně se podle nich zařídil.


------------+----------------+---------------------------------------------------------------------------------------------------------------------------
  hodnota   | zkratka        | význam  
  decimal   | (pro informaci)|              
------------+----------------+---------------------------------------------------------------------------------------------------------------------------
   1..max   | OK + hodnota   | funkce se provedla v pořádku = OK , návratová hodnota navíc obsahuje požadovaný údaj (např. velikost atd. - dle funkce).
     0      | OK             | funkce se provedla v pořádku = OK
    -1      | DISK_ERROR     | nelze pracovat s SD kartou (chyba komunikace, karta chybí, výpadek napájení, atd.)
    -2      | INTERNAL_ERROR | vnitřní chyba; funkce se neprovedla
    -3      | NOT_READY      | SD karta není připravena, funkce se neprovedla
    -4      | NO_FILE        | soubor nelze nalézt
    -5      | NO_PATH        | cestu nelze nalézt
    -6      | INVALID_NAME   | název je neplatný (použity např. nesprávné znaky, nebo nesprávný formát sestavy)
    -7      | DENIED         | přístup odepřen (např. složka je už plná)
    -8      | EXISTS         | přístup odepřen (např. soubor už existuje)
    -9      | INVALID_OBJ    | neplatný handle (např. nesprávné použití file_open, nebo byla vyjmuta karta, atd.)
   -10      | WRITE_PROT     | SD karta je chráněna proti zápisu
   -11      | INVALID_DRIVE  | použit neplatný název disku
   -12      | NOT_ENABLED    | SD karta není naformátována (nelze ji použít)
   -13      | NO_FILESYSTEM  | na SD kartě nebyl nalezen podporovaný souborový systém
   -14      | N/A            | nepodporováno
   -15      | TIMEOUT        | přístup k SD kartě zablokován jiným procesem (zkuste to později znovu...)
   -16      | LOCKED         | zablokován pokus o přístup k souboru, který je už používán (je otevřen)
   -17      | NO_MEMORY      | nedostatek paměti k provedení operace
   -18      | TOO_MANY_FILES | soubor nelze otevřít, protože už jste dosáhli maximálního počtu současně otevřených souborů
   -19      | INVALID_PARAM  | obecná chyba - byl zadán neplatný parametr
   -99      | NO_SD_CARD     | SD karta není připravena k použití (např. není fyzicky vložena do držáku)
------------+----------------+---------------------------------------------------------------------------------------------------------------------------

Pokud tedy kterákoliv funkce vrátí hodnotu menší než nula (tedy nikoliv OK), tak se daná funkce neprovedla - selhala. Váš FULL-C program se podle toho musí správně zařídit.

Pokud dojde k vyndání karty za běhu zařízení, je zřejmé že tyto funkce také selžou. FULL-C program si to musí hlídat a umět se z toho zotavit (zejména, pokud je karta vrácena zpět).

Pro kontrolu jestli je v SDS zasunuta ta stále stejná karta, je vhodné si hlídat položku "ProductSN" (což je sériové výrobní číslo dané karty, a je "unikátní" pro každou SD kartu). Při výměně karty za jinou se tato hodnota patřičně změní (a pokud se vloží zpět ta samá SD karta, bude tato hodnota stejná).

Při nezasunuté SD kartě (popř. není-li karta použitelná), tak funkce vracejí chybu NO_SD_CARD.


Úplné vypnutí (zakázání) SD karty

Pokud chcete SD kartu zcela vypnout (či odpojit či zablokovat), tak použijte funkci SDS_disable_sdc().

Parametr key ve funkci SDS_disable_sdc() má následující význam:

  • 0xD15AB7E - zcela zablokuje SD kartu, takže ji SDS vůbec nepoužije (ani pro FC, ani pro web atd.) = bez ohledu je-li SD karta fyzicky vložena do držáku
  • 0x5DCA2D - povelení práce s SD kartou

Po zapnutí SDS je vždy práce s SD kartou povolena (zapnuta), není potřeba volat tuto funkci pro povolení SD karty. Typicky se tato funkce volá právě za účelem SD kartu zakázat.


Práce se soubory

Pro přístup k souboru na SD kartě je potřeba soubor otevřít, a tím získat unikátní hodnotu file_handle (identifikátor otevřeného souboru). Tuto hodnotu si držíte v proměnné ve vašem programu, a je platná po celou dobu otevření souboru, až do okamžiku kdy je soubor uzavřen (nebo dojde k vyjmutí SD karty).

Prakticky tedy zavoláte funkci file_open(), ta (pokud se nestane chyba) nastaví hodnotu do vaší proměnné (předáváte ukazatel, viz příklady). Dále pracujete se souborem dle potřeby (čtení, posuny, zápis, atd.) a nakonec vždy soubor uzavřete - funkce file_close(). Každé funkci pro takovou práci se souborem předáváte vždy proměnnou s identifikátorem otevřeného souboru.

Lze mít současně více otevřených souborů, to není problém; každý takový soubor pak má unikátní identifikátor.


Určování cest na SD kartě

Všechny názvy souboru a složek se vždy zadávají úplné - tedy neexistuje možnost pracovat s relativními cestami.

Soubory a složky v rootu (kořenová složka) SD karty se mohou zadávat jen svým čistým názvem, např. "soubor.txt", "directory123" atd.

Podsložky a soubory v podsložkách se pak zadávají pomocí celé cesty, s oddělovacími lomítky dle běžných zvyklostí.

Příklad: "/slozka/dalsi/img.jpg" - doporučuji si to předem vyzkoušet a přijít si na to, ať nejste pak zbytečně překvapeni.


file_open

Získání přístupu k vybranému souboru pro váš program.

<c>

int file_open(unsigned int * p_file_handle, char * file_path, char * open_mode);

</c>

Základní funkce pro získání přístupu k souboru. Pokud se její provedení nepovede, nelze s vybraným souborem pracovat (buď neexistuje, nebo není možné se dostat na SD kartu, nebo je vyčerpán počet současně otevřených souborů).

Funkce má dva vstupní parametry, a to "file_path" a "open_mode". Pokud se přístup k souboru získá, provede funkce nastavení hodnoty v proměnné na kterou ukazuje "*p_file_handle").

Návratová hodnota funkce vrací 0 (OK) pokud se vše povedlo a je možné se souborem pracovat; nebo vrací chybu (záporné číslo), viz tabulka výše.

Je povinností vašeho programu každý otevřený soubor uzavřít - funkce file_close().

Pozor! - pokud je soubor otevřen ve FULL-C programu, je exklusivně vyhrazen pro váš program - není tedy např. po celou dobu otevření (dokud není uzavřen pomocí file_close() funkce) dostupný pro webový server !

Význam "open_mode": jedná se o textový řetězec, který zadáváte vy jako autor programu.

  • "r" - otevřít soubor pouze a jenom pro čtení (soubor musí existovat, jinak se neotevře)
  • "r+" - otevřít soubor jak pro čtení, tak pro zápis (soubor musí existovat, jinak se neotevře)
  • "w" , "w+" - otevřít soubor pouze a jenom pro zápis (soubor je vytvořen pokud neexistuje)
  • "w+x" - otevřít soubor jak pro čtení, tak pro zápis (soubor je vytvořen pokud neexistuje)
  • "a" - otevřít existující soubor pro doplnění jeho obsahu (jen zápis) - tzn. append
  • "a+" - otevřít existující soubor pro doplnění jeho obsahu (umožněn je zápis i čtení) - tzn. append

Parametry funkce:

  • * p_file_handle - ukazatel na proměnnou, do které uloží funkce nový identifikátor souboru
  • file_path - text cesty k souboru, vždy od rootu (kořenové složky) na SD kartě
  • open_mode - způsob otevření souboru (přístupová práva)


file_close

Ukončení přístupu programu k otevřenému souboru.

<c>

int file_close(unsigned int * p_file_handle);

</c>

Tato funkce ukončí práci se souborem (který byl otevřen pomocí file_open() funkce). Dokud je soubor otevřen, je exklusivně vyhrazen pro váš program, a jiné části SDS se k němu nemohou dostat (např. po tuto dobu nepůjde daný soubor zobrazit přes web, je-li to soubor který by jinak přes web zobrazit šel).

Je-li uživatelem vyndána SD karta (za běhu) ze zařízení SDS, provede SDS automatické uzavření všech otevřených souborů (jakýkoliv další přístup k souboru tedy selže, což je v pořádku). Sledujte proto vždy návratové hodnoty od všech funkcí pro práci se soubory.

Parametry funkce:

  • * p_file_handle - ukazatel na proměnnou, ve které je uložen identifikátor souboru


Příklad pro: file_open() a file_close()

<c> .

int err;
unsigned int file1, file2;

err = file_open(&file1, "soubor1.txt", "r");
if (0 != err) { ... zpracuj_chybu ... };

err = file_open(&file2, "folder\soubor1.txt", "w+");
if (0 != err) { ... zpracuj_chybu ... };

// ...

err = file_close(&file2);
if (0 != err) { ... zpracuj_chybu ... };

err = file_close(&file1);
if (0 != err) { ... zpracuj_chybu ... };

</c>


file_read

Ze souboru, který se povedlo úspěšně otevřít funkcí file_open(), lze číst data.

<c>

int file_read(unsigned int file_handle, void * buffer, unsigned int bytes_to_read, unsigned int * bytes_read);

</c>

Data se čtou z aktuální pozice ukazatele polohy v souboru. Tento ukazatel polohy začíná při otevření souboru vždy na nule (na úplném začátku souboru), a automaticky se posune dále o tolik bajtů, kolik tato funkce file_read() ze souboru přečetla. Ukazatel polohy lze ručně změnit (kamkoliv jinam v souboru) pomocí funkce file_lseek(), a zjistit jeho aktální hodnotu pomocí funkce file_tell().

Funkce čte pouze tolik bajtů dat, kolik je možné z dané pozice souboru přečíst (toto je omezenou skutečnou velikostí souboru), a současně jen tolik dat, kolik je možné zapsat do předávacího bufferu (toto omezení určujete vy při volání této funkce).

Počet skutečně fyzicky přečtených bajtů je zapsán do určené proměnné (funkci na ni předáte ukazatel, viz příklady). Vždy zkontrolujte tuto hodnotu, a zařidtě se v programu podle ní.

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)
  • * buffer - paměťové místo (pole, buffer, proměnná), kam budou zapsány data přečtené ze souboru (musí tam být k dispozici dostatek prostoru, pozor)
  • bytes_to_read - množství bajtů, které si přejeme ze souboru přečíst do bufferu
  • * bytes_read - ukazatel na proměnnou, do které funkce zapíše skutečný počet přečtených bajtů (tedy 0 až hodnota bytes_to_read).


file_write

Do souboru, který se povedlo úspěšně otevřít funkcí file_open(), lze zapisovat data.

<c>

int file_write(unsigned int file_handle, void * buffer, unsigned int bytes_to_write, unsigned int * bytes_written);

</c>

Data se zapisují na aktuální pozici ukazatele polohy v souboru. Tento ukazatel polohy začíná při otevření souboru vždy na nule (na úplném začátku souboru), a automaticky se posune dále o tolik bajtů, kolik tato funkce file_write() do souboru skutečné zapsala. Ukazatel polohy lze ručně změnit (kamkoliv jinam v souboru) pomocí funkce file_lseek(), a zjistit jeho aktální hodnotu pomocí funkce file_tell().

Počet skutečně fyzicky zapsaných bajtů je zapsán do určené proměnné (funkci na ni předáte ukazatel, viz příklady). Vždy zkontrolujte tuto hodnotu, a zařidtě se v programu podle ní.

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)
  • * buffer - paměťové místo (pole, buffer, proměnná), kde jsou připravena data pro zápis do souboru (buffer musí mít odpovídající velikost, pozor)
  • bytes_to_write - množství bajtů, které si přejeme do souboru (z bufferu) zapsat
  • * bytes_written - ukazatel na proměnnou, do které funkce zapíše skutečný počet zapsaných bajtů (tedy 0 až hodnota bytes_to_write).


file_sync

Provedení všech případných odložených zápisů na SD kartu. Tato funkce je určena pro pokročilé uživatele, a při běžném použití ji nikdy nepotřebujete.

<c>

int file_sync(unsigned int file_handle);

</c>

SDS v určitých případech optimalizuje zápisy na SD kartu, s cílem sloučit více malých zápisů do jednoho velkého, a tím zabránit rychlému snižování životnosti SD karty (a současně zrychlit celý systém). Každý zápis na SD kartu totiž znamená, že SD karta interně smaže cílový sektor a celý jej znovu zapíše, i když změníte jen jeden bajt. S každým smazáním a zápisem se zkracuje životnost paměťového média. Proto je SDS vybaveno optimalizačním algoritmem (sektorová cache), který se takovému plýtvání snaží zabránit.

Samozřejmě při uzavření souboru je garantováno, ze všechny případné odložené zápisy jsou vždy provedeny, a v souboru je uloženo vždy vše. Stejně tak to platí i pro soubory, ze kterých je umožněno číst i do nich zapisovat. Při každém požadavku na čtení je vždy garantováno, že budou přečtena všechna případně (zápisem) změněná data.

Aby měl tvůrce programu úplnou kontrolu, je k dispozici tato funkce file_sync(), kdy si může vynutit synchronizaci všech změn (provedení případných odložených zápisů) na SD kartu.

<c> .

int err;
unsigned int soubor1;

// soubor musí být otevřen: ... file_open(&soubor1, . . . ) ...

err = file_sync(soubor1);

</c>

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)


file_lseek

Nastavení nové pozice ukazatele pracovní polohy v rámci otevřeného souboru.

<c>

int file_lseek(unsigned int file_handle, uint64_t new_position);

</c>

Funkce pro čtení a zápis pracují v souboru vždy od pozice ukazatele polohy. Často je potřeba ji změnit, a k tomu slouží tato funkce.

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)
  • new_position - nová pozice (pořadové číslo bajtů) v rámci souboru, kde 0 = začátek souboru (úplně první bajt v souboru), 1 = druhý bajt v souboru, atd. až do konce souboru


file_tell

Funkce vrací hodnotu aktuální pozice ukazatele pracovní polohy v rámci otevřeného souboru.

<c>

uint64_t file_tell(unsigned int file_handle);

</c>

Návratová hodnota je v rozmezí 0 až "velikost souboru - 1".

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)


file_eof

Funkce vrací informaci, zda-li je aktuální pozice ukazatele pracovní polohy v rámci otevřeného souboru, na jeho samotném konci.

<c>

int file_eof(unsigned int file_handle);

</c>

V případě, že je EOF podmínka splněna, nelze ze soubor už přečíst jakákoliv další data. Tato funkce je tedy s oblibou využívána při čtení dat ze souboru, kdy se tato funkce používá pro určení dosažení konce souboru.

Návratová hodnota určuje, je-li dosaženo konce souboru (EOF = End Of File) nebo ne.

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)


file_truncate

Funkce pro pokročilé uživatele. Uřízne soubor na pozici aktuální hodnoty ukazatele pracovní pozice.

<c>

int file_truncate(unsigned int file_handle);

</c>

Pokud si např. dopředu připravíte velký soubor (viz funkce file_expand), a už víte že více do něj nechcete zapsat, zavoláte funkci file_truncate(). Tato funkce upraví soubor na SD kartě tak, že nastaví jeho velikost právě na takovou hodnotu, jakou ve chvíli zavolání této funkce má pozice ukazatele pracovní polohy v souboru (což lze zjistit funkcí file_tell).

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)


file_expand

Funkce pro pokročilé uživatele. Umožňuje zvětšit velikost souboru, a tím jej připravit na zápis většího množství dat.

<c>

int file_expand(unsigned int file_handle, uint64_t new_size, unsigned int op_mode);

</c>

Funkci lze použít při založení nového souboru, nebo pro změnu existujícího souboru.

Typické použití je pro optimalizaci - tedy zajištění neztracení rychlosti - při zápisu většího množství dat do souboru.

Pokud víte, že budete do souboru zapisovat velké množství dat (a k tomu např. ještě po spoustě malých bloků), pak je mimořádně výhodné si takový soubor před-připravit, tedy nastavit mu dopředu takovou velikost, aby spolehlivě takové množství dat pokryla. Tedy tzv. před-alokace místa (podmínkou je, aby bylo toto místo na SD kartě dostupné - musíte mít dostatek volného místa na SD kartě !).

Proč ? protože před-alokací souboru tak se předejde zpomalení způsobené změnou FAT tabulky při každém zápisu datového bloku. Při zápisu do každého nového sektoru se totiž tento sektor musí (ve FAT tabulce) přiřadit právě vašemu souboru. Toto přiřazení lze provést i blokově (najednou) dopředu, právě pomocí funkce file_expand(), a tím dojde k významnému zrychlení datových zápisů do souboru.

Pokud nastavíte velikost větší, než nakonec využijete, jednoduše zavolejte funkci file_truncate() a tak velikost souboru ořízne (a uvolní tím místo na SD kartě).

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)
  • new_size - nová velikost souboru v bajtech
  • op_mode - (op_mode == 1): alokovat FAT záznamy ihned, nebo (op_mode == 0): až později


Příklad pro: file_expand() a file_truncate()

<c> .

int err;
unsigned int file1;

// otevreme soubor pro zapis
err = file_open(&file1, "soubor1.txt", "w+");
if (0 != err) { ... zpracuj_chybu ... };

// nastavime mu dopredu dostatecnou velikost
err = file_expand(file1, NOVA_VELIKOST_V_BAJTECH, 1);
if (0 != err) { ... zpracuj_chybu ... };

// provedeme zapis dat, tak jak je potreba
// ... file_write(file1, . . .) ...
// ... file_write(file1, . . .) ...
// ... file_write(file1, . . .) ...

// uz nebudeme dale zapisovat, 
// a protoze je mozne ze jsme take nevyuzili vsechno pred-alokovane misto
// (tedy, ze jsme si soubor nastavili na zbytecne velkou velikost)
// tak jej ted zkratime tak akorat
err = file_truncate(file1);
if (0 != err) { ... zpracuj_chybu ... };

// a vzdy musime soubor nakonec uzavrit !
err = file_close(&file1);
if (0 != err) { ... zpracuj_chybu ... };

</c>


file_size

Funkce vrací informaci o aktuální velikosti souboru na SD kartě.

<c>

uint64_t file_size(unsigned int file_handle);

</c>

Návratová hodnota je velikost souboru v bajtech.

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)


file_error

Funkce vrací hodnotu výsledku (chyby nebo úspěchu) od poslední provedené funkce nad souborem.

<c>

int file_error(unsigned int file_handle);

</c>

Návratová hodnota je chyba, která má formát specifikovaný v tabulce (viz nahoře na stránce).

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)


file_stat

Funkce předá informace o souboru. Volající musí zajistit strukturu, do které budou tyto informace funkcí uloženy.

<c>

int file_stat(char * file_path, void * existing_file_stat_structure);

</c>

Návratová hodnota je chyba, která má formát specifikovaný v tabulce (viz nahoře na stránce).

Parametry funkce:

  • file_handle - přímo hodnota identifikátoru souboru (byl poskytnut funkcí file_open)
  • * existing_file_stat_structure - ukazatel na proměnnou (strukturu) do které bude uložen výsledek

<c> .

typedef struct {
  uint64_t fsize;      // File size 
  uint16_t fdate;      // Modified date 
  uint16_t ftime;      // Modified time 
  uint8_t  fattrib;	// File attribute 
  char     altname[12 + 1]; // Altenative file name 
  char     fname[255 + 1];  // Primary file name 
} filinfo_t;

{
  int err;
  filinfo_t finfo;

  // otevreme soubor pro zapis
  err = file_stat("soubor1.txt", (void *)&finfo);
  if (0 != err) { ... zpracuj_chybu ... };

  // OK
  printf("velikost souboru %s je %u", finfo.fname, finfo.fsize);
}

</c>


file_unlink

Provede smazání souboru nebo složky na SD kartě.

<c>

int file_unlink(char * file_path);

</c>

Pokud se má smazat složka, musí být prázdná.

Parametry funkce:

  • file_path - textová cesta k souboru nebo ke složce, určené ke smazání; cesta se dává vždy celá a od rootu (kořenová složka) SD karty

file_rename

Provede přejmenování souboru nebo složky na SD kartě.

<c>

int file_rename(char * file_path_from, char * file_path_to);

</c>

Určitá omezení zde mohou být. TBD.

Parametry funkce:

  • file_path_from - původní název; cesta se dává vždy celá a od rootu (kořenová složka) SD karty
  • file_path_to - nový název; cesta se dává vždy celá a od rootu (kořenová složka) SD karty


file_mkdir

Vytvoří novou složku na SD kartě.

<c>

int file_mkdir(char * file_path);

</c>

Určitá omezení zde mohou být. TBD.

Parametry funkce:

  • file_path - textová cesta s názvem nové složky; cesta se dává vždy celá a od rootu (kořenová složka) SD karty


Příklad: čtení ze souboru

Následující příklad čte kus ze souboru (který musí být na SD kartě nachystán).

<c> .

#define MAX_BUFFER (32)

void test_cteni_ze_souboru(void)
{
 int res;
 unsigned int file1;
 unsigned int read;
 char text[MAX_BUFFER + 1];

 //
 printf("oteviram soubor\n");

 // otevreme soubor: sdcard_root\test.txt jako pouze pro cteni ("r")
 res = file_open(&file1, "test.txt", "r"); 
 if (0 != res) goto fail_2;

 // od ted, muzeme s timto souborem pracovat pomoci "file1" (dokud jej neuzavreme)

 //
 printf("OK, jdu z nej cist\n");

 // nastavime si do text[] same nuly
 memset((void *)text, 0, MAX_BUFFER);

 // precteme data 
 // - budeme chtit precist az MAX_BUFFER znaku (budou-li k dispozici)
 //   a do "read" se nam zapise, kolik se jich nakonec skutecne precetlo
 res = file_read(file1, text, MAX_BUFFER, &read);
 if (0 != res) goto fail_1;

 printf("1. precetl jsem %d znaku, zde jsou: '%s'", read, text);

 // . . . muzeme se souborem dale pracovat, napr. cist dalsi data ...



 // nakonec: vzdy zavreme soubor
 res = file_close(&file1);
 if (0 != res) goto fail_2;

 // hotovo OK
 return;

 // spravna obsluha chyb

 //
fail_1:
 file_close(&file1);
 // a pokracuj na fail_2

 //
fail_2:
 printf("nepovedlo se, chyba = %d\n", res);
}

</c>

Optimalizace

SD karta samotná určuje rychlost, s jakou se bude pracovat se soubory. Typicky, zápis na SD kartu je časově náročná operace, a může trvat dlouho (čím déle je karta používána, tím déle to trvá, v krajním případě trvá zápis do sektoru i několik sekund - ale to už je extrém - typicky počítejte s tím, že zápis typicky trvá SD kartě stovky milisekund).

S tím nemůže SDS ani FULL-C nic moc dělat, protože toto zdržení je na straně SD karty. SDS používá optimalizace kde to jen jde (vícebitová komunikace, slučování sektorů do multisector přístupu, atd.), takže se dá říct, že SDS jako takové prakticky jakékoliv zpoždění negeneruje, a veškeré čekání které budete pozorovat je z interních důvodů v SD kartě samotné.

Přesto je zde jeden základní trik, se kterým si můžete výhodně poradit ve svém FULL-C programu. Klíčem k vysokým rychlostem a co nejmenšímu čekání je pracovat se SD kartou tak, aby se z ní četlo (a zapisovalo) co nejvíce dat najednou.

Příklad: váš FC program zapisuje postupně nějaké malé hodnoty do textového souboru. Při každém zápisu tak vzniká veliká režije, která způsobuje zásadní zpoždění. Nicméně pokud se provede zápis jen jednou za čas, tedy pokud napíšete svůj program tak, aby zapisoval data do souboru tak, aby zápis byl svou velikostí právě násobkem velikosti sektoru (a ideálně čím více sektorů tím lépe), tak dosáhnete řádového citelného zrychlení celého programu.

SD karta interně pracuje s logickým rozdělením svého paměťového prostoru do "sektorů". Typicky je velikost jednoho sektoru právě 512 bajtů. Proto je zřejmé, že nejrychleji se s kartou pracuje, pokud se strefíme právě do datového bloku o velikosti jednoho - nebo více (celého násobku) - sektoru. Ne vždy je to prakticky možné, nicméně čím více se tomu přiblížíte, tím větší datové propustnosti (kratšímu čekání) dosáhnete.


Upozornění

Vždy vyzkoušejte, je-li SD karta kompatibilní s daným SDS modulem. Ideálně vyzkoušejte každou jednu SD kartu, kterou hodláte použít. V praxi fungují prakticky všechny karty, a je obtížné nalézt takovou, která by kompatibilní nebyla; ale pokud se taková objeví, pak takovou situaci nelze řešit jinak než použitím úplně jiné karty.

SD karta je výborným doplňkem zařízení SDS, protože oproti zabudované paměti DF poskytuje SD karta mnohem více prostoru pro data. Nicméně paměť DF je v SDS přítomna vždy a pořád - kdežto SD kartu lze vytáhnout a vyměnit.

Maximální počet současně otevřených souborů je 15.

Současný firmware v modulu SDS umožnujě přístup k SD kartě pouze z programu FULL-C, a zobrazování souborů ze SD karty přes webové rozhraní SDS (tzn. soubory nahrané na kartě, či vytvořené nebo změněné FC programem).