De bitSet(P,b) macro versus P |= 1 << b

IDE gerelateerde berichten
Berichten: 287
Geregistreerd: 15 Apr 2021, 20:05

De bitSet(P,b) macro versus P |= 1 << b

Berichtdoor ctunes » 15 Apr 2021, 22:04

Hallo, ik ben nieuw hier.

(Sorry als deze post niet op de juiste plek verschijnt, ongetwijfeld weet een admin mij te helpen de juiste plek te vinden?)

Ik heb een vraagje over de arduino compiler.

Kan iemand mij vertellen of de bitSet() macro daadwerkelijk doet wat die moet doen?

Ik probeer een output te "toggelen" zonder eerst de staat ervan hoeven te weten.

Normaal gesproken kan dat met de assembly instructie:
Code: Alles selecteren
sbi P,b
; Set bit b in Port P


Bijvoorbeeld:
Code: Alles selecteren
sbi PINC,5
; xor output van PORTC_B5 met 1


Paragraaf 10.2.2 van de atmega88/168/328 documentatie stelt dat dat zo is.

Hiervan zijn overigens ook verschillende BLINK_LED voorbeelden beschikbaar.
Sommigen daarvan echter gebruiken de volgende methode:

Code: Alles selecteren
P |= 1 << b


En dat lijkt mij niet juist.

Neem het volgende voorbeeld:

Code: Alles selecteren
PINC == 0b00000011 // Waarbij Bit0 en Bit1 beide output zijn.

Als het de bedoeling is om bit1 te flippen, dan werkt
Code: Alles selecteren
 PINC |= 1 << 1

niet.



Code: Alles selecteren

PORTC = 0b0000 0011


PINC  =   0b0000 0011
OR
PINC =    0b0000 0011
OR
1 << 1 = 0b0000 0010

=            0b0000 0011

dus:
       
PORTC = 0b0000 0000


Bit0 word door de OR ook "geflipt".


bitSet(PINC,1) zou het beoogde resultaat moeten opleveren.


Maar in mijn projecten werkte dat ook niet altijd.

Voorzover ik de macro kon volgen, leidt deze tot bovenstaande code.

::

Wat ik eigenlijk beoog te vragen is hoe de bitset() macro werkt, cq compileert.
Het schijnt namelijk ook nog zo te zijn dat de SBI instructie niet op alle registers werkt, en in hoeverre de compiler daar rekening mee houdt?

Alvast bedankt voor enige "enlightenment".

Advertisement

Berichten: 4064
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: De bitSet(P,b) macro versus P |= 1 << b

Berichtdoor shooter » 16 Apr 2021, 07:44

om dit soort dingen precies te puzelen kun je een decompiler of disassembler gebruiken, want je hebt gelijk het hoeft maar 1 bitje te zijn in de hex file die anders is.
paul deelen
shooter@home.nl

Berichten: 287
Geregistreerd: 15 Apr 2021, 20:05

Re: De bitSet(P,b) macro versus P |= 1 << b

Berichtdoor ctunes » 17 Apr 2021, 20:25

shooter schreef:om dit soort dingen precies te puzelen kun je een decompiler of disassembler gebruiken, want je hebt gelijk het hoeft maar 1 bitje te zijn in de hex file die anders is.


Ik begrijp uit deze reaktie dat ik wat niveaus verwijderd ben ...

Ik wilde juist niet het disassembly traject in, en hoopte dat iemand -bijvoorbeeld een compiler-programmeur- uitsluitsel kon geven in hoe de genoemde macro er uiteindelijk komt uit te zien in machinetaal.

Want als ik alsnog mijn code moet decompileren zodat ik zeker weet wat er gebeurt, had ik het heel programma net zo goed van het begin af aan in assembly kunnen schrijven.

"Goodbye quick and easy prototyping".

Overigens begrijp ik de opmerking: "hex file", niet?
- Daar ging het niet om, het ging om de onjuiste toepassing van een bepaalde constructie in een specifieke situatie.

Berichten: 287
Geregistreerd: 15 Apr 2021, 20:05

Re: De bitSet(P,b) macro versus P |= 1 << b

Berichtdoor ctunes » 20 Apr 2021, 18:33

Ik ben er inmiddels zelf achter gekomen.

in Arduino.h staan de macro's:
Code: Alles selecteren
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))


Heb inmiddels ook maar de disassembly bekeken, en -inderdaad- wordt soms:
Code: Alles selecteren
P |= 1 << b;

gecompileerd naar:
Code: Alles selecteren
sbi P, b

Maar niet altijd! Soms kom je doodleuk de OR actie tegen. (Het zal wel een "quirk" van de compiler zijn?)

Ik heb het uiteindelijk maar opgelost met een stukje inline assembly code (Pin A3 is gedefinieerd als output):
Code: Alles selecteren
asm ("sbi %0, %1 \n": : "I" (_SFR_IO_ADDR(PINC)), "I" (PINC3));  // Toggle state of pin A3, implemented in assembly.

Dan ben ik er tenminste zeker van.


In ieder geval bedankt voor het meedenken, en ik hoop dat iemand die tegen hetzelfde probleem aanliep hier wat aan heeft.

(En het illustreert het feit dat door een vraag te stellen je soms je eigen vraag beter leert begrijpen.)

:)

Terug naar Arduino IDE

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 8 gasten