Forum: Mikrocontroller und Digitale Elektronik Probleme mit Pointer zu Memory


von Dominik (Gast)


Lesenswert?

Hallo zusammen,
ich arbeite mit einem uC, der zwei Kerne hat. Der eine Kern liest u16 
Daten ein, während der zweite Kern die Daten auslesen soll (im Rahmen 
einer größeren AD-Wandlung mit Weitergabe der Daten).
Die Daten werden dabei im Memory abgespeichert, damit beide Kerne 
gleichzeitig darauf zugreifen können. Eine einseitige Sperre (damit noch 
nichts ausgelesen ist, wo noch nichts steht) ist vorhanden.
Mein Problem ist jetzt, dass bei 2500 Werten alles hervorragen läuft und 
anschließend nur noch nicht plausible und falsche Werte ausgegeben 
werden.

Einen Speicherüberlauf kann ich ausschließen, weil der von mir 
vorgesehene Addressatenraum nicht überlaufen ist/wird.

Ich vermute, dass mein Fehler bei der Definition der einzelnen Pointer 
liegt. Meine Skills sind hier leider nur mittelmäßig. Könnte mir hier 
jemand einen Tipp geben, wo vermutlich mein Fehler liegt?
1
const  uint32_t  BASEADDR  = 0x3000000;
2
u16* ptr = (u16*) BASEADDR; //hier u16, da meine AD-Wandlung einen u16 Wert zurück gibt

von Thomas W. (diddl)


Lesenswert?

Am Pointer kann es nicht liegen.
Das ist so simpel, dass da nichts schief gehen kann.


Letztlich ist ein Pointer ja nur ein 32 Bit Wert, wenn der Adressraum 32 
Bit breit ist

von Frank (Gast)


Lesenswert?

Mit dem kleinen code Fragment ist nicht viel anzufangen :(

Wie verwendest du den ptr?
Wie zählst du in hoch?
Wie groß ist dein zur Verfügung stehender Speicherbereich?
etc.

Mehr code, mehr antworten.

von Axel S. (a-za-z0-9)


Lesenswert?

Dominik schrieb:
> Der eine Kern liest u16
> Daten ein, während der zweite Kern die Daten auslesen soll (im Rahmen
> einer größeren AD-Wandlung mit Weitergabe der Daten).
> Die Daten werden dabei im Memory abgespeichert, damit beide Kerne
> gleichzeitig darauf zugreifen können.

Wie groß ist der Buffer? Wie implementiertst du den Überlauf vom Ende 
des Buffers zu seinem Anfang?

> Eine einseitige Sperre (damit noch
> nichts ausgelesen ist, wo noch nichts steht) ist vorhanden.

Und du bist sicher, daß die korrekt ist? Daß sie insbesondere damit 
zurecht kommt, wenn der writer schon wieder zum Anfang des Buffers 
gesprungen ist, der reader aber noch weiter hinten hängt?

> Mein Problem ist jetzt, dass bei 2500 Werten alles hervorragen
> läuft und anschließend nur noch nicht plausible und falsche
> Werte ausgegeben werden.

Nicht genug Informationen. Zeig Code.

von Thomas (Gast)


Lesenswert?

Dominik schrieb:
> Könnte mir hier jemand einen Tipp geben, wo vermutlich mein Fehler
> liegt?

Nun der Fehler liegt vermutlich am Programm was du hier nicht zeigt.

Thomas

von PittyJ (Gast)


Lesenswert?

>const  uint32_t  BASEADDR  = 0x3000000;

Die 3 ist ungerade .das führt bei uint16, als 2 Bytes zu Problemen.
Besser wäre
const  uint32_t  BASEADDR  = 0x2000000;
oder
const  uint32_t  BASEADDR  = 0x4000000;











Und jetzt mal ehrlich: Die Zeilen, die am wenigstens Fehler machen 
können, die wurden hier gapostet. Das komplizierte aber nicht.
BTW: was für ein Prozessor? Liegt noch irgendeine Art von Betriebssystem 
dazwischen?

von georg (Gast)


Lesenswert?

Dominik schrieb:
> Der eine Kern liest u16
> Daten ein, während der zweite Kern die Daten auslesen soll

Ob Pointer oder sonstwie ist egal - wenn einer schreibt und der andere 
liest, müssen die Operationen (Wert schreiben + Pointer erhöhen) 
entweder atomar sein oder durch Semaphore o.ä. abgesichert. Sonst 
schreibt z.B. A den Wert in den Buffer, aber bevor A den Pointer erhöht 
und zurückgeschrieben hat greift B zu. Ausserdem braucht man 2 Pointer, 
einen zum Schreiben und einen zum Lesen.

Georg

von Stefan (Gast)


Lesenswert?

Der Pointer ist grade egal ob big oder little endian. Wicht ist nur die 
letzte stelle der Hexzahl zum auslesen ob die grade ist, wenn es us um 
16bit zugriffe geht und auch nur auf System die Boundries definiert 
haben für ihren Speicher

von Stefan F. (Gast)


Lesenswert?

Wie viele Bits schriebt die CPU gleichzeitig ins RAM (8, 16 oder 32)?

Geht es hier um eine Speicherzelle, die wiederholt überschrieben wird, 
oder um einen Puffer? Wie ist der Puffer organisiert (Ring, LiFo, ...)?

von Dr. Sommer (Gast)


Lesenswert?

Gleichzeitiger Zugriff von mehreren Kernen ist eine sehr komplizierte 
Angelegenheit und wird u.a. durch die folgenden Faktoren beeinflusst:
- Prozessor-Architektur
- Cache-Configuration
- Cache Coherence
- Cache Maintenance Operations
- Speicher-Controller
- Atomics / exklusive Zugriffe
- Memory Barriers
- Compiler-Optimierung
- Exceptions
- Alignment
- Bus-Hierarchie
- Betriebssystem / RTOS
- Implementation der Mutexe
- Dein Programmcode
usw.
Keinen dieser Punkte hast du genannt. Wie soll man hier auch nur die 
geringste Idee haben woran es liegen könnte?

von foobar (Gast)


Lesenswert?

Bei SMP ist mehr zu beachten als nur simple atomare Zugriffe.

Das wichtigste sind wohl die Caches - nur weil ein Core etwas 
geschrieben hat, heisst das nicht, dass ein anderer das auch sieht. Beim 
schreibenden Core müssen die Daten aus dem eigenen Cache auch wirklich 
in das RAM (oder einem gemeinsamen Cache) transferiert werden; beim 
lesenden Core, muß sein Cache für den zu lesenden Bereich geleert 
werden, sonst liest er nur alte Daten aus seinem Cache. Einige CPUs 
haben da Hardwarekomponenten, die das vereinfachen (z.B. snooping), 
andere nicht. Evtl muß die MMU für bestimmte Speicherbereiche speziell 
konfiguriert werden, dass sie für Datentransfers geeignet sind.

Ein anderer Aspekt ist Reordering. Daten müssen nicht in der Reihenfolge 
ins Memory transferiert werden, in denen sie vom Programm geschrieben 
worden sind. Es müssen evtl Memory-Barrier eingebaut werden, damit der 
andere Core die richtige Reihenfolge sieht.

Usw usf ... Low-Level-SMP-Programmierung ist nicht ohne und verlangt 
ordentliche Kenntnisse der Architektur. Das alles selbst aufzubauen ist 
ne Menge Arbeit - wenn's irgendwie geht, würd ich schauen, dass ich ein 
OS bekomme, dass mir den Großteil schon abgenommen hat.

von Nop (Gast)


Lesenswert?

PittyJ schrieb:
>>const  uint32_t  BASEADDR  = 0x3000000;
>
> Die 3 ist ungerade .das führt bei uint16, als 2 Bytes zu Problemen.

Bullshit.

von Dr. Sommer (Gast)


Lesenswert?

Nop schrieb:
> Bullshit.

Na sowas :D 0x3000000 = 50331648 dez = 2^24 * 3 ... "Ungerade" ist eine 
Zahl welche kein Vielfaches von 2 ist. In der Zahl kommt die 2 24x als 
Primfaktor vor. Wie soll die denn ungerade sein...

von Peter D. (peda)


Lesenswert?

Dominik schrieb:
> const  uint32_t  BASEADDR  = 0x3000000;

Ich kenne das so, daß man die Speicherverwaltung immer dem Linker 
überläßt und nicht irgendwelche magische Adressen am Linker vorbei 
benutzt.

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.