C in različne definicije

Vse o programiranju na in za PC

Moderatorji: Kroko, tilz0R

C in različne definicije

OdgovorNapisal/-a Kroko » 18 Okt 2017, 21:55

Imam dva verziji boarda na katerem bi rad poganjal isti software. Razlika med njimi je samo, kje so določeni pini.

V main.c ugotovim za katero verzijo gre. Na podlagi tega bi rad uporabil ustrezen #include. Absolutno mi je jasno, na tak način, kot je spodaj, ne gre. Obstaja kakšna elegantna rešitev?

Koda: Izberi vse
version_1000.h
#define PIN 1000

version_2000.h
#define PIN 2000

main.c

if (autodetect())
#include "version_1000.h"
else
#include "version_2000.h"

printf("%d", PIN);
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4809
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 687 krat
Prejel zahvalo: 1670 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C in različne definicije

OdgovorNapisal/-a VolkD » 18 Okt 2017, 22:19

Tisti if naj bi se izvedel v realnem času, #ukazi pa v času pred prevajanje. Torej ne bo šlo brez da bi imel kodo za oba borda v obeh bordih.
Dokler bodo ljudje mislili, da živali ne čutijo bolečine, bodo živali čutile, da ljudje ne mislijowww.S5tech.net
Uporabniški avatar
VolkD
Administratorji strani
 
Prispevkov: 42599
Pridružen: 29 Dec 2014, 20:49
Kraj: Kačiče (Divača)
Zahvalil se je: 9303 krat
Prejel zahvalo: 5274 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 111

Re: C in različne definicije

OdgovorNapisal/-a gumby » 19 Okt 2017, 06:24

#ifdef / #define lahko uporabiš samo, če hočeš imet en source in ga prevedeš v dva programa.
Če bi rad imel samo en program, pa lahko uporabiš pointerje na registre in spremenljivke za posamezne bite. In potem daš *port |= 1<<bit
my brain hurts
Uporabniški avatar
gumby
 
Prispevkov: 2591
Pridružen: 14 Jan 2015, 19:49
Kraj: Lendava
Zahvalil se je: 109 krat
Prejel zahvalo: 612 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 63

Re: C in različne definicije

OdgovorNapisal/-a Kroko » 19 Okt 2017, 08:53

Do sedaj, ko je bil samo en board sem imel narejeno z define. Sedaj pa imam dva in drugi ima nekatere pine drugje.
Vem, da z #define ne bo šlo. V skrajni verziji imam lahko dva sourca. Iščem pa elegantno rešitev z enim sourcem, ki ne bo vplivala na hitrost izvajanja.
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4809
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 687 krat
Prejel zahvalo: 1670 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C in različne definicije

OdgovorNapisal/-a peterp » 19 Okt 2017, 09:09

Moje razmišljanje:
Koda: Izberi vse
int board;

int get_pin(int board) {
  if (board == 1) {
    #include "version_1000.h"
    return PIN;
    #undef PIN
  } else if (board == 2) {
    #include "version_2000.h"
    return PIN;
    #undef PIN
  } else
    return 0;
}

int autodetect(char *argv[]) {
  return atoi(argv[1]);
}

#define PIN get_pin(board)

int main(int argc, char *argv[]) {
  board = autodetect(argv);
  printf("main board: %d\n", board);
  printf("       PIN: %d\n", PIN);
  return 0;
}
/*
$ ./test 1
main board: 1
       PIN: 1000

$ ./test 2
main board: 2
       PIN: 2000
*/


Razmišljam pa še o boljši rešitvi...
peterp
 
Prispevkov: 663
Pridružen: 23 Feb 2015, 14:52
Kraj: Maribor
Zahvalil se je: 171 krat
Prejel zahvalo: 112 krat
Uporabnika povabil: gumby
Število neizkoriščenih povabil: 114

Re: C in različne definicije

OdgovorNapisal/-a peterp » 19 Okt 2017, 09:51

