1

Téma: [vyřešeno] Alokace bloků na SD-kartě

Plánuji vytvořit na SDS-BIG cyklickou frontu, ve které budou data přidávána i odebírána. Aby mi SD-karta vydržela co nejdéle, alokuji na začátku dostatečnou velikost souboru a budu do něj zapisovat od pozice 0 stále dál. V zálohované RAM si budu držet ukazatel zápisu i čtení, takže na začátku souboru bude postupně vznikat "prázdné místo" po vyčtených záznamech. V případě, že zápis dojde na konec souboru, nebudu jej přepisovat od začátku, ale uvažuji vytvořit další generaci souboru a první soubor ponechat, abych zabránil systému použít již alokované bloky. Teprve v okamžiku, až se začne SD-karta zaplňovat, nejstarší verze vymažu a alokuji nový soubor.

Je to nutné (vhodné) provádět to takto, nebo má SDS nějakou optimalizaci alokace bloků, takže se vždy alokují ty nejméně přepsané?

2

Re: [vyřešeno] Alokace bloků na SD-kartě

file_expand() s parametrem 1
viz návod https://wiki.merenienergie.cz/subdom/wiki/index.php?title=FULL-C:_SD_card_functions

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

3

Re: [vyřešeno] Alokace bloků na SD-kartě

Ano, to je mi jasné. Jedná se mi o to, jaká je pravděpodobnost, že když smažu soubor, alokují se znovu ty samé bloky. Podobně jako třeba v heapu, kdy se při pravidelné alokaci a uvolňování přiřazuje stále to stejné fyzické místo. Tímto postupem si "ničím" stále ty samé bloky, zatímco jiné zůstávají "nedotčené a zdravé". Pokud to neřeší systém (podobně jako např. řadiče SSD disků), tak to udělám tak, že si SD-kartu budu postupně zaplňovat sám až téměř do konce a pak teprve začnu uvolňovat ty nejstarší soubory. Velikost alokace a počet souborů si pak musím vhodně zvolit taky tak, ať zbytečně neničím FATku častými zápisy.

Ještě mám k SD-kartám další dotaz:

- Probíhají odložené zápisy "na pozadí" mimo režii mého programu (např. v jiném vláknu systému), nebo až při nějaké jiné operaci s SD-kartou? Ztrátu jednoho záznamu jsem schopen oželet, ale pokud by jich v cache bylo víc a čekalo se, až překročím hranice bloku, tak to raději po každém zápisu provedu flush.

- Z dokumentace vyplývá, že žádná možnost zjistit obsah adresáře na SD-kartě neexistuje, takže si musím přehled udržovat sám (případně pokusem o otevření souboru zjistit, zda existuje). Je tomu tak, že?

4

Re: [vyřešeno] Alokace bloků na SD-kartě

Práce s SD kartou je blokujícíc, tedy nepoužívá se nějaká větší "file cache" - každé čtení je vždy fyzicky provedeno v okamžik požadavku, a každý zápis je proveden v okamžik požadavku (mimo aktivitu jednosektorové cache).
Do dokončení provedení dané činnosti (komunikace s SD kartou) je FC program zablokován (je tam timeout, samozřejmě). Bez ohledu na vyšší vrstvy, tedy jestli je soubor dopředu "natáhnutý" nebo se postupně natahuje s každým dalším zápisem.

Jediná optimalizace ("cache"), ve SDS, je pouze na úrovni jediného sektoru, tedy typicky 512 B. Viz funkce file_sync().
Tato cache má význam (a způsobí tedy zrychlení) jen při zápisu bloků menších než velikost sektoru (jinak se toto neuplatní).
Při zápis menších bloků (než velikost 1 sektoru - POZOR ale vždy v rámci 1 stejného sektoru) dochází k jejich cachování, a uložení je provedeno až při: (a) přechodu zápis na jiný sektor, (b) zavoláním file_sync(), (c) uzavřením souboru.
Pokud by se toto nedělalo, tak každý zápis, by vždy znamenal čtení, smazání a zápis celého sektoru. A to je nežádou opotřebení SD karty, kde se má zápis dělat ideálně po celých sektorech.

Dále je zde ještě další záležitost.

