Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage MMU ARM


von heinz (Gast)


Lesenswert?

Hallo,

ich spiel mit einem Raspberry rum und versuch mich jetzt an der MMU

was ich will ist ein identity mapping mit 1 MB Sections

Versteh ich das richtig dass ich dann nur die Basetable brauch (also 
keine Subpages)

Kommt in die Basetable Bit 31 .. 20 die physikalische Adresse auf die 
gemappt wird?

Gruss Heinz

von Sascha (Gast)


Lesenswert?

Hallo Heinz,
so in etwa ja, also die Physicalische Adresse, die Domaine und noch ein 
paar Attribut. Ist nur der Eintrag in die Tabelle da 1MB die Größte 
Section sein dürfte. Bei kleinerer Unterteilung gibts dann eine weitere 
Tabelle.Also Tabelle von der Tabelle usw.
Achtung: Wird die Tabelle aktualisiert müssen die Caches geleert werden, 
die MMU abgeschaltet werden, MMU-Caches geleert und neu eingeschalten 
werden. Sonst gibts Probleme da im Cache noch etwas anderes über den 
Speicherbereich steht. Die MMU verwaltet ja auch die Cache Attribute.

Ich habe das ganze mal vor ca. 2 Jahren auf einem ARM9 gemacht.

Gruß Sascha

von heinz (Gast)


Lesenswert?

Hallo Sascha,

mir gings eigentlich nur um den Cache, der funktioniert ja ohne MMU 
nicht.

Hab das jetzt auch mal runterprogrammiert und funktioniert auch, aber 
noch nicht ausgetestet.

Ich hab jetzt eine Base Translationtable ohne Coarsepages also auch ohne 
Tables. Mir ging es auch um den Speicher so brauch ich halt "nur" 16 KB

Gruss Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Sascha schrieb:
> Achtung: Wird die Tabelle aktualisiert müssen die Caches geleert werden,
> die MMU abgeschaltet werden, MMU-Caches geleert und neu eingeschalten
> werden. Sonst gibts Probleme da im Cache noch etwas anderes über den
> Speicherbereich steht. Die MMU verwaltet ja auch die Cache Attribute.

Beim ARM11 (ARMv6) muss man im Gegensatz zum ARM9 ohnehin die Caches und 
TLB invalidieren bevor man sie erstmalig verwendet.

Hier geht es anscheinend um eine statische Initialisierung bevor Caches 
und MMU überhaupt in Betrieb genommen werden, sodass man sich im 
laufenden Betrieb darüber keine Gedanken mehr machen muss.

Solange lediglich die Adresszuordnung dynamisch verändert werden 
(gleiche Attribute) müssen die D/I Caches beim ARM11 (ARMv6) ebenfalls 
nicht geleert werden, da hier VIPT Caches zum Einsatz kommen. Ein TLB 
flush ist dennoch fällig.

Gruß
Marcus

von Sascha (Gast)


Lesenswert?

Hallo,
super man lernt immer noch was dazu.
PS. genau so habe ich es auch gehalten MMU ja, aber nur damit man in den 
genus der Caches kommt. Übrigens kann man die Caches auch bei 
Register(Hardware) und statischem Speicher abschalten (bringt dort 
relativ wenig).
Gruß Sascha

von heinz (Gast)


Lesenswert?

Hallo zusammen,

ich hab immer noch ziemliche Probleme mit dem Verständnis der MMU
1
  base = (uint32_t*) 0;
2
3
4
// pinmod  
5
  base[GPFSEL1] &= ~(7<<18);
6
  base[GPFSEL1] |= 1<<18;
7
8
// set timer
9
  base[C1] = base[CLO] + 0x080000;
10
  base[CS] = 2;
11
12
// set irq controller
13
  base[0x2000B210 /4] = 0x0;
14
  base[0x2000B20C /4] = 0x80|1;
15
16
// 512 MB RAM cachable
17
  for (i=0;i<512;i++){
18
     MMUTBL[i] = i<<20 | 0x0C0E;
19
  }
20
21
// rest shared device
22
  for (i=512;i<4096;i++){
23
     MMUTBL[i] = i<<20 | 0x0C06;
24
//10987654321098765432109876543210     
25
//                   0110000000110
26
//             0000TEXapP dom0CB10
27
     
28
  }
29
    
30
  start_mmu(MMUTBL);
31
  start_l1cache();
