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