Changes between Version 1 and Version 2 of DigitaliE9302


Ignore:
Timestamp:
11/22/10 00:17:41 (14 years ago)
Author:
mancausoft
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DigitaliE9302

    v1 v2  
    1 Prima cosa da sapere prima di iniziare e' che le periferiche nei processori arm sono [http://it.wikipedia.org/wiki/Metodi_di_input/output#Memory-mapped_I.2FO memory mapped] quindi per accedere alle periferiche (come le digitali) basta leggere ad un indirizzo prefissato in memoria. Per conoscere l'indirizzo di memoria corretto basta leggere il datasheet del processore.
     1Prima cosa da sapere prima di iniziare è che le periferiche nei processori arm sono [http://it.wikipedia.org/wiki/Metodi_di_input/output#Memory-mapped_I.2FO memory mapped] quindi per accedere alle periferiche (come le digitali) basta leggere ad un indirizzo prefissato in memoria. Per conoscere l'indirizzo di memoria corretto basta leggere il datasheet del processore.
    22
    3 (continua...)
    4  
     3Leggendo i datasheet del processore in questione si può notare che le periferiche di I/O sono suddivise in 8 porte differenti da 8 bit ciascuno (chiamate con le lettere dalla A alla H). Alcune uscite sono assegnate a piu' device tramite multiplexer, e quindi configurabili scrivendo in un'apposita area di memoria di 32 bit chiamata device_config. Inoltre per ogni digitale si deve settare un'altra area di memoria che indica se quella digitale sara' usata come input o come output.
     4
     5Avevo letto in giro gente che usava push e pop scritte in assembler per scrivere e leggere in memoria, e io non capivo il perché, quindi ho provato a fare di testa mia e ad usare i puntatori, e tutto funziona a meraviglia ed il codice risulta IMHO molto piu' leggibile:
     6
     7
     8{{{
     9#!C
     10// Dichiaro i puntatori che dovranno puntare all'indirizzo di memoria
     11// in cui sono mappate le digitali
     12static volatile uint8_t* port[8], *portd[8];
     13
     14// Apro /dev/mem
     15int devmem = open("/dev/mem", O_RDWR|O_SYNC);
     16assert(devmem != -1);
     17
     18// Prendo la pagina di memoria relativa alle digitali
     19data_page = (unsigned long)mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
     20        MAP_SHARED, devmem, DATA_PAGE);
     21assert (&data_page != MAP_FAILED);
     22
     23// Prendo la pagina di memoria relativa alle configurazioni
     24syscon_page = (unsigned long)mmap(0, getpagesize(), PROT_READ|PROT_WRITE
     25        , MAP_SHARED, devmem, SYSCON_PAGE);
     26assert(&syscon_page != MAP_FAILED);
     27
     28// Prendo l'area di memoria relativa ai device config
     29uint32_t* deviceCfg = (uint32_t*) (syscon_page + DEVICECFG);
     30
     31
     32// Abilito la scrittura in memoria.
     33uint32_t* syscon_unlock = (uint32_t*) (syscon_page + SYSCON_UNLOCK);
     34*syscon_unlock = UNLOCK_VAL;
     35
     36//Associo ai puntatori l'area di memoria relativa alle porte digitali
     37port[0] = (uint8_t*) (data_page + PADR);
     38//[...]
     39port[7] = (uint8_t*) (data_page + PHDR);
     40
     41//Associo ai puntatori l'area di memoria relativa alla direzione delle porte digitali
     42portd[0] = (uint8_t*) (data_page + PADDR);
     43//[...]
     44portd[7] = (uint8_t*) (data_page + PHDDR);
     45
     46}}}
     47
     48E adesso non serve altro che leggere e scrivere nelle aree di memoria:
     49{{{
     50#!C
     51
     52inline void set_bit(bool src, uint8_t *dst, uint8_t bit)
     53{
     54        int value = 1 << bit;
     55        if(src)
     56                *dst |= value;
     57        else
     58                *dst &= ~value;
     59}
     60
     61inline void get_bit(uint8_t src, bool *dst, uint8_t bit)
     62{
     63        int value = 1 << bit;
     64        *dst = (src & value) >> bit;
     65}
     66int set_port_bit (uint8_t nport, bool value, uint8_t pos)
     67{
     68        if(nport < 8 && pos < 8)
     69        {
     70                set_bit(value, port[nport], pos);
     71                return 0;
     72        }
     73        return -1;
     74}
     75
     76int get_port_bit (uint8_t nport, bool* value, uint8_t pos)
     77{
     78        if(nport < 8 && pos < 8)
     79        {
     80                get_bit(*port[nport], value, pos);
     81                return 0;
     82        }
     83        return -1;
     84}
     85int set_port_dir_bit (uint8_t nport, bool value, uint8_t pos)
     86{
     87        if(nport < 8 && pos < 8)
     88        {
     89                set_bit(value, portd[nport], pos);
     90                return 0;
     91        }
     92        return -1;
     93}
     94
     95}}}
     96
     97PS: Se vi servono maggiori informazioni basta chiedere vi email: me (at) mancausoft (dot) org