32
//  enable_fiq();
33
34
35
36
37
while(1){
38
  base[GPCLR0] = 1<<16; // LED off
39
  tmp=0;
40
  while (tmp<1000000){
41
    tmp++;
42
  }
43
  
44
  base[GPSET0] = 1<<16; // LED on
45
  tmp=0;
46
  while (tmp<1000000){
47
    tmp++;
48
  }
49
};

So läuft das Programm wie es soll - die LED toggelt

Jetzt versuch ich die LED in einem IRQ Handler zu Toggeln
1
void c_irq_handler ( )
2
{
3
  static uint32_t t=0, i;
4
  asm("push {r0,r1,r2,r3,r4,r5,r6,r7,lr}");
5
6
  base[C1] = base[CLO] + 1000000;
7
  if (t){
8
    t=0;
9
    base[GPSET0] = 1<<16;
10
  }
11
  else{
12
    t=1;
13
//GotoXY(1,160);
14
//DrawString((uint8_t*)"1"); 
15
    base[GPCLR0] = 1<<16;
16
  }
17
18
  base[CS] = 2;
19
  asm ("pop  {r0,r1,r2,r3,r4,r5,r6,r7,lr}");
20
  asm ("subs pc,lr,#4");
21
}

das funktioniert wenn ich die Zeile
  start_l1cache();
auskommentiere. Also kein Cache

Mit Cache bleibt die LED aus

Kommentar vor dem Print weg füllt sich mein Bildschirm mit Einsen

Also versuch ich es in Assembler
1
s_irq_handler:
2
push {r0,r1,r2,r3,r4,r5,r6,r7,lr}
3
4
ldr r9,=0x20003004
5
ldr r10,[r9]
6
add r10,#999424
7
ldr r9,=0x20003010
8
str r10,[r9]
9
10
cmp r12,#0
11
mov r9,#0x10000
12
ldrne r10,=0x2020001C
13
ldreq r10,=0x20200028
14
str r9,[r10]
15
moveq r12,#1
16
movne r12,#0
17
18
ldr r9,=0x20003000
19
mov r10,#2
20
str r10,[r9]
21
22
pop  {r0,r1,r2,r3,r4,r5,r6,r7,lr}
23
subs pc,lr,#4

Ergebniss
Die LED geht mal an und bleibt dann an oder sie leibt aus

Und jetzt weiss ich nicht mehr weiter. Wäre nett wenn mir jemand ein Tip 
gibt

Gruss
Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
> das funktioniert wenn ich die Zeile
>   start_l1cache();
> auskommentiere. Also kein Cache

Hab keine Ahnung, was genau Du in der Funktion anstellst...
Hast Du den Cache invalidiert, oder schaltest Du ihn nur ein?

: Bearbeitet durch User
von heinz (Gast)


Lesenswert?

Das sollte eigentlich sauber sei
1
.globl start_l1cache
2
start_l1cache:
3
    mov r0, #0
4
    mcr p15, 0, r0, c7, c7, 0 ;@ invalidate caches
5
    mcr p15, 0, r0, c8, c7, 0 ;@ invalidate tlb
6
    mrc p15, 0, r0, c1, c0, 0
7
    orr r0,r0,#0x1000 ;@ instruction
8
    orr r0,r0,#0x0004 ;@ data
9
    mcr p15, 0, r0, c1, c0, 0
10
    bx lr

Ich habe gedacht ich brauch vielleicht ein memory barrier, aber wieso 
sollte es dann funktionieren wenn ich eine Schleife in dar Main mache?

hätte ich schreiben sollen
wenn ich es mit dem Version IRQ probiere habe ich am Ende eine Schleife

while(1){};


hmm - Unterschied ist dass ich der ohne IRQ Version in der Main zig mal 
einen Zugriff auf den Speicher mache. Ich versuch morgen mal was 
passiert wenn ich in der IRQ Version in Schleife sinnlos eine Variable 
ändere

Gruss
Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Also zumindest der TLB sollte vor dem Einschalten der MMU invalidiert 
werden. Eine ISB sollte dem Einschalten der MMU und der Caches folgen.

von heinz (Gast)


Lesenswert?

1
.globl start_mmu
2
start_mmu:
3
    mov r2,#0
4
    mcr p15,0,r2,c7,c7,0 ;@ invalidate caches
5
    mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb
6
7
    mov r2,#0x03
8
    mcr p15,0,r2,c3,c0,0 ;@ domain 0 = Manager
