kann nicht in Register schreiben

Gast #5461971
Lesenswert?
• ▲
▼
Hallo zusammen!
Ich verwende gerade ein Embedded System (Zybo) und habe ein Problem bei 
der Prozessorprogrammierung!
Ich will in das gemappted Register (vom XADC) einen Wert schreiben 
(verwende Petalinux), dieser wird aber nicht reingeschrieben.
Ich verwende folgenden Befehl (mit Überprüfung):
1
int fd = open("/dev/mem", O_RDWR|O_SYNC);
2
UINT16 *xadc_addr = (UINT16 *)mmap(0, XADC_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, XADC_START_ADDR);
3
*((volatile UINT16 *)(xadc_addr + 0x49)) = 0x4000;
4
if (*((volatile UINT16 *)(xadc_addr + 0x49)) != 0x4000)
5
{
6
  printf("Error: simultaneous mode for channel 6 and 14\n");
7
  //return -1;
8
}

Hat jemand eine Idee, warum ich den Wert nicht auslesen kann, bzw warum 
er sich jetzt nicht im Register befindet?
Moderator Persönliche Seite #5462001
Lesenswert?
• ▲
▼
Tja, dann musst du wohl tiefer reinsteigen. Ich fürchte, dass es nicht
so viele Leute gibt, die sich mit dieser Plattform auskennen.

Gibt's vielleicht irgendwelche Kernelmeldungen in den Logs?  Kann es
sein, dass dein Register irgendeine Form von Schreibschutz besitzt?

Btw., du solltest natürlich unbedingt den Rückkehrwert von mmap()
testen, bevor du auf die Region zugreifst.  Ist allerdings vermutlich
nicht dein Problem hier.
Gast #5462020
Lesenswert?
• ▲
▼
Vielen Dank für die schnelle Antwort!
Den Rückgabewert von mmap() habe ich schon getestet und das läuft 
soweit.

Ich hab natürlich auch schon eine Recherche gemacht, aber nichts 
gefunden.
Einen Fehler beim Schreiben erhalte ich auch nicht.

Finde ich sehr komisch....
Moderator Persönliche Seite #5462038
Lesenswert?
• ▲
▼
Prinzipiell ist die Vorgehensweise schon korrekt so, wenn man mit
memory mapping auf sowas zugreifen muss.  Allerdings habe ich selbst
solche Aktionen das letzte Mal vor mehr als 20 Jahren gemacht, als
die PCs noch deutlich einfacher strukturiert waren (ISA-Adressraum).

mmap() sieht natürlich normalerweise nur virtuelle Adressen, wie diese
auf physische Adressen umgesetzt werden, entscheidet das OS darunter.
Dieser Teil scheint jedoch beim TE zu funktionieren, sein Problem ist
ja nur, dass sich in der Hardware dabei nichts ändert, er also seinen
geschriebenen Wert nicht rücklesen kann.
Moderator Persönliche Seite #5462051
Lesenswert?
• ▲
▼
derFragende schrieb:
> Bedeutet, den Wert den ich in das Register schreibe, ist sofort wieder
> weg.

Naja, für memory-mapped IO ist das ja erstmal nicht völlig ungewöhnlich:
ist halt kein Speicher, sondern ein IO-Register eines Peripherals.

Da wirst du dich wohl durch die Details selbst durchbeißen müssen.
Schau dir mal einen größeren Bereich an Adressen an und versuche, ob
du da irgendeinen Zusammenhang zur Registeranordnung gemäß Dokumentation
herstellen kannst.
Gast #5462057
Lesenswert?
• ▲
▼
Ich meinte damit auch nicht die Vorgehensweise ändern. Vielleicht gibt's 
ja schon einen Treiber für eine andere Hardwarekomponente, die das so 
macht.
Dort könnte man dann Schritt für Schritt vergleichen und ggf. abschauen.

Als nicht-user-mode Programm könnte man das mit Pointern auf die 
Adressen lösen.