Pa še prepis pinov v spremenljivko:
Koda: Izberi vse
int board;
int pins[2][3];

int autodetect(char *argv[]) {
  #include "version_1000.h"
  pins[0][0] = PIN1;
  pins[0][1] = PIN2;
  pins[0][2] = PIN3;
  #undef PIN1
  #undef PIN2
  #undef PIN3

  #include "version_2000.h"
  pins[1][0] = PIN1;
  pins[1][1] = PIN2;
  pins[1][2] = PIN3;
  #undef PIN1
  #undef PIN2
  #undef PIN3

  return atoi(argv[1]);
}

#define PIN1 pins[board-1][0]
#define PIN2 pins[board-1][1]
#define PIN3 pins[board-1][2]

int main(int argc, char *argv[]) {
  board = autodetect(argv);

  printf("main board: %d\n", board);
  printf("      PIN1: %d\n", PIN1);
  printf("      PIN2: %d\n", PIN2);
  printf("      PIN3: %d\n", PIN3);
  return 0;
}
/*
$ ./test 1
main board: 1
      PIN1: 1001
      PIN2: 1002
      PIN3: 1003

$ ./test 2
main board: 2
      PIN1: 2001
      PIN2: 2002
      PIN3: 2003
*/
peterp
 
Prispevkov: 663
Pridružen: 23 Feb 2015, 14:52
Kraj: Maribor
Zahvalil se je: 171 krat
Prejel zahvalo: 112 krat
Uporabnika povabil: gumby
Število neizkoriščenih povabil: 114

Re: C in različne definicije

OdgovorNapisal/-a marko » 19 Okt 2017, 09:59

To kar je gumby povedal, je pomoje najbolj optimalna rešitev. Odvisno sicer od arhitekture, ampak recimo, da so vsi porti uint8_t (oz. najbrž kaj drugega na 32 bitniku) in če imaš za vsak par port+pin+ddr, svojo spremenljivko (tako kot imaš sedaj z define), ne bi smel imeti težav. Ob zagonu programa enostavno incializiraš vse te spremenljivke in potem operiraš s tem naprej. Da je malo bolj pregledno, lahko daš v struct in s tistim delaš.

Kaj pa je točno razlog, da želiš imeti isto kodo na obeh devicih? Da ti ni treba delati dve verziji firmwara pri upgradih in da strankam ni treba gledat kaj rabijo ali kaj drugega?
Če ti v življenju ne gre in si nesrečen, se spomni na lastnike Renaultov.
marko
 
Prispevkov: 1234
Pridružen: 18 Jan 2015, 02:00
Zahvalil se je: 144 krat
Prejel zahvalo: 169 krat
Uporabnika povabil: VolkD
Število neizkoriščenih povabil: 89

Re: C in različne definicije

OdgovorNapisal/-a Kroko » 19 Okt 2017, 11:53

Takole imam definirane pine:
Koda: Izberi vse
#define AUX1_HWPORT       0x7
#define AUX1_HWPIN          7
#define AUX1_HWFUNC         FUNC0
#define AUX1_PORT             3
#define AUX1_PIN            (1UL<<15)
#define AUX1               AUX1_PORT, AUX1_PIN


Dva firmwareta bi po nepotrebnem povečala kompleksnost in sčasoma bi postalo neobvladljivo.
http://www.planet-cnc.com poskakuješ na eni nogi in žvižgaš alpske podoknice Kroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 4809
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 687 krat
Prejel zahvalo: 1670 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 255

Re: C in različne definicije

OdgovorNapisal/-a sundancer » 19 Okt 2017, 11:54

Pomoje je Gumby mislil nekaj takega.

Koda: Izberi vse
#ifdef BOARD1
#include "version_1000.h"
#endif

#ifdef BOARD2
#include "version_2000.h"
#endif