Pokud si soubor dopředu nenatáhnete (file_expand), tak při každém zápisu (který obsah dat, tj. velikost souboru, zvětšuje) dojde nejen k zápisu dat samotných, ale i k zápisu do FAT tabulky (pro každý nově přidaný sektor), tedy dvojnásobné zpoždění.
Zde se tedy významně ukazuje proč je lepší si soubor alokovat předem.

-

Na SD kartě nelze nikdy garantovat, že bude zápis do stejného fyzického sektoru v paměťovém chipu. To je starost kontroléru v SD kartě (wear-leveling), a prakticky každá si to řeší sama a jinak. Takže může dojít k různým zpožděním. Prakticky jediné zpoždění, které lze pocítit, je vždy mazání sektoru v paměťovém chipu SD karty. Čím více se zapisuje, a pak se má mazat (nebo zapisovat znovu na už zapsané místo), tím více to (postupem času) trvá.

Dále je zde otázka opakované alokace FAT sektorů. Z principu funkce SD karty ale tato otázka nemá význam. I kdyby se FAT opakovaně strefila do stejných sektorů, doba jejich zápisu/přepisu (čtení, smazání a pak zápis) bude trvat cca stejně.
Jediná optimalizace zde je, tak jak jsem psal výše, vyhnout se postupnému zápisu do FAT pomocí před-alokace FAT,
a vhodně pracovat s jednosektorovou cache.

-

Ověření, zda-li soubor existuje - např. pomocí file_open()

Výpis obsahu disku/složky - je připraveno ale ještě neuvolněno (specifické FC funkce), až to bude dotestováno tak s novým firmware to bude k dispozici.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

5

Re: [vyřešeno] Alokace bloků na SD-kartě

Díky za vysvětlení. Je to v podtstatě tak, jak jsem předpokládal. Nebylo mi jasné, jestli alokaci bloků provádí řadič SD-karty nebo SDS.

Doplním to jen o vlastní zkušenost, třeba se to někomu bude hodit. Používáme SD-kartu ve dvou aplikacích na embedded systémech s Windows CE:

- Jednou pomocí MSMQ, což je správa front zpráv, přenášených mezi aplikacemi (nebo jednou aplikací) - součást systému. Má dva kanály - zápisový a čtecí a měla by být optimalizována právě pro embedded systémy - tedy spolehlivost, odolnost proti náhodným pádům systému a optimalizaci využití SD-karty. Je to opravdu spolehlivé a i po několika letech běží systémy bez problémů. Fronta vytáří několik generací souborů, a to i přes to, že je stále téměř prázdná. Jestli je to opravdu proto, aby se šetřila SD karta, se mohu jen dohadovat, nicméně mě to inspirovalo k postupu, který sem již popsal v předchozím příspěvku.

- Druhá aplikace používá MS SQL CE - a tam už dříve než po roce nastávají problémy - aplikace se neustále zpomaluje a zpomaluje, až to může dojít do stádia, že je SD-karta částečně nečitelná. A to i přes to, že se do databáze neustále přidávají nové záznamy, aniž by se staré mazaly. SQL CE asi není dobře optimalizován, v poslední (dnes už stejně nepodporované) verzi WIndows CE dokonce SQL CE chybí a ani se tam nedá doinstalovat. Používáme SQL Lite, ale ani tady si nejsem moc jist spolehlivostí.

adamn napsal:

Jediná optimalizace ("cache"), ve SDS, je pouze na úrovni jediného sektoru, tedy typicky 512 B. Viz funkce file_sync().
Tato cache má význam (a způsobí tedy zrychlení) jen při zápisu bloků menších než velikost sektoru (jinak se toto neuplatní).
Při zápis menších bloků (než velikost 1 sektoru - POZOR ale vždy v rámci 1 stejného sektoru) dochází k jejich cachování, a uložení je provedeno až při: (a) přechodu zápis na jiný sektor, (b) zavoláním file_sync(), (c) uzavřením souboru.
Pokud by se toto nedělalo, tak každý zápis, by vždy znamenal čtení, smazání a zápis celého sektoru. A to je nežádou opotřebení SD karty, kde se má zápis dělat ideálně po celých sektorech.

