GCC optimalizace, zahada

Jan Waclawek konfera na efton.sk
Sobota Listopad 4 13:22:50 CET 2017


No tak potom problem nie je tam.

Cele to zacalo tym, ze v 'F1 je GPIO na APB a naviac jeho registre su
pristupne len 32-bitovo (aj ked je napr. BRR defacto 16-bitovy), a tak
niekoho napadlo, ze okrem toho BSRR registra, ktorym sa da nulovat aj
nastavovat naraz, sa urobi este aj ten BRR register, ktory je pre vsetky
prakticke ucely zbytocny. Moj osobny tip je, ze v ST zrecyklovali IP z
nejakeho starsieho designu, mozno 8- alebo 16-bitoveho, kde na jeho
existenciu boli nejake velmi dobre dovody.

Dalsim modelom bola 'L1 a v nej je uz GPIO na AHB (asi bol krik, ze sa s
GPIO neda robit tak rychly toggle ako u konkurencie, hoci je to IMO
pomerne neuzitocna poziadavka, ale taky je uz zivot), uz je 8/16/32-bit
pristup, a ten BRR tam je tiez. Toto je zachovane aj v 'F0 a 'F3, zrejme
zo zotrvacnosti.

V 'F2/'F4 uz ten zbytocny register nie je, co ale znamena, ze struktura pre
GPIO v headeri z 'F4 SPL vyzera inak:
typedef struct
{
  __IO uint32_t MODER;    /*!< GPIO port mode register,              
Address offset: 0x00      */
  __IO uint32_t OTYPER;   /*!< GPIO port output type register,       
Address offset: 0x04      */
  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,      
Address offset: 0x08      */
  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register, 
Address offset: 0x0C      */
  __IO uint32_t IDR;      /*!< GPIO port input data register,        
Address offset: 0x10      */
  __IO uint32_t ODR;      /*!< GPIO port output data register,       
Address offset: 0x14      */
  __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register, 
Address offset: 0x18      */
  __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register,
Address offset: 0x1A      */
  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register,
Address offset: 0x1C      */
  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,    
Address offset: 0x20-0x24 */
} GPIO_TypeDef;

toto si vyzaduje bud to predefinovat (to je primarny dovod preco som tie
headery prepisoval, aj ked viem ze to nie je dobry napad) alebo urobit ten
typecast co ste urobili. Kedze ste pisali, ze to pomohlo, tak som cakal,
ze mate nejaky hybridny header z nejakeho ktovieakeho zdroja, ktory vyzera
nejako takto ako tento z 'F4, a teda ze v nom je BSRR definovany tak ako
tu ten BSRRL, t.j. ako 16-bitovy. Jeden nikdy nevie, a ja 'F3 nepouzivam.

Mimochodom, pri robeni Cube mali genialny napad vsetko zmenit, takze v
headeri z CubeF4 je tato struktura takto:
typedef struct
{
  __IO uint32_t MODER;    /*!< GPIO port mode register,              
Address offset: 0x00      */
  __IO uint32_t OTYPER;   /*!< GPIO port output type register,       
Address offset: 0x04      */
  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,      
Address offset: 0x08      */
  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register, 
Address offset: 0x0C      */
  __IO uint32_t IDR;      /*!< GPIO port input data register,        
Address offset: 0x10      */
  __IO uint32_t ODR;      /*!< GPIO port output data register,       
Address offset: 0x14      */
  __IO uint32_t BSRR;     /*!< GPIO port bit set/reset register,     
Address offset: 0x18      */
  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register,
Address offset: 0x1C      */
  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,    
Address offset: 0x20-0x24 */
} GPIO_TypeDef;


No ano, niekomu treba silno tresnut po prstoch klavesnicou.

K anonymnym unionom a MISRE a spol. sa na tomto mieste nejdem vyjadrovat (v
tom mojom prepisanom headri som ten union bez vahania pouzil, ale s
vedomim, ze ten header je moj a nepotrebujem aby bol prenositelny a
MISRA-compliant).

Toto ale s Vasim problemom nesuvis.

-----

Chodte do RM a vsimnite si poznamku pod popisom toho BSRR registra:

Note: If both BSx and BRx are set, BSx has priority.

Z toho vyplyva, ze pri takychto "prehadzanych" pinoch sa da do horneho
halfwordu BSRR dat konstanta ako maska, a do dolneho halfwordu
"rozhadzana" verzia "zdrojoveho" slova, co sa zase da niekedy dost
efektivne riesit tabulkou. Nie je to univerzalne lepsie riesenie, ale
jedno z tych co stoja za zvazenie.