9
10
    mov r2,#0
11
    mcr p15, 0, r2, c2, c0, 2 ;@ 16k pagetable 
12
                              ;@ always use Translation Table Base Register 0.
13
14
    mcr p15,0,r0,c2,c0,0 ;@ tlb base
15
;@    mcr p15,0,r0,c2,c0,1 ;@ tlb base
16
17
    mrc p15,0,r2,c1,c0,0
18
    ldr r1,=0x000001     ;@ enanle mmu
19
    orr r2,r2,r1
20
    mcr p15,0,r2,c1,c0,0
21
22
    bx lr

Hab jetzt mal versucht den Speicher in der Schleife zu belasten - bringt 
auch nichts

>Eine ISB sollte dem Einschalten der MMU und der Caches folgen
Was ist eine ISB?

Gruss
Heinz

von heinz (Gast)


Lesenswert?

Hab jetzt mal die IRQ Routine und die Endlosschleife geändert
1
void c_irq_handler ( )
2
{
3
  static uint32_t t=0;
4
  asm("push {r0,r1,r2,r3,r4,r5,r6,r7,lr}");
5
  
6
DrawString((uint8_t*)" "); 
7
DrawDec(t);
8
DrawString((uint8_t*)" "); 
9
10
  base[C1] = base[CLO] + 1000000;
11
12
  if (t){
13
    t=0;
14
    base[GPSET0] = 1<<16;
15
  }
16
  else{
17
    t=2;
18
    base[GPCLR0] = 1<<16;
19
  }
20
21
  base[CS] = 2;
22
  asm ("pop  {r0,r1,r2,r3,r4,r5,r6,r7,lr}");
23
  asm ("subs pc,lr,#4");
24
}

Schleife
1
while(1){
2
  tmp=0;
3
  while (tmp<1000000){
4
    tmp++;
5
  }
6
  DrawString((uint8_t*)"1"); 
7
};

Und was bekomm ich auf den Bildschirm
"11111111 0  2 11111111 0  2 1111111....." Einsen sind es mehr

Die blinkt also schon - nur ein bischen kurz

Gruss
Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
>>Eine ISB sollte dem Einschalten der MMU und der Caches folgen
> Was ist eine ISB?

Instruction Synchronization Barrier. Stellt sicher, dass der nächste 
Befehl garantiert aus dem Speicher bzw Cache kommt und kein 
möglicherweise "veralteter" Opcode aus der Pipeline genommen wird.
DSB für den Daten Cache entsprechend auch.
Memory Barriers sind nach kontextverändernden Befehlen (context changing 
instructions) vorgeschrieben. Siehe ARM ARM.

Auch eine interessante Frage ist, ob die Inline Assembler Befehle der 
ISR garantiert an den entsprechenden Stellen eingefügt werden, oder ob 
der Compiler da noch mal "nachbessert".

von Sascha (Gast)


Lesenswert?

Hallo,
ich habe das Problem auch bei einem CM4 mit dem Interrupt feststellen 
können. Wollte dort auch nur eine LED Togglen lassen. So und jetzt zu 
dem Problem. Es wird ein Read-Modify-Write Speicherzugriff über die 
I/O-Register ausgeführt. Lesen und Schreiben sind aber trotz deiner 
Assembler oder C Struktur im Arbeitsablauf richtig, werden aber duch die 
Unterstützung des Read und Write Cache nicht richtig ausgeführt, 
jedenfalls Zeitlich. Da brauchst du zwingend einen DSB Befehl. Alle 
IO-Register (Adressen) solltest du in der MMU-Tabelle als none-cachable 
und none-bufferable einstellen. Also keinen Cache und keinen 
Write-Buffer für I/O und Hardwareregister.

Gruß Sascha

von heinz (Gast)


Lesenswert?

Okay kann ich mal einfügen.

Die Inline Befehle stehen an der richtigen Stelle (objdump)

Ich lass mir jetzt auch den Stand vom Counter 1 anzeigen und der zählt 
hoch.
Beim Wechsel von t=0 zu t=2 in fast Nullzeit

Ich brauch scheinbar in der IRQ Routine eine Memory Barriere. Broadcom 
sagt

"In order to keep the system complexity  low  and data throughput high, 
the BCM2835  AXI system does  not always return read data in-order"
.....

"You should place:
•  A memory write barrier before the first write to a peripheral.
•  A memory read barrier after the last read of a peripheral. "