To je právě můj problém, protože do souboru se budou zapisovat události různé délky (cca 10 - 160 bytů) a alokovat pro každou zprávu maximální velikost nebo dokonce velikost bloku 512 mi připadá jako příliš velké plýtvání. Takže každé zprávě bude předcházet délka a ukazatel posledního zápisu (tell) si vždy uložím do zálohované RAM. V případě pádu systému bych zapisoval dál od uloženého ukazatele, ale data z přechozího cachovaného bloku by nemusela být uložena. To by mohlo způsobit fatální problémy při čtení - délka by mohla být nesmyslná a já bych se nikdy správně nenapozicoval na správný záznam. Takže mi zbývá volat flush po každém zápisu nebo ci cachovat sám s tím, že ukazatel zápisu do RAM uložím až po zápisu cache. Ostatně z fronty bude možné současně číst (ukazatel čtení v RAM), takže ten odložený zápis by se pak stejně moc nevyužil (pokud nemá soubor samostatnou cahe pro čtení i zápis). I tak uvažuji, že budu data nějak synchronizovat podobně jako u sériové komunikace nějakým startbytem, popř. endbytem, abych se v případě poškozeného souboru nějak správně napozicoval.

Tím jsem snad téma vyčerpal a nebudu už s tím otravovat. Pokud bych se však snad v něčem podtstně mýlil, tak budu rád, když dáte vědět.

6

Re: [vyřešeno] Alokace bloků na SD-kartě

Tak se k tomu musím vrátit. Funkce file_expand mi vrací hodnotu -7 (DENIED). Co dělám špatně? Přikládám celý program.

    void main(void)
    {
       printf("Startn");
       while (SDS_get_u32(3850) == 0)
             ;
       printf("SD Card ready, block size=%dn", SDS_get_u32(3852));

       file_mkdir("web");
       unsigned int handle;
       unsigned int w;
       int res;
       if ((res = file_open(&handle, "test.dat", "w+")) != 0)
          printf("File open error %dn", res);
       printf("File open OK, handle: %dn", res);
       if ((res = file_write(handle, "EXPAND", 6, &w)) != 0)
          printf("File write error %dn", res);
       if ((res = file_sync(handle)) != 0)
          printf("File flush error %dn", res);
       printf("File write OKn");
       if ((res = file_expand(handle, 10000, 1)) != 0)
          printf("File expand error %dn", res);
       while (1)
          ;
    }

Výstup je:

Start
SD Card ready, block size=512
File open OK, handle: 0
File write OK
File expand error -7

Je vidět, že zapisovat jde, protože metoda file_write a file_sync fungují.

7

Re: [vyřešeno] Alokace bloků na SD-kartě

Jde o dvě samostatné záležitosti.

První je před-alokace informace ve FAT tabulce, pro vybraný soubor.
Tady jde o optimalizaci zápisu. Pokud není soubor před-alokován, tak pro každý zápis dat, který si vyžádá nový FAT cluster, dojde k dvojitému write přístupu na SD kartu (zápis do FAT pro alokaci clusteru, a zápis dat samotných). Což je zpomalení nejméně o polovinu. Tomu se dá plně předejít před-alokací FAT tabulky pro tento soubor.

Druhá je jednosektorová write cache na úrovni driveru v SDS. Ano, ta se dá plně pokořit pomocí file_sync().
Nicméně, při zápisu 10 až 160 B, by případná ztráta byla (snad) akceptovatelná, protože do jednoho sektoru (512B) se těchto prvků zase tolik nevleze.
Flush této cache se provádí i automaticky při uzavření souboru.
Tato cache má velký vliv na výkon - pokud ji nevyužijete na straně SDS, stejně +/- skončíte s nějakou podobnou formou na straně svého FC programu, a tam bude riziko ztráty o to větší (SDS se při detekci výpadku napájení aspoň snaží kartu uzavřít, to v programu nejde).

Každopádně, jak jsem psal, obě tyto záležitosti jsou na sobě zcela nezávislé.

Jak si to pak interně organizuje SD karta, to je sázka do loterie. Ano mohou být systémy které to mají (pro některé typy SD karet) odkoukané / změřené, ale pak mohou zcela pohořet pokud se najednou použije karta jiná.
Pro SDS jsem skončil s tímto řešením, jednodušeji už to dále vymyslet moc nepůjde.

---

