Hallo!
Ich beschäftige mich gerade mit dem STM32F0DISCOVERY Board und möchte
den STM32F0 aus Spaß möglichst nur nach Datenblatt programmieren. Dabei
bin ich auf ein kurioses Problem gestoßen, dessen Lösung ich hier nun
poste, falls jemand anderes ebenfalls darüber stolpert.
Ich wollte im FLASH_ACR Register den Prefetch Buffer einschalten. Und da
ich ein großer Fan von Bitfeldern bin, tat ich folgendes:
1 | struct __attribute__((__packed__)) flash_acr
|
2 | {
|
3 | unsigned latency : 3;
|
4 | unsigned : 1;
|
5 | unsigned prftbe : 1;
|
6 | unsigned prftbs : 1;
|
7 | };
|
8 | volatile flash_acr &acr = *((volatile flash_acr*)0x40022000);
|
9 | acr.prftbe = 1;
|
Dies wird in die folgenden Instruktionen übersetzt:
1 | 8000448: 2110 movs r1, #16
|
2 | 800044a: 4a27 ldr r2, [pc, #156]
|
3 | 800044c: 7813 ldrb r3, [r2, #0]
|
4 | 800044e: 430b orrs r3, r1
|
5 | 8000450: 7013 strb r3, [r2, #0]
|
Bei der ldrb Instruktion springt er allerdings in den Hardfault
Interrupt.
Die Adresse ist auf jeden Fall richtig, denn wenn ich das ganze ohne
Bitfelder mache geht es:
1 | volatile unsigned &flash_acr = *((volatile unsigned*)0x40022000);
|
2 | flash_acr |= 1<<4;
|
Dabei werden die folgenden Instruktionen erzeugt:
1 | 8000448: 2111 movs r1, #16
|
2 | 800044a: 4a27 ldr r2, [pc, #156]
|
3 | 800044c: 6813 ldr r3, [r2, #0]
|
4 | 800044e: 430b orrs r3, r1
|
5 | 8000450: 6013 str r3, [r2, #0]
|
Der Unterschied ist hierbei, dass statt eines einzelnen Bytes das ganze
32 Bit Word gelesen wird. Scheinbar ist byteweises Lesen hier nicht
erlaubt.
Daher muss man dem Compiler irgendwie mitteilen, dass er auch bei der
Bitfeld Methode ganze Wörter lesen und schreiben soll. Das geht indem
man das Bitfeld bis zur Wortgrenze auffüllt:
1 | struct __attribute__((__packed__)) flash_acr
|
2 | {
|
3 | unsigned latency : 3;
|
4 | unsigned : 1;
|
5 | unsigned prftbe : 1;
|
6 | unsigned prftbs : 1;
|
7 | unsigned : 26;
|
8 | };
|
9 | volatile flash_acr &acr = *((volatile flash_acr*)0x40022000);
|
10 | acr.prftbe = 1;
|
Damit werden die selben Instruktionen erzeugt wie in der zweiten
Methode.
Ich hoffe das hilft irgendjemandem von euch!
Cheers,
Michael