Fwd: STM32F103 UART DMA

Pavel Hudeček edizon na seznam.cz
Středa Prosinec 27 20:58:29 CET 2023


Některé MCU jsou na cvičení s porty i optimalizované.

Třeba LPC11U68, tam udělám programem v C na pinu přes 20 MHz, tedy 
blízko CLK/2. Taky jsem toho hojně využíval. Displej v paralelním módu, 
data i všechny řídící signály na jednom 32b portu, pak je rychlost 
komunikace taková, že doba překreslení závisí výhradně na sw co data 
generuje.

Ale jsou i opačná překvápka: Potřeboval jsem na AM3358 nenáročný přístup 
k SPI flash a byl jsem línej rozchozovat HW SPI. Zápis šel dle 
očekávání, někde v řádu 100 Mbit, ale čtení jsem si napřed myslel, že 
zatuhlo ... ne, jen bylo rychlé asi jako vytáčený internet před 25 
lety:-) Přitom CLK do CPU bylo 650 MHz.

PH

Dne 27.12.2023 v 18:58 Jaroslav Buchta napsal(a):
> Mam spravny pocit, ze dokonceni vsech zapisu by mela zajistit 
> instrukce DSB? Nebo nejaka podobna z tech cca 3, se mi furt pletou.
> Ale asi az u novejsich.
> Mam ale vyzkouseno, ze kdyz to melo byt rychle (simulace SPI kdyz se 
> netrefily piny...), nasazel jsem za sebe instrukce zapisu do 32b 
> registru S/R, kazda menila hodiny , kazda druha data a chodilo to jak 
> vino maximalni rychlosti, kdyz jsem vyhazel DSB, tak rychleji  ale 
> stale dobre. Sbernice mely stejnou frekvenci a byl to tusim M4.
> Tak se toho asi netreba uplne bat a cekam, ze to je nejak interne 
> poresene.
>
> Dne 27.12.2023 v 18:06 dresler napsal(a):
>> Bavíme-li se klasických STM32, zápisy se neztrácejí. Podle typu 
>> architektury je tam 0-1 write buffer mezi jádrem a hlavní sběrnicí, 
>> pak (AXI-)AHB-APB bridge. Zde je zpoždění dané tím, že se data 
>> resynchronizují mezi různými hodinami, kde platí nejdelší zpoždění 
>> (1+ratio) a zpoždění vnější periferie. Není tedy potřeba psát opakovaně.
>>
>> Aby se zajistilo, že program pokračuje po dokončení zápisu do 
>> registru, prostě ten registr přečtěte zpět.
>>
>> Tomáš
>>
>>
>>
>> Odesláno z mého zařízení Galaxy
>>
>>
>> -------- Původní zpráva --------
>> Od: Petr Labaj <labaj na volny.cz>
>> Datum: 26.12.23 22:27 (GMT+01:00)
>> Komu: hw-list na list.hw.cz
>> Předmět: Re: Fwd: STM32F103 UART DMA
>>
>> Tak v tom případě i já pošlu odpověď, kterou jsem Vám posílal soukromě,
>> do konference:
>>
>> Hmmm.
>> A díval jste se prosím na to, čeho se Vámi vysmívaná "rada nad zlato"
>> vlastně týkala?
>> Psal jsem o prvním zápisu do nějakého registru, kdy obecně nemusím
>> vědět, jaký je předchozí stav daného registru.
>> Takže pokud tam zapíšu ORem, tak tam můžou zůstat nahozené nějaké bity,
>> které nechci, ale byly tam v jedničce už dřív.
>>
>> V tomto případě přece naplatí, že by se mohl ztratit nějaký zápis kvůli
>> asynchronnosti přístupu na danou periferii.
>> Jedná se o _první_ zápis na tuto periferii.
>> Všechny případné další zápisy už samozřejmě musí být ORem, protože jinak
>> by zmizela předchozí konfigurace.
>>
>> PL
>>
>> *****************
>>
>> Dne 26.12.2023 v 22:06 František Burian napsal(a):
>> > Omlouvám se, asi jsem to neposlal do konference ale p. Labajovi, ale
>> > mířilo to do konference.
>> >
>> >
>> >
>> >
>> > Zdravíčko,
>> >
>> >   Obvykle nepřispívám ale tady musím, protože zde je nastíněna "rada
>> > nad zlato", která tomu, kdo se jí bude řídit způsobí mnoho bezesných
>> > nocí.
>> >
>> >   Nezapomínejte, že ARM je architektura mnoha sběrnic, různých keší a
>> > to, co napíšete do programu nikdy není to, co se provede. Zkuste si
>> > udělat
>> > rychlý program, který bude pouze zapisovat do GPIO portu a nahazovat
>> > všechny bity na 1 a shazovat všechny bity do 0, připojte osciloskop k
>> > pinu
>> > a pozorujte, co uvidíte.
>> >
>> > Operace = je převedena do instrukce STRB která nezapisuje na paměťové
>> > místo, ale do cache, která to posílá na pomalejší sběrnici. A pokud se
>> > sejdou dva STRB do stejné paměťové pozice, je předchozí zápis ztracen
>> > a na pomalejší sběrnici se populuje později zapsaná hodnota. GPIO 
>> jsou na
>> > STMku za dvěma takovými cachemi, AHB, APB a dokážete si představit
>> > jakýpak krásný náhodný děj se na GPIO povede vyrobit.
>> >
>> > Aby byly zápisy jednoznačně orderované, musí mezi nimi být LDRB který
>> > počká na úplnou invalidaci všech keší po cestě před další instrukcí.
>> > Když tedy
>> > převedete původní sekvenci (pseudokód)
>> >
>> > while (1) { PORTB = 0; PORTB=255;  }
>> >
>> > na
>> >
>> > while (1) { PORTB &=0; PORTB|=255; }
>> >
>> > dosáhnete výrazně pomalejšího programu, ale krásného obdélníku ikdyž z
>> > logiky věci by ty programy měly dělat totéž. Ještě krásnější je, že
>> > druhý příklad se může přeložit na první kvůli optimalizacím překladače
>> > když někdo při definici PORTB zapoměl na volatile u každého prvku.
>> >
>> > Toto samosemou platí pro každý přístup na jakoukoliv paměť která má po
>> > cestě nějakou cache (tedy je na pomalejší sběrnici). Proto musí být
>> > všechny přístupy k řídícím registrům které musí být vždy sekvenční
>> > (nejprv nastav tento bit, pak tento bit) buďto provedeny pomocí 
>> operátorů
>> > |= nebo &= nebo použít instrukci dmb, která ale čeká na všechny cache,
>> > ne jen na tu, kterou chcete zapsat, takže ještě víc zpomalí.
>> >
>> > Registry konfigurace periferií jsou přesně ty, které mají v podmínkách
>> > nejprv toto pak toto a když na tento postup nemyslíte, "ono to nějak
>> > funguje"
>> > ale jednou za čas to selže a daná periferie se jeví jako zmrzlá
>> > protože jste nastavili bity ve stejný okamžik, ne jeden po druhém.
>> >
>> > Cache mezi sběrnicemi má omeznou velokost, takže pokud za sebou
>> > zapíšete dostatečný počet zápisů do stejné sběrnice, tak můžete 
>> zase ten
>> > první, protože se čeká na ostatní zápisy. Jak je cache dlouhá je
>> > nedokumentovaná funkce a mění se to mezi výrobními dávkami
>> > (odpozorováno 2-8
>> > zápisů u stejného čipu jen z jiných dávek, dokonce jsem nabyl dojmu že
>> > se hloubka mění podle poměru frekvencí ale tam nemám ověřeno) takže
>> > nelze spoléhat na konkrétní velikost cache.
>> >
>> > Stejný problém je když takto přistoupíte na dvě po sobě jdoucí
>> > paměťové místa, tak ty čipy s delší cachí zápis uvnitř keše převedou
>> > na jeden přístup
>> > do paměti s delším slovem a na některých architekturách hard fault
>> > jako vyšitý, když ale použijete RMW, hardfault zmizí. (Nevím jestli to
>> > je aktuální,
>> > takto se chovaly staré čipy)
>> >
>> > Pokud se podíváte do implementace CMSIS, je tam vždy RMW operace s
>> > registry, nikdy to není čistý zápis právě kvůli tomuto fenoménu.
>> >
>> > S tímto jsem si při psaní vlastních rychlých knihoven užil více než
>> > dost. Probíralo se to i v intelektuálním klubu v Patronce, je dobré
>> > číst backlogy
>> > nebo se účastnit :-)
>> >
>> > S pozdravem a přáním pěkných svátků
>> >
>> >   František Burian
>> >
>> >
>> > Dne 26. 12. 23 v 17:14 Petr Labaj napsal(a):
>> >> Můžu drobnou poznámku, která je ale obecnější a s daným problémem
>> >> nesouvisí?
>> >>
>> >> Vy všude používáte "orování" parametrů, které zadáváte do řídících
>> >> registrů.
>> >> Např.:
>> >> USART2->CR1 |= USART_CR1_TE | USART_CR1_RE;
>> >> nebo
>> >> DMA1_Channel6->CCR |= DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_TCIE;
>> >>
>> >> Ale používáte to i při prvním zápisu do daného registru.
>> >> Tedy jinými slovy spoléháte na to, že předtím tam byly samé nuly.
>> >> Což může být velice zrádné, když tu konstrukci použijete třeba i
>> >> někdy později, kdy už v těch registrech něco je.
>> >>
>> >> Takže by podle mě měl první zápis vypadat takhle:
>> >> USART2->CR1 = USART_CR1_TE | USART_CR1_RE;
>> >> nebo
>> >> DMA1_Channel6->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_TCIE;
>> >>
>> >> A orování použít až když tam už dodatečně něco přidáváte.
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20231227/0cadf5f5/attachment.htm>


Další informace o konferenci Hw-list