OldComp.cz

Komunitní diskuzní fórum pro fanoušky historických počítačů


Právě je 28.03.2024, 18:46

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]




Odeslat nové téma Odpovědět na téma  [ Příspěvků: 23 ]  Přejít na stránku Předchozí  1, 2
Autor Zpráva
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 20.08.2021, 20:26 
Offline
Kecálek

Registrován: 07.05.2014, 12:10
Příspěvky: 197
Bydliště: Jbc
Has thanked: 0 time
Been thanked: 39 times
RayeR píše:
Panda38 píše:
Tohle se sice asi Amigy netýká, ale k volatile bych doplnil - moderní překladače (jako gcc) jsou "chytřejší než uživatel" (to asi odkoukaly z Windows) a sice zachovají volatile přístup k adrese, ale nezaručují pořadí přístupu k různým adresám, mohou pořadí změnit. Na to pak může být nutné použít bariéru, která funkčně nic nedělá, jen řekne překladači "přeze mě nejede vlak!" Typický příklad je přehození zapnutí hodin periferie STM32 procesoru za inicializaci, kdy se pak člověk diví proč periferie v Release nefunguje když v Debug funguje.


Nemas konkretni priklad kodu (odkaz) pro to STM32, kde se vyskytuje tenhle problem? Ja sem kdysi narazil na nake podivne chovani, kde stacilo zduplikovat zapis hodnoty do jednoho registru a pak to chodilo a myslim, ze ten problem se objevil prave po nake aktualizaci gcc, ktere je (nekdy bohuzel) cimdal chytrejsi. A nejde to resit jinak nez tim hnusnym inline assemblerem ale jen nakym atributem ci pragmou?


Napr. na procesorech ARM jsou tzv. synchronizacni instrukce, ktere zajistuji, ze kod pred touto instrukci bude provedeny drive nez kod za touto instrukci. Od procesoru Cortex-M3 vyse to je nutne, protoze samotne zapisy do periferii neresi jadro, ale radic sbernice, takze se muze stat, ze se dva po sobe provedene zapisy provedou (z ruznych dovodu) ve stejnem instrukcnim cyklu. Kdyz druhy zapis potrebuje aktivni nastaveni z prvniho zapisu, tak to samozrejme nefunguje. Navic se chovani muze menit podle optimalizaci pri prekladu apod., takze pak se muze zdat, ze je ten kod nevyzpytatelny :-) ale pri dukladnem prozkoumani tam vzdy je k nalezeni nejaka pricina...
Naposledy jsem podobny problem resil dnes u obsluhy SPI na Cortex-M4, kde pomohlo spravne umisteni nekolika instrukci DSB - v C knihovne jsou pripravene jako funkce __DSB().


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 20.08.2021, 20:48 
Offline
Pan Štábní
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 1972
Bydliště: Most, Praha
Has thanked: 864 times
Been thanked: 697 times
RayeR píše:
Panda38 píše:
Tohle se sice asi Amigy netýká, ale k volatile bych doplnil - moderní překladače (jako gcc) jsou "chytřejší než uživatel" (to asi odkoukaly z Windows) a sice zachovají volatile přístup k adrese, ale nezaručují pořadí přístupu k různým adresám, mohou pořadí změnit. Na to pak může být nutné použít bariéru, která funkčně nic nedělá, jen řekne překladači "přeze mě nejede vlak!" Typický příklad je přehození zapnutí hodin periferie STM32 procesoru za inicializaci, kdy se pak člověk diví proč periferie v Release nefunguje když v Debug funguje.
Nemas konkretni priklad kodu (odkaz) pro to STM32, kde se vyskytuje tenhle problem? Ja sem kdysi narazil na nake podivne chovani, kde stacilo zduplikovat zapis hodnoty do jednoho registru a pak to chodilo a myslim, ze ten problem se objevil prave po nake aktualizaci gcc, ktere je (nekdy bohuzel) cimdal chytrejsi. A nejde to resit jinak nez tim hnusnym inline assemblerem ale jen nakym atributem ci pragmou?
Konkrétní kód už nemám, navíc to nemusí být reprodukovatelné (podle toho jak se kompilátoru bude zrovna zdát vhodné zpřeházet pořadí), ale bylo to na způsob uvedený níže (funkce PortInit). Běžně se při inicializaci zařízení v STM32 procesoru nejdříve zapnutím hodin aktivuje zařízení a pak se inicializuje zařízení. Setkal jsem se s tím problémem když mi port v debug překladu fungoval normálně, ale při optimalizovaném překladu nefungoval, jakoby neproběhla inicializace. Teprve až při porovnání listingů jsem si všiml, že kompilátor nedodržel uvedené pořadí přístupů k portům, tudíž u vypnutého portu nemohla proběhnout inicializace. Většinou pořadí dodržuje, ale není to zaručené, někdy se může rozhodnout to zpřeházet.