Werde ich dann später mal versuchen

von heinz (Gast)


Lesenswert?

Mal weiter probiert

Eine Data memory barrier bringt nichts
Datacache invalidieren und es funktioniert wie es soll

Für die Performance kann das ja wohl keine Lösung sein?

Ich bin davon aushehangen, dass wenn ich den Speicherbereich über 2 Gig 
(da ist die Peripherie eingeblendet) in der Translationbase Tabelle als 
nicht cachbar ausweise ein flush nicht nötig ist

Gruss
Heinz

von Sascha (Gast)


Lesenswert?

Hallo Heinz,
ja Cache und Performanche ist für viele Anwendungen wie ein trojanisches 
Pferd.
Wenn man auf einem solchen Controller programme schreibt wie auf einem 
Mikrocontroller mit hochfrequenten Interrupts oder ständiges 
Contextswitching dann hat man in der Tat mit dem Cacheverwalten mehr 
Arbeit als manchmal Vorteile. Das habe ich auch schon auf meinem ARM9 
bemerkt. Diese Teile sind halt schon eher auf die Verarbeitung von 
Multimedia ausgelegt. Es gibt aber auch die Möglichkeit im Cache 
verschiedene Bereich fest einzulagern sozusagen verschiedenen 
Programmteilen zuzuweisen, wie dem Interruptsheduler oder 
Betriebssystem.

Gruß Sascha

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
> Datacache invalidieren und es funktioniert wie es soll

Prima!

> Für die Performance kann das ja wohl keine Lösung sein?

Das machst Du doch in Deiner Anwendung nur einmal nach dem Reset. Beim 
Invalidieren im laufenden Betrieb kann man durchaus selektiv vorgehen 
und muss nicht den gesamten Inhalt verwerfen.

> Ich bin davon aushehangen, dass wenn ich den Speicherbereich über 2 Gig
> (da ist die Peripherie eingeblendet) in der Translationbase Tabelle als
> nicht cachbar ausweise ein flush nicht nötig ist

Ist er auch nicht. Aber Du hast ja noch andere Datenzugriffe im 
Programm.

von heinz (Gast)


Lesenswert?

@Marcus Harnisch

Das hast Du falsch verstanden
Ich versuch im Timerinterupt (zum Testen 1 Hz) eine LED zu toggeln. 
Zugriff auf den entsprechenden Ausgang ist Memory Mapped 0x2020001C.

Ich sehe über eingetreute Prints dass meine IRQ Routine einmal nach 1 
Sekunde und dann sofort wieder "ohne" Zeitverzögerung aufgerufen wird

Die LED toggelt nur wenn ich jedesmal am Anfang der IRQ Routine den 
Daten Cache invalidiere.
1
  for (i=512;i<4096;i++){
2
     MMUTBL[i] = i<<20 | 0x0C06;
3
//10987654321098765432109876543210     
4
//                   0110000000110
5
//             0000TEXapP dom0CB10
6
     
7
  }

Jetzt habe ich meiner Meinung nach (auch) diesen Speicherbereich als 
shared Device deklariert.
0x0c06 = 0b110000000110
TEX = 000
B = 1
C = 0
AP = 11 sollte keine Rolle spielen weil domain 0 als Manager defieniert 
ist

Eigentlich sollte das also am Cache vorbeigehen. Wobei dann aber wieder 
die Aussage von Broadcom entgegen steht.

von heinz (Gast)


Lesenswert?

Und weil das alles zu einfach war
1
void c_irq_handler ( )
2
{
3
  static volatile uint32_t t=0;
4
  asm("push {r0,r1,r2,r3,r4,r5,r6,r7,lr}");
5
6
  base[C1] = base[CLO] + 1000000;
7
8
  if (t){
9
    t=0;
10
    base[GPSET0] = 1<<16;
11
  }
12
  else{
13
    t=2;
14
    base[GPCLR0] = 1<<16;
15
  }
16
17
  base[CS] = 2;
18
  base[CS] = 2;
19
20
  asm ("pop  {r0,r1,r2,r3,r4,r5,r6,r7,lr}");
21
  asm ("subs pc,lr,#4");
22
}

so funktioniert es ohne Bariere oder Flush
man beachte die Zeile

  base[CS] = 2;

ist 2 mal vorhanden

