este jedna dlazdicska...
Jiri LINHART
hw.jirilinhart na gmail.com
Neděle Leden 8 16:49:46 CET 2017
Nebylo by lepší v dnešní době to nechat na překladači a linkeru co s tím
sám udělá (možná to nebude nejrychlejší a nejkratší v RAM).
Zkus se pro jistotu podívat na různé překlady možná vyjdou stejně
Pro rychlost a jednoduchost zpracování použij bytes
J.L.
Dne Sun, 08 Jan 2017 01:15:06 +0100 Jan Waclawek <konfera na efton.sk>
napsal(a):
>> je tu nejak ticho tak pridam blbu otazku...
>>
>>
>> majme porty na procesore Atmega. Chcel by som niektore piny nadratovat
>> do boolean premennej, tak aby som po precitani dostal 0/1. Takisto by
>> som chcel zase niektore ine boolean premenne chcel nadratovat na
>> vystupne piny. Ako sa to v C spravne robi?
>
> Nijako.
>
> _Bool v C nie je typ, ktory by sa dal namapovat na bit. Presnejsie, v C
> nemoze existovat samostatny objekt (a tym ani typ, ktory by ten objekt
> popisoval), ktory by nepozostaval z jedneho alebo viacerych bytov (C99,
> 6.2.6.1#2).
>
> V C vsak existuje prostriedok na manipulaciu jednotlivych bitov, bitove
> polia (bitfields, resp. v norme sa to pise so spojovnikom bit-fields) v
> strukturach (struct). Pouzitie je trocha ine ako so samostatnou
> premennou,
> t.j. nemozes zapisat nieco ako PORTC_1 = 1; a musis zapisat nieco ako
> PORTC.b1 = 1; - ale tipujem, ze to by Ti az tak velmi nevadilo.
>
> Zacnime vsak s tymi portami (resp. vseobecnejsie k SFR) u AVR. Tie
> samozrejme su (mozu) byt bitovo manipulovatelne, rovnako ako u '51. V
> povodnom AVR tak ako ho A&V vymysleli, je pre SFR vyhradena oblast 64
> byte, kde samotne SFR su adresovane 0x00-0x3F - to su adresy P pouzite v
> instrukciach pre SFR. Su dve instrukcie pre nastavenie/nulovanie SFR bitu
> - SBI P,b a CBI P,b (Set resp. Clear Bit in I/O) - a dve instrukcie na
> testovanie bitu a obskocenie nasledujucej instrukcie - SBIS P,b a SBIC
> P,b
> (Skip if Bit in I/O Set resp. Cleared). Toto sa prenieslo aj do
> programovania v C s prekladacom avr-gcc - avr-gcc spociatku nevedel
> zohladnit tuto specialitu, a tak sa porty efektivne nastavovali pomocou
> makier sbi()/cbi() generujucich inline assembler - toto spominam preto,
> lebo pozostatky tych makier sa daju najst v starsich programoch ako aj v
> dokumentacii k avr-libc, a pre spatnu kompatibilitu su stale obsiahnute v
> <compat/deprecated.h>
> http://www.nongnu.org/avr-libc/user-manual/group__deprecated__items.html
> .
>
> Sucasne vsak je cela SFR oblast namapovana aj v "unifikovanej" pamati,
> ktora u klasickych AVR obsahuje na adresach 0x00 az 0x1F registre
> procesora (uzitocnost tohoto je na velmi dlhu diskusiu a tyka sa vlastne
> len tych najmensich a najstarsich Tiny), na adresach 0x20 az 0x5F
> klasicke
> bitovo adresovatelne SFR registre ako boli popisane hore (takze kazdy
> taky
> register ma vlastne dve adresy, jednu v priestore SFR (od adresy 0x00) a
> druhu v unifikovanej pamati (posunutu o 0x20). Unifikovana pamat znamena,
> ze k vsetkym prostriedkom sa da pristupovat jednou sadou instrukcii v
> jednom adresnom priestore. Unifikovana pamat je prave jedna z vlastnosti
> AVR ktora bola zamerne pritomna uz od pociatku prave kvoli pouzitiu vo
> vyssich jazykoch (na cele s C), kedze tie maju notoricky problem s
> rozmanitostou pamati (prave preto vravi pan kolega Andel, ze C pre '51 je
> Keil - C pre '51 musi totiz obsahovat rozsirenia pre viacero roznych
> pamatovych oblasti, ktorych ma '51 tak zhruba 5, inak je takmer
> nepouzitelne a urcite nie efektivne pouzitelne).
>
> Klasicky bola v AVR nad SFR oblastou umiestnena SRAM (t.j. od adresy
> 0x60).
> FLASH nebola v unifikovanej pamati (to prinasa dalsiu sadu problemov s
> konstantnymi premennymi umiestnenymi vo FLASH, toto sa vo svete avr-gcc
> prejavovalo skupinou makier a funkcii v <pgmspace.h> a s nimi spojenymi
> zvlastnostami, od urciteho casu sa to prejavuje skupinou pomenovanych
> pamatovych priestorov typu _flash) a ani EEPROM (tam sa to vsak obvykle
> ani necaka a pristupuje sa k nej dost prirodzene zvlastnymi funkciami).
> Toto sa zmenilo v xMEGA kde vznikla skutocne unifikovana pamat zahrnajuca
> vsetky prostriedky, avsak za cenu strankovania, kedze prirodzeny adresny
> priestor AVR je dost pochopitelne 16-bitovy (ta potreba vsak u FLASH
> >64kB
> tak ci tak existuje).
>
> Vratme sa vsak k SFR. Pochopitelne, v urcitom bode prestalo 64 byte pre
> vsetky SFR stacit, a v novsich, vacsich modeloch boli dodatocne SFR
> umiestnene uz len do unifikovanej pamate, nad oblast povodnych SFR t.j.
> od
> adresy 0x60 (a SRAM bola posunuta nad nove SFR, na adresu 0x100 a neskor
> aj vyssie). Tieto nove SFR uz teda neboli bitovo manipulovatelne, pre
> unifikovanu pamat take instrukcie nie su. (Mimochodom, aj v '51 je len
> pomerne mala cast SFR priestoru bitovo manipulovatelna, vsakze). Pre ne
> teda zmena bitu znamena precitat cely SFR do registra, zmodifikovat ten
> jeden bit, a zapisat naspat.
>
> Pisatelom v C/avr-gcc teda vznikli dve moznosti: bud si pamatat, pre
> ktore
> SFR sa da pouzit cbi()/sbi() a pre ktore nie, alebo prosto pouzivat pre
> vsetky SFR pristup ako k normalnej pamati (to je to PORTx |= 1 << 5
> apod.)
> aj za cenu, ze to pre tie klasicke SFR nie je optimalne. Medzicasom sa
> vsak nasiel aj dobrodinec ktory do avr-gcc doplnil optimalizaciu, ktora
> skuma, ci bitovo-manipulovana adresa je v oblasti klasickych SFR, a ak
> ano, tak pouzije cbi/sbi, co umoznilo standardizovat pristup k SFR ako k
> pamati a zachovat optimalitu. Tym padom sa stali makra cbi()/sbi()
> zastarale (deprecated) a oficialne doporuceny pristup je popisany tu:
> http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html
>
> Ono to PORTB |= _BV(PB1); nie je omnoho zrozumitelnejsie ci citatelnejsie
> ako PORTB |= (1 << PB1), takze si to mnohi aj tak spestruju svojimi
> makrami. My vo firme napriklad mame taky postup, ze si na zaciatku
> projektu porobime makra typu
> #define SetLED1() PORTB |= (1 << 3)
> #define ClrLED1() PORTB &= ~(1 << 3)
> #define GetButton1() ((PINB & (1 << 5)) == 0)
> a podobne - je to mozno trocha tukania, ale potom zvysok programu je
> relativne dobre citatelny.
>
> Ale aby som sa po tejto obrovskej okluke vratil uplne na zaciatok, je
> mozne
> urobit nieco taketo (http://bit.ly/2i5mMXr ):
>
> #include <stdint.h>
> #include <avr/io.h>
>
> typedef union __attribute__((packed)) {
> uint8_t all;
> struct __attribute__((packed)) { uint8_t nibH : 4, nibL : 4; };
> struct __attribute__((packed)) { _Bool lsb: 1; uint8_t : 6; _Bool msb:
> 1;
> };
> struct __attribute__((packed)) { _Bool b0: 1, b1: 1, b2: 1, b3: 1, b4:
> 1,
> b5: 1, b6: 1, b7: 1; };
> } bit8;
>
>
> #define SFR2BITFIELD8(sfr) (*(volatile bit8 *)(&(sfr)))
>
> #define pinC SFR2BITFIELD8(PINC)
> #define portC SFR2BITFIELD8(PORTC)
> #define pinF SFR2BITFIELD8(PINF)
> #define portF SFR2BITFIELD8(PORTF)
>
>
> int main(void) {
> if (PINC & (1 << 4)) {
> PORTC |= (1 << 5);
> }
>
> if (pinC.b4) {
> portC.b5 = 1;
> }
>
>
> if (PINF & (1 << 4)) {
> PORTF |= (1 << 5);
> }
> if (pinF.b4) {
> portF.b5 = 1;
> }
>
> portC.b5 = !pinC.b4;
>
> portC.b5 = ~pinC.b4;
> }
>
> z coho relevantna cast sa prelozi ako
>
>
> int main(void) {
> if (PINC & (1 << 4)) {
> be: 9c 99 sbic 0x13, 4 ; 19
> PORTC |= (1 << 5);
> c0: ad 9a sbi 0x15, 5 ; 21
> }
>
> if (pinC.b4) {
> c2: 9c 99 sbic 0x13, 4 ; 19
> portC.b5 = 1;
> c4: ad 9a sbi 0x15, 5 ; 21
> }
>
>
> if (PINF & (1 << 4)) {
> c6: 04 9b sbis 0x00, 4 ; 0
> c8: 05 c0 rjmp .+10 ; 0xd4 <main+0x16>
> PORTF |= (1 << 5);
> ca: 80 91 62 00 lds r24, 0x0062
> ce: 80 62 ori r24, 0x20 ; 32
> d0: 80 93 62 00 sts 0x0062, r24
> }
> if (pinF.b4) {
> d4: 04 9b sbis 0x00, 4 ; 0
> d6: 05 c0 rjmp .+10 ; 0xe2 <main+0x24>
> portF.b5 = 1;
> d8: 80 91 62 00 lds r24, 0x0062
> dc: 80 62 ori r24, 0x20 ; 32
> de: 80 93 62 00 sts 0x0062, r24
> }
>
> portC.b5 = !pinC.b4;
> e2: 83 b3 in r24, 0x13 ; 19
> e4: 82 95 swap r24
> e6: 8f 70 andi r24, 0x0F ; 15
> e8: 80 95 com r24
> ea: 81 70 andi r24, 0x01 ; 1
> ec: 82 95 swap r24
> ee: 88 0f add r24, r24
> f0: 80 7e andi r24, 0xE0 ; 224
> f2: 95 b3 in r25, 0x15 ; 21
> f4: 9f 7d andi r25, 0xDF ; 223
> f6: 98 2b or r25, r24
> f8: 95 bb out 0x15, r25 ; 21
>
> portC.b5 = ~pinC.b4;
> fa: 83 b3 in r24, 0x13 ; 19
> fc: ad 9a sbi 0x15, 5 ; 21
>
>
> (domaca uloha: vysvetlit preklad posledneho riadku)
>
> wek
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
--
Vytvořeno poštovní aplikací Opery: http://www.opera.com/mail/
Další informace o konferenci Hw-list