Bsp:
1
volatile char *dst = (volatile char*)0xADD;
Je nach gewünschter Datenbreite int, short, ... verwenden, bzw uint8_t, 
uint16_t, ...
#5462058
Lesenswert?
• ▲
▼
Jörg W. schrieb:
> Vielleicht, weil man auf einer ungeraden Adresse nicht mit einem
> 16bittigen Zugriff arbeiten kann?

Ich sehe da keinen ungraden Offset. Die 0x49 wird zu einem uint16_t* 
addiert - dabei multipliziert der Compiler automagisch mit 2.

Eventuell könnte das auch ein Problem sein (falscher Offset)? Ich finde 
jedenfalls auf die Schnelle kein Datenblatt von dem ADC.

Andererseits sind ADCs von SOCs gerne mal so komplex (DMA & Co), dass 
man die mit einem Kernel Modul ansteuern will.
Moderator Persönliche Seite #5462061
Lesenswert?
• ▲
▼
Safari schrieb:
> Als nicht-user-mode Programm könnte man das mit Pointern auf die
> Adressen lösen.

Im Kontext eines VM-Betriebssystems wäre das dann allerdings kein
"Programm" mehr, sondern ein "Treiber", den man dafür schreiben
müsste.

MMIO über mmap() hat den Vorteil, dass man erstmal flexibler ist,
da man im Userland herumopern kann.  Wenn das Mapping auf das Gerät
prinzipiell funktioniert, dann ist nicht davon auszugehen, dass durch
die Verlagerung des Codes in den Kernel irgendwas anders oder besser
wird.  Es lässt sich dann nur schwieriger debuggen.
Gast #5462082
Lesenswert?
• ▲
▼
Jörg W. schrieb:
> Wenn das Mapping auf das Gerät
> prinzipiell funktioniert, dann ist nicht davon auszugehen, dass durch
> die Verlagerung des Codes in den Kernel irgendwas anders oder besser
> wird.  Es lässt sich dann nur schwieriger debuggen.

Wo zieht man die Grenze zwischen Programm und Treiber? Also was wird 
Programm und was sollte besser ein Treiber werden?
Bei PCs ist das, denke ich, noch einfacher als bei Einzelanfertigungen, 
geringen Stückzahlen und Bastelei.

Aber im Sinne von "universal" würde ich ein /dev/adc doch besser finden, 
als wenn jedes mögliche Programm direkt im Speicher hantiert.

<nicht ernst nehmen> Wir könnten ja CPM-like Sprungtabellen zu den 
Helferroutinen anlegen... </...>

@debugging: Als ich angefangen habe, mir anzusehen, wie Kernel-Module 
geschrieben werden und selbst herumprobiert habe, stellte ich schnell 
fest, dass mein PC eine Reset-Taste braucht.
Gast #5462095
Lesenswert?
• ▲
▼
Also mir fehlt der Schreibzugriff zu den Config-Registern.
Der Wert davor ist 0, ich schreibe
1
xadc_addr[ 0x40 | = 0x8200;
anschließend steht weiterhin der Wert 0 im Register.
Gibts da eine Möglichkeit Schreibzugriff zu erhalten.

Hier wäre das Datenblatt (aufgrund einer Nachfrage)
https://www.xilinx.com/support/documentation/user_guides/ug480_7Series_XADC.pdf

Bzgl. des ändernden Werte, ich habe gerade das Statusregister mit einem 
internen Werteregister verwechselt.
Gast #5463056
Lesenswert?
• ▲
▼
derFragende schrieb:
> also ich hab jetzt mal bei mmap den offset auf 0 gesetzt und geschaut.
> Jetzt hält es die Werte, die ich reinschreibe in die Register.
> Aber ich brauch den offset....

Dann rechne ihn beim zugriff drauf. mmap() und Konsorten arbeiten über 
Page mapping und können daher nur Offsets in Blöcken der Pagegröße 
deines Systems (typischer Wert: 4k) verarbeiten.

Wenn die ADC-Adresse nicht an einer Pagegrenze liegt, geht das durchaus 
mal schief.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.