Gruss
Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
> Das hast Du falsch verstanden
>
> Die LED toggelt nur wenn ich jedesmal am Anfang der IRQ Routine den
> Daten Cache invalidiere.

Nee, hab ich nicht. Ich meinte nur, dass es nicht nötig sein sollte. 
Anscheinend haben Deine Probleme auch nichts mit dem Cache zu tun, 
sondern vermutlich mit irgendeinem kritischen timing. Statt dem Cache 
invalidate hättest Du auch eine Warteschleife ausführen können.

> Eigentlich sollte das also am Cache vorbeigehen. Wobei dann aber wieder
> die Aussage von Broadcom entgegen steht.

Die Aussage von Broadcom ist lediglich, dass die Ergebnisse von 
Lesezugriffen auf zwei unterschiedliche Peripheriebausteine in 
umgekehrter Reihenfolge zurückgegeben werden können. Das hat ebenfalls 
nichts mit Deinem Problem zu tun.

Das doppelte Schreiben ist natürlich auch nicht die Lösung sondern 
verdeckt nur das ursächliche Problem. Was ist denn "base[CS]" überhaupt?

von heinz (Gast)


Lesenswert?

>Was ist denn "base[CS]" überhaupt?
Im Prinzip das EOI für den Timerbaustein

>zwei unterschiedliche Peripheriebausteine
Das ist halt die Frage wie man das interpretiert
Sind damit auch zwei unterschiedliche Adressen gemeint, dann könnte
base[C1] = base[CLO] + 1000000;
in die Hosen gehen

Näturlich mach ich irgendwo irgendwas falsch, wenn nicht hätte Broadcom 
ein riesen Problem (was nicht ist). Das Problem ist nur was.

Ablauf sollte ff. sein
Ich habe eine freilaufenden Timer CLO
Ich habe 4 "compare register" C1 .. C4
sind CLO und Cx gleich gibt es einen Interupt
CS = 2 macht den timecompare wieder scharf

Das letzte steht so nicht in der Doku von Broadcom und wird im Internet 
etwas  diskutiert.

Was seh ich:
ohne D cache funktionierts wie es soll
mit I cache funktionierts

mit D cache kommt mein IRQ nach 1 Sekunde und sofort im Anschluss noch 
einer. Besser gesagt meine IRQ Routine wird sofort nochmal durchlaufen. 
Wobei mein Register CLO um 1000000 inkrementiert ist.
CLO ist read only

Was falsch sein kann:
Ich kontrolliere nicht ob der IRQ überhaupt vom Timer C1 ausgelöst wird
Meine Serviceroutine wird über den FIQ getriggert. Steht eigentlich 
nirgendwo das das geht.

Werde ich morgen probieren

Gruss
Heinz

von Sascha (Gast)


Lesenswert?

Hallo,
nach beendigen der Interrupts FIQ oder IRQ muss man auch aufpassen, das 
der Interrupt Controller den Interrupt als Ausgeführt (Terminiert) 
sieht.
Wird an dieser stelle keine Memory Data Barriere und Instruction 
Barriere eingebaut kann es folgenden Effekt haben. Der Interrupt wird 
zwar beendet, durch den Schreibcache und durch die Pipline wird die 
Terminierung ausherhalb der ISR-Routine gemacht. Somit gilt der 
Interrupt als nicht beendet das Pending-Flag bleibt weiter aktiv, und 
die ISR-Routine wird sofort erneut wieder angesprungen.
Ist bei den ARM Controllern ist das je nach Hersteller mal etwas besser 
oder weniger gut gelöst.

Gruß Sascha

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
>>Was ist denn "base[CS]" überhaupt?
> Im Prinzip das EOI für den Timerbaustein

Das kommt wahrscheinlich zu spät. Man sollte das immer ganz zu Anfang 
der ISR erledigen. Merke: Trotz Memory Barriers gibt es kein absolut 
narrensicheres Verfahren das garantiert, dass die Schreibzugriffe vor 
Ende der ISR durchgeführt wurden. Ein DSB (DMB reicht nicht!) vor 
Verlassen der ISR hilft.

>>zwei unterschiedliche Peripheriebausteine
> Das ist halt die Frage wie man das interpretiert

Das kann man nur mit Kenntnis der Busmatrix. Typischerweise können die 
Daten unterschiedlicher Slaves am AXI Bus out-of-order zurückgegeben 
werden.

> Sind damit auch zwei unterschiedliche Adressen gemeint, dann könnte
> base[C1] = base[CLO] + 1000000;
> in die Hosen gehen

Wieso? Ich sehe maximal zwei Lesezugriffe, deren Reihenfolge egal ist. 
Wahrscheinlich nur einer, da die Konstante vom Compiler als immediate 
erzeugt wird.

> ohne D cache funktionierts wie es soll

Klar, weil alles (z.B. POP) länger dauert und das Interrupt Clear daher 
ausreichend schnell ist.

: Bearbeitet durch User
von heinz (Gast)


Lesenswert?

Hallo,
ich habe heute leider sehr wenig Zeit gehabt.

>Somit gilt der Interrupt als nicht beendet das Pending-Flag bleibt weiter >aktiv

sieht so aus wie wenn das so wäre. Deshalb das doppelte (manchmal) 
ausführen der ISR

Ich werde mal das "Basic pending register" anschauen.

>Man sollte das immer ganz zu Anfang der ISR erledigen
was dann halt zu rekursiven Aufrufen führen kann.

>weil alles (z.B. POP) länger dauert
Ich habe das eigentlich so verstanden, dass der Schreibvorgang noch im 
Cache ist und ich die ISR schon verlassen habe?

Wieso werden die Lese/Schreibzugriffe überhaupt gecached - diese 
Adressen liegen in einem Bereich der in der Translationtabelle als 
nonbuffered,noncachable ausgewiesen sind?

und Danke für die Mühe die Ihr euch macht

Gruss
Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
> Wieso werden die Lese/Schreibzugriffe überhaupt gecached - diese
> Adressen liegen in einem Bereich der in der Translationtabelle als
> nonbuffered,noncachable ausgewiesen sind?

Device memory ist buffered, d.h. die CPU wird durch Schreibzugriffe auf 
langsame Peripherie nicht aufgehalten. Das Lesen vom Device wird nicht 
vom  Cache bedient, wohl aber die Stackzugriffe, die dann schneller 
beendet sind als das Interrupt Clear.

von heinz (Gast)


Lesenswert?

ok,ich denk ich habe es kapiert.

Danke nochmal und noch eine Frage

Ich finde im Internet
http://www.airspayce.com/mikem/bcm2835/
1
// safe write to peripheral
2
void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
3
{
4
  if (debug)
5
    {
6
  printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value);
7
    }
8
  else
9
    {
10
  // Make sure we don't rely on the first write, which may get
11
  // lost if the previous access was to a different peripheral.
12
  *paddr = value;
13
  *paddr = value;
14
    }
15
}

was bei mir
base[CS] = 2;
base[CS] = 2;
ist.

    88d0:  e59f2030   ldr  r2, [pc, #48]  ; 8908
    88d4:  e3a01002   mov  r1, #2
    88d8:  e7831002   str  r1, [r3, r2]
    88dc:  e7831002   str  r1, [r3, r2]

"zwingt" das den Prozessor den Store auszuführen, oder ist das Timing 
einfach so kritisch das der zusätzliche Store ausreicht

Mit einer DSB vor dem pop gibt es immer noch sporatisch doppelte 
Ausführung der ISR, während es mit dem doppelten Store selbst ohne DSB 
stabil läuft.

Gruss
Heinz

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

heinz schrieb:
>   // Make sure we don't rely on the first write, which may get
>   // lost if the previous access was to a different peripheral.
>   *paddr = value;
>   *paddr = value;

Das scheint eine Eigenart des SoC zu sein. Falls das Device an einem 
APB(us) hängt hinge eine mögliche Erklärung damit zusammen, dass dessen 
Busprotokoll (APBv2) keine Waitstates kennt. Das Slave Interface muss 
dann die Daten abnehmen und damit dem Prozessor das Ende des Buszyklus 
signalisieren, bevor sie im eigentlichen Register landen. Keine memory 
barrier kann in so einem Fall helfen. Daher meine frühere Bemerkung, 
dass es kein universelles, absolut sicheres Verfahren geben kann.
Es kann sich ganz schlicht auch um eine Schwäche der verwendeten 
Busmatrix handeln. Das weiß nur Broadcom. Solange es irgenwo 
dokumentiert ist kann man damit wohl ganz gut leben.

von heinz (Gast)


Lesenswert?

Ok, damit kann ich leben,
Ich sag nochmal herzlich Danke an die, die mir geholfen haben

Gruss
Heinz

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.