2017-06-01 1 views
2

Ich versuche Register auf meinem ARM9 (SAM9X25) im Anschluss an diese Schritte zu lesen und schreiben: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html
ich mit dem folgenden Code beendet:WRITE und READ Register in Linux auf ARM

#include "stdio.h" 

#define PIO_WPMR_BANK_D      0xFFFFFAE4 // PIO Write Protection Mode Register Bank D 
#define PIO_PUER_BANK_D      0xFFFFFA64 // PIO Pull-Up Enable Register Bank D 
#define PIO_PUSR_BANK_D      0xFFFFFA68 // PIO Pull-Up Status Register Bank D 

#define MASK_LED7       0xFFDFFFFF // LED7 Mask 
#define DESABLE_WRITE_PROTECTION_BANK_D  0x50494F00 // Desable write protection Bank D 

int main(void) { 
    printf("test"); 
    unsigned int volatile * const register_PIO_WPMR_BANK_D = (unsigned int *) PIO_WPMR_BANK_D; 

    unsigned int volatile * const register_PIO_PUSR_BANK_D = (unsigned int *) PIO_PUSR_BANK_D; 

    unsigned int volatile * const port_D = (unsigned int *) PIO_PUER_BANK_D; 

    *register_PIO_WPMR_BANK_D = DESABLE_WRITE_PROTECTION_BANK_D; 

    *port_D = *register_PIO_PUSR_BANK_D & MASK_LED7; 

    return 0; } 


ich zusammengestellt Cross my Code in Ubuntu 16.04 wie so arm-linux-gnueabi-gcc gpio.c -o gpio
Aber ich habe eine Segmentation Fault kurz nach der printf während der Ausführung des Programms auf meiner Platine.
Ich weiß, dass die Adressen richtig sind ... Warum habe ich diesen Fehler?
Ist es der gute Weg?
Vielen Dank für Ihre Hilfe!

LÖSUNG:
Danke ich @vlk könnte es funktioniert! Hier ist ein kleines Beispiel für Makeln eine LED:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <fcntl.h> 


#define handle_error(msg) \ 
      do { perror(msg); exit(EXIT_FAILURE); } while (0) 

#define _PIOD_BANK_D       0xA00 

#define _PIO_OFFSET        0xFFFFF000 

/* When executing this on the board : 
    long sz = sysconf(_SC_PAGESIZE); 
    printf("%ld\n\r",sz); 
    We have 4096. 
*/ 
#define _MAP_SIZE       0x1000 // 4096 

#define _WPMR_OFFSET      0x0E4 // PIO Write Protection Mode Register Bank D 

#define _PIO_ENABLE       0x000 
#define _PIO_DISABLE      0x004 
#define _PIO_STATUS       0x008 
#define _OUTPUT_ENABLE      0x010 
#define _OUTPUT_DISABLE      0x014 
#define _OUTPUT_STATUS      0x018 
#define _FILTER_ENABLE      0x020 
#define _FILTER_DISABLE      0x024 
#define _FILTER_STATUS      0x028 
#define _OUTPUT_DATA_SET     0x030 
#define _OUTPUT_DATA_CLEAR     0x034 
#define _OUTPUT_DATA_STATUS     0x038 
#define _PIN_DATA_STATUS     0x03c 
#define _MULTI_DRIVER_ENABLE    0x050 
#define _MULTI_DRIVER_DISABLE    0x054 
#define _MULTI_DRIVER_STATUS    0x058 
#define _PULL_UP_DISABLE     0x060 
#define _PULL_UP_ENABLE      0x064 
#define _PULL_UP_STATUS      0x068 
#define _PULL_DOWN_DISABLE     0x090 
#define _PULL_DOWN_ENABLE     0x094 
#define _PULL_DOWN_STATUS     0x098 

#define _DISABLE_WRITE_PROTECTION   0x50494F00 // Desable write protection 

#define LED_PIN         21 

int main(void) { 

    volatile void *gpio_addr; 
    volatile unsigned int *gpio_enable_addr; 
    volatile unsigned int *gpio_output_mode_addr; 
    volatile unsigned int *gpio_output_set_addr; 
    volatile unsigned int *gpio_output_clear_addr; 
    volatile unsigned int *gpio_data_status_addr; 
    volatile unsigned int *gpio_write_protection_addr; 

    int fd = open("/dev/mem", O_RDWR|O_SYNC); 
    if (fd < 0){ 
     fprintf(stderr, "Unable to open port\n\r"); 
     exit(fd); 
    } 


    gpio_addr = mmap(NULL, _MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PIO_OFFSET); 


    if(gpio_addr == MAP_FAILED){ 
     handle_error("mmap"); 
    } 


    gpio_write_protection_addr = gpio_addr + _PIOD_BANK_D + _WPMR_OFFSET; 

    gpio_enable_addr = gpio_addr + _PIOD_BANK_D + _PIO_ENABLE; 

    gpio_output_mode_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_ENABLE; 

    gpio_output_set_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_SET; 

    gpio_output_clear_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_CLEAR; 

    gpio_data_status_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_STATUS; 


    *gpio_write_protection_addr = _DISABLE_WRITE_PROTECTION; 

    *gpio_enable_addr = 1 << LED_PIN; 
    *gpio_output_mode_addr = 1 << LED_PIN; // Output 


    // If LED 
    if((*gpio_data_status_addr & (1<<LED_PIN)) > 0){ 
     *gpio_output_clear_addr = 1 << LED_PIN; 
    }else{ 
     *gpio_output_set_addr = 1 << LED_PIN; 
    } 

    return 0; 
} 