-----
Datova bariera je mozno dobry sposob na "o nieco dlhsi kratky delay",
naviac dava istotu ze sa tie dva zapisy separuju - ale u STM ta istota je
uz dana tym ze GPIO (ako aj drviva vacsina ostatnych periferii, ak nie
vsetky) su namapovane v oblasti ktora je oznacena "Device", t.j.
"bufferable, non-cacheable"; ten druhy atribut by mal zabezpecit, ze sa
dva zapisy na tu istu adresu nespajaju.

Instrukcnu barieru by som vsak ja osobne na delay nepouzil, lebo by som sa
obaval, ze jej efekt co sa tyka oneskorenia zavisi od polohy kodu voci
riadkom pamate a aktualnemu stavu jumpcache a prefetch bufra na strane
FLASH - hoci toto je mozno neopodstatnena obava.


----- 

Vas zakladny problem je mozno v nedodrzani setup-hold casov toho displeja,
t.j. casovanie zmeny dat voci relevantnym hranam
read/write/chipselect/cojaviemcoho. Jednak tam mate zrejme pomerne dlhe
cesty po Nucleu a nasledne po tej doske displeja, potom akesi buffre na
tej doske, o ktorych ste sa ani nezmienili; no a ako bonus, netusite, aky
kontroler pouziva. Inaksie povedane, ak mate "nejaky" problem (t.j.
neviete ho dostatocne presne popisat), a riesite ho "nejako" (nie je Vam
uplne jasny vztah medzi C zdrojakom a vyslednym casovanim), tak dostanete
"nejaky" vysledok.

Zacal by som studiom casovania niekolkych kandidatov na ten kontroler;
odhadom, co mozu urobit tie delaye a tie buffre; a pridanim delayov na
miesta kde treba zarucit oneskorenia, radsej viac nez menej; pripadne
priamo prepisanim celych kritickych sekvencii do asm.

wek


PS. Pouzitie tych rychlejsich 32-bitov prinasa niekedy necakane problemy
takehoto druhu, t.j. ze su prirychle a presne casovanie sa dosahuje
relativne tazko. Napr. riadenie HD44780-kompatibilneho LCD, co v 8-bitoch
bolo kratke cvicenie o par NOPoch, sa zrazu premenilo na pomerne rozsiahlu
sagu o timeroch, DMA a preruseniach...




----- Original Message ---------------

>Koukam, casto, ale z tohodle nic moc relevantniho nevykoukam.  Proste je 
>BSRR 32b stejne jako BRR kde je vyuzita jen spodni pulka.
>polozka struktury je volatile a uint32_t, cekal jsem, ze s tim nebudou 
>problemy.
>
>typedef struct
>{
>   __IO uint32_t MODER;        /*!< GPIO port mode 
>register,               Address offset: 0x00      */
>   __IO uint32_t OTYPER;       /*!< GPIO port output type 
>register,        Address offset: 0x04      */
>   __IO uint32_t OSPEEDR;      /*!< GPIO port output speed 
>register,       Address offset: 0x08      */
>   __IO uint32_t PUPDR;        /*!< GPIO port pull-up/pull-down 
>register,  Address offset: 0x0C      */
>   __IO uint32_t IDR;          /*!< GPIO port input data 
>register,         Address offset: 0x10      */
>   __IO uint32_t ODR;          /*!< GPIO port output data 
>register,        Address offset: 0x14      */
>   __IO uint32_t BSRR;         /*!< GPIO port bit set/reset 
>register,      Address offset: 0x1A */
>   __IO uint32_t LCKR;         /*!< GPIO port configuration lock 
>register, Address offset: 0x1C      */
>   __IO uint32_t AFR[2];       /*!< GPIO alternate function 
>registers,     Address offset: 0x20-0x24 */
>   __IO uint32_t BRR;          /*!< GPIO bit reset 
>register,               Address offset: 0x28 */
>}GPIO_TypeDef;
>
>Dne 04.11.2017 v 9:57 Jan Waclawek napsal(a):
>>> A ten registr BSRR se da pouzivat i sestnactibitove?
>> TAK SA UZ POZRITE DO TOHO **** HEADERU!
>>
>> wek
>>
>> _______________________________________________
>> HW-list mailing list  -  sponsored by www.HW.cz
>> Hw-list at list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>
>
>_______________________________________________
>HW-list mailing list  -  sponsored by www.HW.cz
>Hw-list at list.hw.cz
>http://list.hw.cz/mailman/listinfo/hw-list



Další informace o konferenci Hw-list