Forum: Mikrocontroller und Digitale Elektronik Auf feste Adresse im embedded Linux Schreiben


von Tobias W. (wagnertobse)


Lesenswert?

Hallo,

Ich versuche in einen embedded Linux auf einen ARROW SoCkit auf eine 
feste Adresse (0x00010080) zu schreiben. Um eine virtuelle Adresse mit 
der gewünschten Adresse zu erstellen nutze ich mmap. Leider habe ich im 
bereich speicher zugriff unter Linux nicht viel erfahrungen...

Schreibe im mit folgenden Code auf die Adresse?
1
#include "hwlib.h"
2
#include "socal/socal.h"
3
#include "socal/hps.h"
4
#include "socal/alt_gpio.h"
5
#include "system.h"
6
7
8
int main(){
9
  void *virtual_base;
10
  void *adresse = 0x00010080;
11
  unsigned int fd;
12
  unsigned int in = 0xFFFF9FFF;
13
  unsigned int out;
14
  if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
15
    printf( "ERROR: could not open \"/dev/mem\"...\n" );
16
    return( 1 );
17
  }
18
19
  virtual_base = mmap( adresse, 32, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd , 0 );
20
21
  if( virtual_base == MAP_FAILED ) {
22
    printf( "ERROR: mmap() failed...\n" );
23
    close( fd );
24
    return( 1 );
25
  }
26
27
  alt_write_word( virtual_base, in );
28
29
  out = alt_read_word(virtual_base);
30
  printf("%i wurde zurueckgegeben!!",out);
31
  return 0;
32
}

von S. R. (svenska)


Lesenswert?

Was passiert bei
*virtual_base = in;
printf("%i\n", *virtual_base);
?

von Tobias W. (wagnertobse)


Lesenswert?

Theoretisch dürfte ich auf der Adresse nur schreiben können aber 
alt_red_word gibt mein auf die Adresse glegeten Wert zurück. Auf der 
Adresse sitzt eine Bridge zum FPGA, die in der Aktuellen konfiguration 
nur schreiben kann. Auf dem FPGA kommt leider nichts an :(

von ./. (Gast)


Lesenswert?

Damit ein mmap Erfolg hat, muss etwas zum 'mmap'en da sein.
Z.B. durch ein malloc.
1
  // Allocate MAP block
2
  if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
3
    printf("allocation error \n");
4
    exit (-1);
5
  }
6
7
  // Make sure pointer is on 4K boundary
8
  if ((unsigned long)gpio_mem % PAGE_SIZE)
9
    gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
10
11
  // Now map it
12
  gpio_map = (unsigned char *)mmap(
13
    (caddr_t)gpio_mem,
14
    BLOCK_SIZE,
15
    PROT_READ|PROT_WRITE,
16
    MAP_SHARED|MAP_FIXED,
17
    mem_fd,
18
    GPIO_BASE
19
    );
20
21
  if ((long)gpio_map < 0) {
22
    printf("mmap error %d\n", (int)gpio_map);
23
    exit (-1);
24
  }

von Klaus W. (mfgkw)


Lesenswert?

Tip: mit MAP_ANONYMOUS | MAP_FIXED sowie einem fd=-1 kann man auch ohne 
zugehörige Datei mappen.
Siehe man mmap.

von Tobias W. (wagnertobse)


Lesenswert?

Ok jetzt habe ich mmap ein bisschen mehr verstanden.
ich habe die zeile mit mmap() auf

virtual_base = mmap( NULL , 32, ( PROT_READ | PROT_WRITE ), MAP_SHARED, 
fd , 0x00010080 );