Potem pa pri kompajlerju dodas -DBOARD1 ali -DBOARD2 (za gcc in cpp vem da takole sprejmeta definicijo makroja)
Dyslexic man walks into a bra.
Uporabniški avatar
sundancer
 
Prispevkov: 602
Pridružen: 16 Jan 2015, 23:36
Kraj: Domžale
Zahvalil se je: 219 krat
Prejel zahvalo: 332 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 44

Re: C in različne definicije

OdgovorNapisal/-a tilz0R » 19 Okt 2017, 12:08

Predlagam da narediš const static tabelo pinov in portov in se kasneje na njo nanašaš.
Recimo:

Koda: Izberi vse
typedef struct {
     gpioport* p;
     uint32_t pin;
} pindef_t;


Potem pa naredi dva arraya za vsak board in imej za isto funkcionalnost pina na istem mestu v array-ju tvoje elemente.

Koda: Izberi vse
//Board 1
static const pindef_t board1_pins = {
 {GPIOA, PIN0},
 {GPIOA, PIN1},
};
//Board 2
static const pindef_t board2_pins = {
 {GPIOA, PIN3},
 {GPIOA, PIN4},
};


Narediš define z pozicijami na array-u

Koda: Izberi vse
#define LCD_PIN    0
#define LED_PIN    1


Narediš funkcijo:

Koda: Izberi vse
const pindef_t* get_pin(size_t index) {
    if (board == 1) return board1_pins[index];
    else return board2_pins[index];
}


To je v primeru, da hočeš single HEX poganjati na več boardih
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1830
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 230 krat
Prejel zahvalo: 517 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: C in različne definicije

OdgovorNapisal/-a mujo » 19 Okt 2017, 12:54

Jaz sem pred časom delal podobno zadevo (podpora dveh HW z enim FW).

Nasvet bi bil enak kot je tilz0R napisal.
Struktura pinov/portov in samo spremeniš kazalec na to strukturo.
Enako potem narediš z HW specific funkcijami (pointer na funkcijo).

Priporočam tudi, da premisliš kako boš ugotovil katero verzijo HW imaš (en GPIO vežeš high, ali kaj podobnega).
mujo
 
Prispevkov: 734
Pridružen: 21 Jan 2015, 10:50
Kraj: MB
Zahvalil se je: 1 krat
Prejel zahvalo: 150 krat
Uporabnika povabil: VolkD
Število neizkoriščenih povabil: 18

Re: C in različne definicije

OdgovorNapisal/-a gumby » 19 Okt 2017, 16:42

tilz0R je napisal/-a:Predlagam da narediš const static tabelo pinov in portov in se kasneje na njo nanašaš.

Tole se vsaj na AVR prevede v en sbi/cbi ukaz, če vse pravilno narediš. Morajo pa biti vsi klici direktni, torej nekaj[1] in ne nekaj[x]. Slednji sicer tudi deluje, vendar bo iz njega nastalo več ukazov in s tem počasnejši program.
my brain hurts
Uporabniški avatar
gumby
 
Prispevkov: 2591
Pridružen: 14 Jan 2015, 19:49
Kraj: Lendava
Zahvalil se je: 109 krat
Prejel zahvalo: 612 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 63

Re: C in različne definicije

OdgovorNapisal/-a tilz0R » 19 Okt 2017, 21:03

To se strinjam. Vendar on se ne more direktno na array strukture "vezat", saj ne ve katera je prava. Če pa vrne pointer na strukturo v začetni fazi main-a, pa tudi prevajalnik ne bo kar "hardcode-al" naslova v asm, ker ne ve kater pointer bo vrnjen.

V vsakem primeru bo performance manjši, če hočeš imeti variable pine.
Knowledge sharing is people' caring., T. MAJERLE
Uporabniški avatar
tilz0R
 
Prispevkov: 1830
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 230 krat
Prejel zahvalo: 517 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255


Vrni se na Programski jeziki

Kdo je na strani

Po forumu brska: 0 registriranih uporabnikov in 1 gost