Here is an example, say you wanted to toggle two pins 180 degrees out of phase with one call. You clear both pins using the reset register, I’m using PA0 and PA1 for this example, so you use 0b11 to reset both pins, then you use 0b01 to set PA0 and then next time use 0b10 to set PA1 the next.
void setup() {
pinMode(PA0,OUTPUT);
pinMode(PA1,OUTPUT);
}
void loop() {
static gpio_reg_map * const _GPIOA = GPIOA->regs;
while(1) {
_GPIOA->BSRR = 0b11 << 16 | 0b01;
delay(1);
_GPIOA->BSRR = 0b11 << 16 | 0b10;
delay(1);
}
}
That’s how the libmaple core handles digitalWrite
However, using it to synchronize several pins on the same port doesn’t seem to be talked about much. This feature might come in handy with a DMA call and values.
You can do synchronised bit setting and resetting using the ODR register, but the overhead of reading the reg first and masking it etc, is slower.
while(1) {
_GPIOA->BSRR = 0b11 << 16 | 0b01;
delay(1);
_GPIOA->BSRR = 0b11 << 16 | 0b10;
delay(1);
}
}
A better use case might be using it with a dynamic data variable and you don’t know ahead of time which pins will be on an which will be off. I could have made a 2 bit random variable and used that instead of the hard coded 0b01 and it would still set all the bits properly. It would still be atomic and not require a load and modify.
Maybe you want to use a counter on the pins:
void setup() {
pinMode(PA0,OUTPUT);
pinMode(PA1,OUTPUT);
pinMode(PA2,OUTPUT);
}
void loop() {
static gpio_reg_map * const _GPIO = GPIOA->regs;
unsigned counter=0;
while(1) {
_GPIO->BSRR = 0b111 << 16 | counter++ & 0b111;
}
}
However, using it to synchronize several pins on the same port doesn’t seem to be talked about much. This feature might come in handy with a DMA call and values.
Then the set, 16 lower bits, take precedence, correct?

