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
constuint32_tBASEADDR=0x3000000;
2
u16*ptr=(u16*)BASEADDR;//hier u16, da meine AD-Wandlung einen u16 Wert zurück gibt
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
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.
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.
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
>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?
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
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
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, ...)?
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?
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.
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...
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.