Zařazuji tedy bariéry do míst kde je důležité pořadí přístupů a navíc vypínám pro jistotu optimalizaci u inicializačních funkcí zařízení (kdybych zapomněl doplnit bariéru).

Mimochodem, kernel Linuxu používá bariéry velmi intenzivně, bez toho by nefungoval.

Kód:
// optimalizace kritickych funkci
#define OPTIM __attribute__((optimize("O2")))

// vypnuta optimalizace pri pristupu na porty
#define NOOPTIM __attribute__((optimize("O0")))

// vzdy inline
#define INLINE __attribute__((always_inline)) inline

// compiler barrier
INLINE void cb() { __asm volatile ("" ::: "memory"); }

// data memory barrier
INLINE void dmb() { __asm volatile (" dmb 0xF\n" ::: "memory"); }

// instruction synchronization barrier
INLINE void isb() { __asm volatile (" isb 0xF\n" ::: "memory"); }

// data synchronization barrier
INLINE void dsb() { __asm volatile (" dsb 0xF\n" ::: "memory"); }

NOOPTIM void PortInit()
{
   RCC->AHB4ENR |= 0x1F; // clk pro GPIOA - GPIOE
   cb(); // compiler barrier
   GPIOA->MODER = B0;
   ....

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 22.08.2021, 05:02 
Offline
Profík
Uživatelský avatar

Registrován: 12.06.2013, 00:11
Příspěvky: 641
Has thanked: 1 time
Been thanked: 76 times
Aha, no prave s init. SPI sem s tim mel problem na STM32L476.
Zatim sem ty bariaery nak neresil/neznal a ono to vetsinou nejak fungovalo.
Ted sem ale ponekud zmaten, ze panda uvadi celou radu ruznych barier ale ktere kde pouzit? Jedna se me hlavne o ty init.sekvence zapisu do registru. Postaci to __DSB()? To musim dat po kazdem zapisu hodnoty do cfg registru, takze kdyz budu nastavovat treba 10 registru, tak prolozene 10x __DSB() nebo to jde nak uzavrit do bloku? Co vim gcc ma nakou optimize pragmu:
#pragma GCC optimize ("O2")
#pragma GCC optimize ("O0")
pripadne lze ulozit a obnovit aktualni nastaveni na zacatku a konci bloku pomoci
#pragma GCC push_options
#pragma GCC pop_options
A jak vypada pak ASM kod s tim __DSB()? tam teda primo vlozi nejakou instrukci nebo jen zajisti spravne poradi zapisu do registru?

Jo tady sem nasel ten svuj problemovej kod:

void spi_init(...)
{
RCC->APB2ENR|=RCC_APB2ENR_SPI1EN; // enable bus clock for SPI peripheral
(void)RCC->APB2ENR; // wait 1 APB2 cycle (dummy read) for change being valid
(void)RCC->APB2ENR; // wait 1 APB2 cycle (dummy read) for change being valid
SET_PORT_MODE(SPI1_SS_PORT, SPI1_SS_PIN, GPIO_MODE_ALT, GPIO_OTYPE_PP, GPIO_FLOAT, GPIO_SPEED_HIGH);
SET_PORT_AF(SPI1_SS_PORT, SPI1_SS_PIN, SPI1_SS_AF); // configure GPIO pin to alternate function
...

_________________
http://rayer.g6.cz, core i7-2600K, SB Audigy+YMF724+DreamBlaster, GTX970, DOS/WIN98SE/NT4/XP/Debian | retroPC: PPro 200, 192MB, SB AWE64+Live, Matrox Millenium II/8MB+Voodo1, USB 2.0


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 22.08.2021, 06:46 
Offline
Kecálek

Registrován: 07.05.2014, 12:10
Příspěvky: 197
Bydliště: Jbc
Has thanked: 0 time
Been thanked: 39 times
RayeR píše:
Aha, no prave s init. SPI sem s tim mel problem na STM32L476.
Zatim sem ty bariaery nak neresil/neznal a ono to vetsinou nejak fungovalo.
Ted sem ale ponekud zmaten, ze panda uvadi celou radu ruznych barier ale ktere kde pouzit? Jedna se me hlavne o ty init.sekvence zapisu do registru. Postaci to __DSB()? To musim dat po kazdem zapisu hodnoty do cfg registru, takze kdyz budu nastavovat treba 10 registru, tak prolozene 10x __DSB() nebo to jde nak uzavrit do bloku?

DSB - synchronizace pristupu k datum; ISB - synchronizace provadeni instrukci; DMB - bariera pristupu do pameti.
Z toho, co jsem zjistoval, tak na Cortex-M3/4 staci vetsinou pouzivat instrukce DSB. Inline funkce __DSB() se prelozi jako instrukce DSB.
Ostatni instrukce jsou uzitecne u vyssich typu ARM jader, kde jsou napr. cache a jine vykon zlepsujici techniky.
Jak tomu rozumim, tak DSB je potreba dat tam, kde napr. jeden zapis zapne hodiny pro periferii a hned druhy zapis zapisuje do periferie, coz predpoklada zapnute hodiny. Prvni zapis je u STM32 do periferie RCC, druhy zapis pak do jine periferie, ktera je treba na jine sbernici, tak se klidne muze stat, ze prvni zapis je zpozdeny, protoze se jeste dokoncuje predesly zapis, a druhy zapis se provede ve stejne chvili jako ten prvni...
Pokud se zapisuje nastaveni do jedne periferie, tak jednotlive zapisy jdou po sobe - kazdy dalsi zapis ceka az po dokonceni predchoziho. Tady DSB neni potreba.
Pokud se zapisuje nastaveni do periferii, kde neni potreba dokonceni predchoziho zapisu, tak tam taky DSB neni potreba.
Ve zminovanem kodu je misto DSB provedeno cteni z RCC registru, do ktereho se zapisovalo. To podle me udela stejnou sluzbu, i kdyz o dost pomalejsi... Ale zrovna tady to neni uplne potreba, protoze dalsi zapisy jdou do GPIO registru, coz nema s nastavovanym bitem SPI1EN nic spolecneho...
Snad jsem to svym vysvetlovacim pokusem moc "nezatemnil" ;)


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 22.08.2021, 08:17 
Offline
Pan Štábní
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 1972
Bydliště: Most, Praha
Has thanked: 864 times
Been thanked: 697 times
U jednojádra by se mělo vystačit s bariérou kompilátoru, která zajistí aby se nepromíchávaly přístupy na porty. Stačí použít jen tam kde je pořadí důležité a je zapnutá optimalizace - obvykle jen vypnutí/zapnutí periferie. Do kódu nic nevkládá. Datová bariéra je potřebná hlavně i vícejádra, vloží instrukci dmb/dsb a zajistí aby procesor dokončil paměťové operace a uvidělo je druhé jádro, aby se např. nedržel zápis v cache.

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 23.08.2021, 01:52 
Offline
Profík
Uživatelský avatar

Registrován: 12.06.2013, 00:11
Příspěvky: 641
Has thanked: 1 time
Been thanked: 76 times
On tam u me bude problem asi nekde jinde, kdyz sem zkusil to __DSB(), tak sem ho tam musel dat hned 3x aby ten kod fungoval (inicializace a kresleni na graficky displej po SPI). Ani s vyplou optimalizaci -O0 mi to bez tech opicaren nefunguje. Jinak me zajima jen cortex-M4, ten zadne vice jadra/sperskalary nema...

void spi_init(..)
{
__DSB(); // data sync barrier but why need it 3x ?
RCC->APB2ENR|=RCC_APB2ENR_SPI1EN; // enable bus clock for SPI peripheral
// (void)RCC->APB2ENR; // wait 1 APB2 cycle (dummy read) for change being valid
__DSB();
__DSB();

Takze mozna mi to chybi jeste nekde jinde a zrovna se to projevuje na tomto miste kodu, ale nema to primou souvislost. Ale matne si pamatuju, ze s nakym starsim gcc to kdysi fungovalo bez toho zdvojeneho cteni, ze se to posralo az casem...

_________________
http://rayer.g6.cz, core i7-2600K, SB Audigy+YMF724+DreamBlaster, GTX970, DOS/WIN98SE/NT4/XP/Debian | retroPC: PPro 200, 192MB, SB AWE64+Live, Matrox Millenium II/8MB+Voodo1, USB 2.0


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 23.08.2021, 03:02 
Offline
Pan Generální
Uživatelský avatar

Registrován: 13.05.2013, 09:15
Příspěvky: 2278
Bydliště: Brno
Has thanked: 842 times
Been thanked: 302 times
Jednou, ne já v rámci programování, shodou okolností na Amize a v C, nebo v assembleru programátor taky musel uvést 2 krát po sobě stejný příkaz. Bylo to popsáno, že se instrukce nestihla provést.

_________________
Amiga - PMD 85


Nahoru
 Profil  
 
 Předmět příspěvku: Re: programování v C na Amize
PříspěvekNapsal: 23.08.2021, 04:20 
Offline
Pan Štábní
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 1972
Bydliště: Most, Praha
Has thanked: 864 times
Been thanked: 697 times
RayeR nezkusil jsi místo dsb použít jen nop? Možná to není problém bariér, ale že periferie vyžaduje prodlevu na nastartování.

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
Zobrazit příspěvky za předchozí:  Seřadit podle  
Odeslat nové téma Odpovědět na téma  [ Příspěvků: 23 ]  Přejít na stránku Předchozí  1, 2

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 4 návštevníků


Nemůžete zakládat nová témata v tomto fóru
Nemůžete odpovídat v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete přikládat soubory v tomto fóru

Hledat:
Přejít na:  
Založeno na phpBB® Forum Software © phpBB Group
Český překlad – phpBB.cz