Word-accessible-only Register mit dem GCC?

Gast #2170708
Lesenswert?
• ▲
▼
Hallo!

Ich arbeite auf einem ARM uC mit dem GCC. Es gibt auf dem uC einige 
Register die nur word-accessible sind, d.h. es müssen immer 32-bit 
gelesen/geschrieben werden (nur LDR Instruktionen). Ich suche nun einen 
Weg dies dem GCC klar zu machen. Leider generiert er teilweise 
byte-weise Zugriffe (LDRB Instruktionen) wodurch sich das Programm 
abschießt...

Kennt jemand eine Lösung?
Gast #2170744
Lesenswert?
• ▲
▼
1
void Timer_Setup(void)
2
{
3
  PT_CTRL.bit.ENABLE = 0u;
4
  PT_CTRL.bit.PRESCALER = 0u;
5
  PT_CTRL.bit.AUTO_RELOAD = 0u;
6
  PT_LOAD = 0u;
7
  PT_CTRL.bit.IRQ_ENABLE = 0u;
8
  PT_INTSTAT.bit.EVENT_FLAG = 1u;
9
}
1
  PT_CTRL.bit.ENABLE = 0u;
2
80e8040c:  e3003000   movw  r3, #0
3
   PT_CTRL.bit.PRESCALER = 0u;
4
80e80410:  e3a0c000   mov  ip, #0
5
  PT_CTRL.bit.ENABLE = 0u;