EDIT:
Antwort für die 3) in den Kommentaren. Sie müssen die mmap ändern und die Verabredungen wie so, wenn Sie es möchten die Versetzungen arbeiten mit allen (dh: mmap example):

#define _PIO_OFFSET       0xFFFFFA00 // Instead of 0xFFFFF000 
#define _MAP_SIZE       0x1000 // 4096 
#define _MAP_MASK       (_MAP_SIZE - 1) 
#define _PA_OFFSET       _PIO_OFFSET & ~_MAP_MASK 

Und die mmap:

gpio_addr = mmap(NULL, _MAP_SIZE + _PIO_OFFSET - _PA_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PA_OFFSET); 

Und für das Stelldichein:

gpio_enable_addr = gpio_addr + _PIO_OFFSET - (_PA_OFFSET) + _PIO_ENABLE; 
+0

diese lesen: [Zugriff auf physische Adresse von Userspace] (https://stackoverflow.com/questions/12040303/accessing-physical-address-from-user-space) –

+1

Sie nicht zugreifen können sie direkt aus dem anwendungsraum wie das können sie mmap verwenden, um ein loch durch das os zu schlagen, oder schreiben sie einen kernel treiber oder bare metal, aber wie geschrieben sollte es segeln fehler. –

Antwort

2

Sie können Register nicht direkt zugreifen, da Linux MMU verwenden und diese für Ihre Anwendung virtueller Adressraum schaffen, die MCU-Adressraum und Zugang ou als physischer anders Dieser virtuelle Adressraum verursacht einen Segmentierungsfehler.

einzige Weg, diese Register in Linux zugreifen (wenn Sie nicht Kernel-Treiber nicht möchten, schreiben) ist-Datei zu öffnen/dev/mem als Datei und wo es sich mit mmap

Zum Beispiel habe ich kleine Python-Bibliothek haben für den Zugriff GPIO registriert auf Atmel SAM MCU gpiosam. Sie können inspirieren und Portierung auf C.

+0

Vielen Dank @vlk! Ich könnte eine richtige mmap schreiben! Aber ich habe ein paar Fragen zu deiner Bibliothek. ** 1) ** Ich verstehe nicht wirklich ' Gpio._mm [self._addr + registrieren: self._addr + Register + 4] = struct.pack (' Tagadac

+0

** 2) ** Im Datenblatt können wir lesen: 'Das Lesen einer in PIO_PUSR bedeutet, dass das Hochziehen deaktiviert ist und das Lesen von eine Null bedeutet, dass das Pull-up aktiviert ist. Also sollte 'return (self._reg_get (Gpio._PULL_DOWN_STATUS) & self._bitval)> 0 '' return ** not ** sein (self._reg_get (Gpio._PULL_UP_STATUS) & self._bitval)> 0' oder ähnliches nein? Auf diese Weise haben Sie, wenn das Bit-Register "1" ist, stattdessen "FALSE" und "TRUE". Nein? (und dasselbe für Pull-Down) – Tagadac

+0

** 3) ** Warum, wenn '_PIO_OFFSET' von' 0xFFFFF000' nach '0xFFFFFA00' (Bank D) geändert wird, ergibt sich' mmap: Invalid argument'? Danke für Ihre Hilfe ! – Tagadac

1

busybox devmem

busybox devmem ist ein winziges CLI-Dienstprogramm, das /dev/mem mmaps.

Sie können es in Ubuntu bekommen mit: sudo apt-get install Busybox

Verbrauch: Lesen, 4 Bytes von der physikalischen Adresse 0x12345678:

sudo busybox devmem 0x12345678 

schreiben 0x9abcdef0 an diese Adresse:

sudo busybox devmem 0x12345678 w 0x9abcdef0 

Sehen Sie dies für ein paar Tipps zum Testen: Accessing physical address from user space

Auch bei erwähnt: https://unix.stackexchange.com/questions/4948/shell-command-to-read-device-registers

+0

Schön, danke! Ich werde es später testen :) – Tagadac

Verwandte Themen