Chyba -7 pro danou funkci - by znamenala že buď je soubor neexistuje, nebo není otevřen s parametrem WRITE.
Tyto dva problémy to nejspíše nebudou.

Další důvod pro -7 je, že se nepovede nalézt souvislý blok (FAT clustery) o požadované velikosti (tzn. že je FAT natolik fragmentovaná, že se to nemá kam expandovat).
To se dá ověřit snadno, zkuste ten expand provést s mnohem menší požadovanou velikostí, jestli to projde.
Nebo si kartu dát do PC a FAT si zanalyzovat vhodným SW nástrojem, jak moc je fragmentováná (nebo ne).

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

8

Re: [vyřešeno] Alokace bloků na SD-kartě

První možnost to nebude, na tom se asi shodneme.

SD-karta je nová, 8GB, zformátovaná jako exFAT s velikostí alokační jednotky 512B. Expand jsem zkoušel i s parametrem 512B a 1024B se stejným výsledkem. Ještě mohu zkusit jinou kartu nebo jiný FAT systém. Ale udivuje mě, že zápis se skytou alokací (file_write) nového bloku funguje, ale alokace jednoho bloku pomocí expand ne. Nemůže být problém s přetypováním int32 na int64? Je konstanta 10000 správně? 10000ULL bohužel nefunguje.

9

Re: [vyřešeno] Alokace bloků na SD-kartě

Je možné že je nějaký problém ve firmware. Vyzkouším to.
Za tou chybou -7 je skryto více vnitřních možností, takže si to musím odkrokovat, pokud se mi to povede zreplikovat.

Hodnoty tam jsou správně, to problém nebude.

Dám vědět.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

10 Naposledy upravil: absolonj (2022-11-09 11:53:41)

Re: [vyřešeno] Alokace bloků na SD-kartě

Zatím jsem to vyřešil vlastní funcí expand, v které se napozicuji na konec souboru a zapíšu "prázdný" blok požadované velikosti (to by mohlo podobně jako původní expand minimalizovat zápisy do FAT). Jen mám dojem, že je tam nějaké omezení v délce bufferu pro file_write, protože od jisté velikosti rozšíření mi to hlásilo chybu.

11

Re: [vyřešeno] Alokace bloků na SD-kartě

Odzkoušel jsem to a je to v pořádku - ten příklad byl špatně.

Základní princip pro file_expand() je v tom, že se musí provést nad souborem, který je zcela prázdný.

Zde je upravený původní příklad:

void main(void)
{
       unsigned int handle;
       unsigned int w;
       int res;

       printf("Startn");

       while (0 == SDS_get_u32(3850))
             ;

       printf("SD Card ready, block size=%dn", SDS_get_u32(3852));

       file_mkdir("web");

       // soubor vytvorime do podslozky "web" at se na tento soubor pak muzem podivat pres prohlizec

       if ((res = file_open(&handle, "web/test1.txt", "w+")) != 0)
          printf("File open error %dn", res);

       printf("File open - handle: %dn", res);

       // expand lze provest jedine na novy prazdny soubor, a to jen jednou
       if ((res = file_expand(handle, 10000, 1)) != 0)
          printf("File expand error %dn", res);

       // a muzeme zapisovat a zapisovat ... atd.
       if ((res = file_write(handle, "TEST", 4, &w)) != 0)
          printf("File write error %dn", res);

      
       // always close
       file_close(&handle);

       printf("File closedn");

       //
       while (1)
          ;
}

Přesto, jeden závěr mi z toho vyšel, pro doplněni do FW - a to zjemnění chybových kódů (ať vše není pod generickým -7). V novém FW budou nové kódy -20 a -21.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

12

Re: [vyřešeno] Alokace bloků na SD-kartě

Vyzkoušel jste ?

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

13

Re: [vyřešeno] Alokace bloků na SD-kartě

Ano, takto to funguje. Já jsem sice počítal s tím, že budu soubor rozšiřovat průběžně, jakmile dojde k jeho naplnění, ale to už si vyřeším jinak. I tak se to hodí.

Ještě jsem při pokusech narazil na chybu -20, která také není zatím zdokumentována.

14

Re: [vyřešeno] Alokace bloků na SD-kartě

Dokumentace opravena (chybové kódy).

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !