[ foxhunter1 @ 02.12.2017. 14:54 ] @
Pokusava ovaj chika, sa krstenicom koja je odavno pozutela i skoro 6 decenija stara, da predje sa basic na C kompajlere.
Pa se onda cudim sto ce nesto pre uci pozadi, nego uglavu .
Salu na stranu, odavno je meni jasno zasto se u skolu ide kad se ide, a ne u mojim godinama... no sta je tu je.

LM, u raznim PIC basicima je bilo moguce da definisem red (array), a da posle na pojedine clanove napravim alijas, sto mi je derasticno olaksavalo zivot.

Evo primera is basic-a:
Code:

Dim MyArray[10] as byte  ' niz od 10 bajtova

Dim MyWordVar1 as word at MyArray#2    ' MyWordVar1 je duzine 2 bajta (word) i pocinje na poziciji MyArray[2]
Dim MyByteVar1 as byte at MyArray#4    ' MyByteVar1 je duzine  1 bajta (byte) i pocinje na poziciji MyArray[4]
.
.
itd


Ako je moguce u Basic-u, sigurno je moguce i u C-u... samo ne znam kako . Trazio kod gugleta i nikako da nadjem, verovatno zato sto nisam znao
kako da trazim. Pomagajte drugovi...

[ goran_68 @ 02.12.2017. 15:41 ] @
Ne možeš direktno promenljivu MyWordVar1 koja je dužine dva bajta da smestiš u niz koji je definisan kao niz promenljivih dužine jednog bajta.

niz bi bio:
unsigned char MyArray[10];

a promenljive:
unsigned int MyWordVar1;
unsigned char MyByteVar1;

Može da se izvede drugačije ali ovako direktno ne.
[ Branimir Maksimovic @ 02.12.2017. 16:20 ] @
Kod C, koristis pointere.

char myarray[10];
short* mywordvar1 = (short*)&myarray[2]; // adresa koju kastujes u odgovarajuci tip
char* mybytevar1 = &myarray[4]; // ovde ne treba cast posto je isti tip, dakle obe varijable su pointeri
[ foxhunter1 @ 02.12.2017. 16:21 ] @
Hvala na odgovoru.

Da pojasnim za sta sam tako nesto koristio. Iz spoljasnjeg sveta je, serijskom komunikacijom, stizao u navedenom slucaju,
niz od 10 bajtova. U tih 10 bajtova je sa PCja slato npr 3 word promenljive i 4 bajt promenljive, sto mu u finalnom skoru
izadje total od 10 bajtova (3x2 + 4x1).
U ovim bejzik kompajlerima je bilo moguce da se napravi 'modifier', prakticno pointer na odredjeni clan niza, tako da sam
mogao direktno da pristupam ovim mojim word ili bajt varijablama, a ne da ih preracunavam po sistemu:

MyWordVar1 = MyArray[2]<<8 + MyArray[3] (polazeci od toga da je u nizu ide HiByte, pa iza njega LoBwyte)

Nadam se da sam sada malo pojasnio moje pitanje (i potrebe ) i da ce valjda sada 'all mighty C' moci ono sto moze omaleni
basic.

A i sta ce meni, da se u ovim godinama, zahebavam sas ARMici i C-ovi

ps. Moj odgovor je bio namenjen za 'goran_68'. Sada videh da smo Branimir i ja pisali u skoro istom momentu. Branimire,
rekao bih da je to to, i kad procitas ovo moje sadasnje pisanije molim te da potvrdis ili opovrgnes.

Hvala svima.
[ mikikg @ 02.12.2017. 20:56 ] @
Citat:
foxhunter1

U ovim bejzik kompajlerima je bilo moguce da se napravi 'modifier', prakticno pointer na odredjeni clan niza, tako da sam
mogao direktno da pristupam ovim mojim word ili bajt varijablama, a ne da ih preracunavam po sistemu:

MyWordVar1 = MyArray[2]<<8 + MyArray[3] (polazeci od toga da je u nizu ide HiByte, pa iza njega LoBwyte)



To se moze odraditi preko unija, recimo ovakva neka univerzalna varijanta (zatrebace posto se na ARM sve barata sa 32bit):

Code:



//definicija unije (a.k.a konventer 32bit<>2*16bit<>4*8bit)
union unionU32 { //union=kljucna rec, unioU32=ime definicije
  uint32_t bit32;
  uint16_t bit16[2];
  uint8_t  bit8[4];
};

void nesto(void) {
   
    union unionU32 myU32;  //definisi nasu instancu unije pod imenom myU32
   
    myU32.bit32=0; // pocetna vrednost
   
    myU32.bit8[0] = 0xAB; //dodeli nesto u nizi nibl
    myU32.bit8[1] = 0x12; //dodeli nesto u visi nibl
   
    myU32.bit16[0]; //ovde je vrednost 0x12AB
    myU32.bit32;    //ovde je vrednost 0x000012AB
   
    //...
    myU32.bit32 = 0xDCBA4321; //dodeli 32bit podatak
    myU32.bit8[0]; //= 0x21
    myU32.bit8[1]; //= 0x43
    myU32.bit8[2]; //= 0xBA
    myU32.bit8[3]; //= 0xDC
   
    //..
}


[ Branimir Maksimovic @ 02.12.2017. 23:47 ] @
Ne moze preko unija, zato sto ako pises u jedan element, a citas drugi, to je undefined behavior. Naravno opalis #pragma pack(1) pa ce sve jedno raditi ;)

edit:
ali ivek postoji mogucnost da kompajler napravi nesto pametno tipa kesiranja elementa, tako da jos treba dodati i `volatile` kod definisanja varijable ...
[ mikikg @ 03.12.2017. 00:06 ] @
Moze preko unija ako se malo povede racuna i napravi "thread-safe" funkcija i ako se lepo instancira jedna unija za jednu potrebu ...

Na primer ovo moze da se koristi sa USART ili EEPROM i slicne stvari gde treba ta konverzija a svakako te funkcije su "single thread", nema tu ko da dira ili menja/cica te vrednosti osim trenutnog parceta code-a koji barata sa njima.
U globalnom scope-e su druge veriable i njih upisujemo kao rezultat ovih unija, ne mesa se unija u globalni scope memorije.
[ Branimir Maksimovic @ 03.12.2017. 00:15 ] @
Nema to veze sa threadovima. Unija ne moze tako da se koristi po pravilu C standarda ;)

edit:
a ni ovo moje nije garantovano da radi, zbog `strict aliasing rule`, pa treba videti da se kod kompajliranja iskljuci taj feature ;)
[ mikikg @ 03.12.2017. 00:41 ] @
Ovo su malo "modifikovane" varijante da bi radile pod Keil : )

U svakom slucaju rade vrlo lepo i konkretno parce code-a recimo za pisanje i citanje 32bit podatka u EE (FRAM : ) moze da se svede na ovo:
Code:

    //citanje 32bit    
    U32a.bit8[3] = FR_SPI2_8_transfer (0); //hi
    U32a.bit8[2] = FR_SPI2_8_transfer (0);
    U32a.bit8[1] = FR_SPI2_8_transfer (0);
    U32a.bit8[0] = FR_SPI2_8_transfer (0); //lo

    //pisanje 32bit
    FR_SPI2_8_transfer (U32a.bit8[3]); //hi
    FR_SPI2_8_transfer (U32a.bit8[2]);
    FR_SPI2_8_transfer (U32a.bit8[1]);
    FR_SPI2_8_transfer (U32a.bit8[0]); //lo


A threadovi imaju veze takodje samo su vezani za neke truge stvari ali kao koncept drzanja "stvari pod kontrolom" makar se one svodile na nekoliko komandi je praksa koja treba da postuje prilikom pisanja programa, konkretno ima veze gde je koja memorija postavljena, organizovana, itd itd a ko cita i pise po memoriji i sto je mnogo bitnije kako je druga stvar, ovde na bare-metal smo mnogo nisko, imamo samo interni scope u okviru funkcije i globalni scope koji dodatno moze (tj za nesto MORA) kao sto sti spomenuo da budu volatile.
Kada se u program uvede ISR prakticno njegov handler je mikro-thread koji radi nezavisno od glavnog main i ako se "cacka" memorija iz main i iz ISR a ne vodi se racuna naravno da ce da bude raznih potencialnih zaglupa :)
Takodje opet dobra praksa pisati tako programe jer multicore mikrokontroleri dolaze tj vec su dosli i bice ih sve vise, probao sam XMOS, heh, 16 procesorskih jezgra i gomila procesa stim ako ispostujes thread-safe funkcionalnost po procesoru onda mozes da nasiljis svih 16 jezgra da rade paralelno i da melje to sto je krenulo da radi :)

[Ovu poruku je menjao mikikg dana 03.12.2017. u 01:54 GMT+1]
[ Branimir Maksimovic @ 03.12.2017. 00:46 ] @
Ma vidi, volatile ti treba da natera kompajler da `unija.a `uvek procita iz RAM-a, a ne da kesira u registru. Jer ako upises `unija.b = 5`, pa citas `unija.a`, kompajler je slobodan da se ne obrati RAM-u nego da vrati kesiranu vrednost. Zato volatile, ne zbog threadova.