Arbeiten uns gerade in den IAR Compiler für ARM Prozessoren ein. Im
angehängten include file befindet sich ein Auszug der Deklaration des
Registers RCC_APB2ENR (IOSTM32....). Wir möchten den UART einschalten
also USART1EN setzen. Wie macht man das , ohne das ganze Register direkt
mit einer Zahl zu beschreiben? Wir haben schon alles probiert, der
Compiler bringt immer eine Fehlermeldung. Bei anderen Compiler wars so:
RCC_APB2ENR |= (1<<USART1EN) wo aber der Compiler anmeckert, das er
USART1EN nicht kennt.
probier mal, statt USART1EN die echte bit-Position(0..7)? in dem
Register, wo es sich befinden sollte, einzutragen. Wenn es dann geht,
kennt der Compiler den Namen für die bit-Position nicht. Habe aber von
ARMs weiter keine Ahnung.
HERRMANN schrieb:> RCC_APB2ENR |= (1<<USART1EN)
dass heißt "USART1EN" ist nirgens definiert.
es geht aber RCC_APB2ENR |= (1<<5); wenn USART1EN das Bit 5 währe (weiß
ich aber nicht)
Schon lange nichts mehr mit EWARM gemacht und auch nicht mehr
installiert aber soweit erinnert, bietet der IAR Compiler die
Möglichkeit Register direkt auf Bit-Felder "abzubilden". Der im
TO-Beitrag angehängte Teil der Definitionen ist etwas knapp, um das
nachzusehen. Testweise also:
RCC_APB2ENR.USART1EN=1; Wie das intern umgesetzt wird, kann man dem
erzeugen Assembler-Listing und/oder Disassembly entnehmen.
Das Konstrukt "mappen auf Bitfelder" sollte jedoch vermieden werden,
wenn man portablen Code schreiben will. Beim GNU C-Compiler wurde diese
Funktionalität meines Wissens z.B. erst jüngst in den Entwicklungs-Code
aufgenommen (Google-Futter: -fstrict-volatile-bitfields). Ältere und
aktuelle Versionen erkennen eine vermeindliche Optimierungsmöglichkeit
und nutzen für Hardware-Register nicht zulässige Byte-Zugriffe).
Martin Thomas schrieb:> Das Konstrukt "mappen auf Bitfelder" sollte jedoch vermieden werden,> wenn man portablen Code schreiben will. Beim GNU C-Compiler wurde diese> Funktionalität meines Wissens z.B. erst jüngst in den Entwicklungs-Code> aufgenommen (Google-Futter: -fstrict-volatile-bitfields). Ältere und> aktuelle Versionen erkennen eine vermeindliche Optimierungsmöglichkeit> und nutzen für Hardware-Register nicht zulässige Byte-Zugriffe).
Bitfelder sind im ARM ABI ausführlich dokumentiert. Insbesondere ist es
vorgeschrieben, dass die Größe der Zugriffe auf volatile Bitfelder deren
Containergröße entsprechen muss. Das Verhalten der betroffenen GCC
Versionen ist somit fehlerhaft und hat nichts mit Portabilität zu tun.
--
Marcus
Marcus Harnisch schrieb:> Bitfelder sind im ARM ABI ausführlich dokumentiert. Insbesondere ist es> vorgeschrieben, dass die Größe der Zugriffe auf volatile Bitfelder deren> Containergröße entsprechen muss.
Ja, das wird auch als Grund für die Erweiterung in der GNU compiler
collection angegeben.
> Das Verhalten der betroffenen GCC> Versionen ist somit fehlerhaft und hat nichts mit Portabilität zu tun.
Ja, dass das Verhalten bei volatilen Bitfeldern in bisherigen GCC C/C++
Versionen mag im Sinne von ARMs Vorgaben fehlerhaft sein. Vermeidet man
aber Bitfelder 'über Hardwareregistern' und nutzt stattdessen
'*(volatile uint32_t *)' und Bitoperationen, kann man Quellcode mit
allen Compilern für ARM in lauffähigen Maschinencode übersetzten. Ich
bezeichne das dann als portablen Code. Lerne aber gerne eine korrektere
Defintion.
Weiteres ist in einem neuen Thread besser aufgehoben.
Also bei RCC_APB2ENR.USART1EN=1; kommt eben "expression must have struct
oder union Type" Ich gebs jetzt vorläufig mal auf und werde später
wieder auf das Problem zurückgehen, wenn ich mit dem Prozessor etwas
firm bin....
HERRMANN schrieb:> Das geht natürlich, es befriedigt mich aber nicht, da USART1EN im h file> steht und so mit Sicherheit angewendet werden kann.
Dann würde ich mal an dieser Stelle im .h File anfangen.
Wie genau ist USART1EN dort eingetragen?
Ich nehm mal an, dass dort so etwas steht wie
#define USART1EN 5
Von dort gehts jetzt weiter nach aussen:
Steht dieser #define in einem #ifdef?
Wenn ja, welche Bedingung (anderes #define) muss es daher dafür geben?
Wo kommt das wiederrum her?
Dieses .h File, wird das von einem anderen .h File includiert?
etc, etc.
Solange bis du genau weßt, waann und warum der #define für UART1EN aktiv
ist und welche anderen Symbole das steuern.
Und dann sieht man nach, wie man das auf der Oberfläche regeln kann,
dass das erste Symbol definiert wird, welches dann alles weitere
triggert.
Martin Thomas schrieb:> Vermeidet man aber Bitfelder 'über Hardwareregistern' und nutzt> stattdessen '*(volatile uint32_t *)' und Bitoperationen, kann man> Quellcode mit allen Compilern für ARM in lauffähigen Maschinencode> übersetzten.
Und wer garantiert, dass der Zugriff auf ein (volatile uint32_t) in
jedem Fall von jeder beliebigen Compilerversion durch einen
Wortzugriff erfolgt? Du gehst davon aus, weil es in der ABI (sec
7.1.5) so definiert ist und erwartest, dass der Compiler sich daran
hält.
Man kann den Einsatz von bit-fields für sinnvoll halten oder nicht
(durchaus auch fallweise), aber in diesem Zusammenhang einen
Compilerfehler als Begründung seiner Präferenz zu bemühen ist schon
arg weit hergeholt.
Notfalls kann man sich den Registerwert in eine lokale Variable
kopieren, auf dieser Kopie arbeiten und das Ergebnis wieder zurück
schreiben. Bei der Manipulation mehrerer bits ist das in beiden
Fällen ohnehin nötig.
Gruß
Marcus