geändert. Jetzt gibt mit mmap den Fehler zurück :(
Der speicherbereich müsste durch den ersten Übergabewert, der jetzt NULL 
ist, den Speicherberich reservieren.

von CC (Gast)


Lesenswert?

Tobias Wagner schrieb:
> Jetzt gibt mit mmap den Fehler zurück :(

Welchen Fehler denn?

von Tobias W. (wagnertobse)


Lesenswert?

mmap gibt eine -1 zurück

von S. R. (svenska)


Lesenswert?

Wenn mmap -1 zurückgibt, steht der Fehler in errno. Welchen Fehler 
bekommst du da? (Gleiche das am besten mit der Liste der möglichen 
Fehler aus der Manpage ab, z.B. http://linux.die.net/man/2/mmap ).

von mh (Gast)


Lesenswert?

Warum möchte man auf eine fest vorgegebene virtuelle Adresse schreiben?

von Tobias W. (wagnertobse)


Lesenswert?

In errno steht Invalid argument...
@mh
Ich möchte für eine Hardwareadresse eine Adresse in meinem virtuellen 
Adressraum.

von Tobias W. (wagnertobse)


Lesenswert?

Ich habe vermutlich den Fehler gefunden :)
Ich habe den Flaschen speicherbereich für die Brücke gewählt.

von Klaus W. (mfgkw)


Lesenswert?

1. Der Speicher wird immer ein Vielfaches einer Kachelgröße gemappt.
D.h. du wirst nicht irgendeine physikalische an irgendeine beliebige 
Adresse mappen können, sondern nur seitenweise.
Also erst überlegen, in welcher Seite die gesuchte Adresse ist, dann 
mappen.
2. Du musst entsprechend vorher für die gemappte Seite Speicher 
allokieren.
3. Siehe man mmap

von ./. (Gast)


Lesenswert?

Der TO scheint auch beratungsresistent zu sein.

Soll er mal allein weiter im trueben fischen...

von Tobias W. (wagnertobse)


Lesenswert?

Es Funktioniert jetzt :)
Der Code sieht jetzt so aus:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <unistd.h>
4
#include <fcntl.h>
5
#include <sys/mman.h>
6
#include <errno.h>
7
#include <string.h>
8
#include "hwlib.h"
9
#include "socal/socal.h"
10
#include "socal/hps.h"
11
#include "socal/alt_gpio.h"
12
#include "system.h"
13
14
15
16
int main(){
17
  void *virtual_base;
18
  unsigned int offset = 0x00010080;
19
20
  unsigned int fd;
21
  unsigned int in = 0xFFFFFFFF;
22
  unsigned int out;
23
  unsigned int i = 0;
24
  off_t base = 0xff200000;
25
26
27
28
  if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
29
    printf( "ERROR: could not open \"/dev/mem\"...\n" );
30
    return( 1 );
31
  }
32
33
  virtual_base = mmap( NULL , 2000000, PROT_WRITE , MAP_SHARED, fd , base );
34
35
  if( virtual_base == MAP_FAILED ) {
36
    printf( "ERROR: mmap() failed...\n" );
37
    close( fd );
38
    printf("%s\n", strerror(errno));
39
    return( 1 );
40
  }
41
42
  alt_write_word( virtual_base + offset, in );
43
44
  for(i = 0;i<=1000;i++){
45
    i--;
46
    i++;
47
  }
48
  out = alt_read_word(virtual_base);
49
  printf("%i wurde zurueckgegeben!!",out);
50
  return 0;
51
}

von Konrad S. (maybee)


Lesenswert?

Klaus Wachtler schrieb:
> 2. Du musst entsprechend vorher für die gemappte Seite Speicher
> allokieren.

Ganz sicher nicht!

von Tock (Gast)


Lesenswert?

/dev/mem oder /dev/kmem

von Florian H. (heeen)


Lesenswert?

./. schrieb:
> Damit ein mmap Erfolg hat, muss etwas zum 'mmap'en da sein.
> Z.B. durch ein malloc.

Klaus Wachtler schrieb:
> 2. Du musst entsprechend vorher für die gemappte Seite Speicher
> allokieren.

Unsinn. Im Gegenteil verwenden einige Betriebssysteme mmap um Speicher 
für malloc zu alloziieren.

von Tobias W. (wagnertobse)


Angehängte Dateien:

Lesenswert?

So (Florian H.) habe ich es in den beschreibungen für malloc auch 
verstanden. Gibt man als ersten Übergabewert eine NULL an, wird ein 
freier Speicherbereich der angegeben Größe alloziiert.
Im Anhang befindet sich der Adressaufbau des Mikrocontrollers und ich 
kann mit meinen Programm mit den Lightweight FPGA Slaves kommunizieren 
(3 LEDs an der FPGA Peripherie einschalten).

von ./. (Gast)


Lesenswert?

> Unsinn. Im Gegenteil verwenden einige Betriebssysteme mmap um Speicher
> für malloc zu alloziieren.

mmap hat ja auch deutlich mehr als nur 1 Parameter.

Mein Schnipsel weiter oben funktionierte jedenfalls von Anfang an...
Du darfst das aber gerne weiter als Unsinn qualifizieren...

von Gsum (Gast)


Lesenswert?

seek sollte auch auf /dev/mem funktionieren.

von Konrad S. (maybee)


Lesenswert?

./. schrieb:
> Mein Schnipsel weiter oben funktionierte jedenfalls von Anfang an...
> Du darfst das aber gerne weiter als Unsinn qualifizieren...

... was noch lange nicht bedeutet, dass es notwendig ist.
Der mmap()-Aufruf überdeckt den von malloc() bereitgestellten Speicher. 
Kannst du machen, ist aber unnötig.

von Georg A. (georga)


Lesenswert?

HW-IO via mmap ist bequem, geht aber nicht immer. x86 ist kein Problem, 
aber bei ARM muss das nicht immer gehen. Hab deshalb schon mal extra 
einen Treiber für ein paar Bits GPIO schreiben müssen...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.