How to evaluate digitalWrite at compile time?

What could be included in further releases, or for the forum.
Post Reply
danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

How to evaluate digitalWrite at compile time?

Post by danieleff » Mon May 29, 2017 4:22 am

If the parameters are constant, I want digitalWrite(pin, val) to evaluate it at compile time. Down to one instruction.
Currently pseudocode (the exact structure of pin_type is irrelevant):

Code: Select all

//variant.cpp
const pin_type variant_pins[] = {...}

//gpio.h
extern const pin_type variant_pins[];
inline void digitalWrite(pin, value) {...variant_pins[pin]...}

//x.ino
...gpio.h included...
digitalWrite(PA0, LOW);

//other.cpp
...gpio.h included...
digitalWrite(PA1, LOW);
Theoretically variant_pins[pin] could be evaluated at compile time (well, link time, but at compile time it could be a placeholder that the linker fills in), but it is not.

I could put the whole list into the header (as static local), which works, but then it is duplicated in every compilation unit when used.

I checked https://stackoverflow.com/q/5010216/834966 , https://stackoverflow.com/q/11403800/834966 , -fmerge-all-constants , -flto and god knows what already.
I always get either no compile time evaluation, or duplicated array.
Anybody knows some solution to this?

ag123
Posts: 719
Joined: Thu Jul 21, 2016 4:24 pm

Re: How to evaluate digitalWrite at compile time?

Post by ag123 » Mon May 29, 2017 9:11 am

i'm not too sure if c++ templates could help or perhaps some kind of pointer style codes is needed ?
i'm not too sure how to use those

Code: Select all

template<class T>
function(T&a) {
 static_cast<T&&>(a);
 }
stuff but i do see them in various c++ codes

stevestrong
Posts: 1520
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: How to evaluate digitalWrite at compile time?

Post by stevestrong » Mon May 29, 2017 9:25 am

I would define separate inline functions digitalSet(PIN) and digitalClear(PIN) something like this:

Code: Select all

inline void digitalSet(p) { PIN_MAP[p].dev->regs->BSRR = PIN_MAP[p].pin; }

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: How to evaluate digitalWrite at compile time?

Post by danieleff » Thu Jun 01, 2017 5:16 am

Well it did need some trickery, making pin names constexpr int-convertable class instead of enum when compiling for c++, but now this

Code: Select all

void loop() {
    digitalWrite(LED_BUILTIN, HIGH);
    digitalWrite(LED_BUILTIN, LOW);
    digitalWrite(LED_BUILTIN, HIGH);
    digitalWrite(LED_BUILTIN, LOW);
    digitalWrite(LED_BUILTIN, HIGH);
    digitalWrite(LED_BUILTIN, LOW);
}
compiles to

Code: Select all

08002188 <loop>:
 8002188:	2202      	movs	r2, #2
 800218a:	4b04      	ldr	r3, [pc, #16]	; (800219c <loop+0x14>)
 800218c:	611a      	str	r2, [r3, #16]
 800218e:	615a      	str	r2, [r3, #20]
 8002190:	611a      	str	r2, [r3, #16]
 8002192:	615a      	str	r2, [r3, #20]
 8002194:	611a      	str	r2, [r3, #16]
 8002196:	615a      	str	r2, [r3, #20]
 8002198:	4770      	bx	lr
 800219a:	bf00      	nop
 800219c:	40010c00 	.word	0x40010c00
which is good enough

Post Reply