6
80e80414:  e3443824   movt  r3, #18468  ; 0x4824
7
80e80418:  e5930608   ldr  r0, [r3, #1544]  ; 0x608
8
80e8041c:  e7c0001f   bfc  r0, #0, #1
9
80e80420:  e5830608   str  r0, [r3, #1544]  ; 0x608
10
   PT_CTRL.bit.PRESCALER = 0u;
11
80e80424:  e5c3c609   strb  ip, [r3, #1545]  ; 0x609
12
   PT_CTRL.bit.AUTO_RELOAD = 0u;
13
80e80428:  e5932608   ldr  r2, [r3, #1544]  ; 0x608
14
80e8042c:  e7c1209c   bfi  r2, ip, #1, #1
15
80e80430:  e5832608   str  r2, [r3, #1544]  ; 0x608
16
  PT_LOAD = 0u;
17
80e80434:  e583c600   str  ip, [r3, #1536]  ; 0x600
18
  PT_CTRL.bit.IRQ_ENABLE = 0u;
19
80e80438:  e5931608   ldr  r1, [r3, #1544]  ; 0x608
20
80e8043c:  e7c2111c   bfi  r1, ip, #2, #1
21
80e80440:  e5831608   str  r1, [r3, #1544]  ; 0x608
22
  PT_INTSTAT.bit.EVENT_FLAG = 1u;
23
80e80444:  e593060c   ldr  r0, [r3, #1548]  ; 0x60c
24
80e80448:  e3802001   orr  r2, r0, #1
25
80e8044c:  e583260c   str  r2, [r3, #1548]  ; 0x60c
26
}
27
80e80450:  e12fff1e   bx  lr

Der Byte-Zugriff erfolgt bei 80e80424 durch das LDRB.
Das betreffende Register ist in C definiert als:
1
struct PT_CTRL_ST
2
{
3
  uint32_t ENABLE : 1;
4
  uint32_t AUTO_RELOAD : 1;
5
  uint32_t IRQ_ENABLE : 1;
6
  uint32_t RESERVED_0 : 5;
7
  uint32_t PRESCALER : 8;
8
  uint32_t RESERVED_1 : 16;
9
};
10

11
union PT_CTRL_U
12
{
13
  uint32_t all;
14
  struct PT_CTRL_ST bit;
15
};
16

17
#define PT_CTRL  \
18
  (*((volatile union PT_CTRL_U*)(TIMER_BASE_ADDR + 0x08)))
Persönliche Seite #2170768
Lesenswert?
• ▲
▼
1) Mach eine lokale Variable reg vom Typ PT_CTRL_U (nicht volatile).
2) Lies das SFR über PT_CTRL.all nach reg.all.
3) Mach deine Modifikationen.
4) Schreib das Register ebenso zurück.

Nich für jede Maschine/SFR ist es adäquat, nach Schema F über Strukturen 
auf SFRs zuzugreifen, weil manch SFRs speziell behandelt werden müssen 
(zB müssen manche Password-Bits für geschützte Zugriffe gleichzeitig 
geändert werden). Daher muss man dann etwas Handarbeit einbringen.
Gast #2170779
Lesenswert?
• ▲
▼
Johann L. schrieb:
> 1) Mach eine lokale Variable reg vom Typ PT_CTRL_U (nicht volatile).
> 2) Lies das SFR über PT_CTRL.all nach reg.all.
> 3) Mach deine Modifikationen.
> 4) Schreib das Register ebenso zurück.
>
> Nich für jede Maschine/SFR ist es adäquat, nach Schema F über Strukturen
> auf SFRs zuzugreifen, weil manch SFRs speziell behandelt werden müssen
> (zB müssen manche Password-Bits für geschützte Zugriffe gleichzeitig
> geändert werden). Daher muss man dann etwas Handarbeit einbringen.

Gibt es evtl. auch ein Compiler Flag oder Type Attribute dafür 
byte-weisen Zugriff auf ein Element zu unterbinden?
Gast #2170825
Lesenswert?
• ▲
▼
Hm, es gibt tausende Compiler Schalter für jeden Mist, nur dafür gibts 
keinen. Naja so wie Johann es beschrieben hat gehts jedenfalls. Die 
lokale Variable brauchte ich nicht, der Zugriff über all hat 
ausgereicht:
1
80e8040c <Timer_Setup>:
2
   PT_CTRL.all = 0u;
3
80e8040c:  e3003000   movw  r3, #0
4
80e80410:  e3a01000   mov  r1, #0
5
80e80414:  e3443824   movt  r3, #18468  ; 0x4824
6
80e80418:  e5831608   str  r1, [r3, #1544]  ; 0x608
7
  PT_LOAD = 0u;
8
80e8041c:  e5831600   str  r1, [r3, #1536]  ; 0x600
9
  PT_INTSTAT.bit.EVENT_FLAG = 1u;
10
80e80420:  e593060c   ldr  r0, [r3, #1548]  ; 0x60c
11
80e80424:  e3802001   orr  r2, r0, #1
12
80e80428:  e583260c   str  r2, [r3, #1548]  ; 0x60c
13
}
14
80e8042c:  e12fff1e   bx  lr
Persönliche Seite #2171396
Lesenswert?
• ▲
▼
Klaus schrieb:
> Hm, es gibt tausende Compiler Schalter für jeden Mist, nur dafür gibts
> keinen.

Stimmt nicht ganz. Das ARM ABI verlangt von einem Compiler, dass 
Zugriffe auf volatile Bitfelder auf jeden Fall in der Größe des 
Containers zu erfolgen haben. GCC hatte aber bis vor kurzem den Fehler, 
dies eben nicht zwangsläufig zu tun. Man kann das bei älteren GCC 
Versionen über einen Schalter, dessen Name mir gerade entfallen ist, 
erzwingen. Bei neueren GCC ist diese option für ARM Targets automatisch 
aktiv. Einfach mal im Manual nachschlagen.

Gruß
Marcus
Gast #2171618
Lesenswert?
• ▲
▼
Hallo Marcus,

nach etwas suchen habe ich "-fstrict-volatile-bitfields" gefunden. Meist 
du vielleicht das?

Als GCC habe ich
1
gcc version 4.4.1 (Sourcery G++ Lite 2010q1-188)

doch der meint zu dieser Option leider nur:
1
cc1.exe: error: unrecognized command line option "-fstrict-volatile-bitfields"

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren