Synchronized multiple pin setting

Post your cool example code here.
User avatar
Rick Kimball
Posts: 722
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Synchronized multiple pin setting

Postby Rick Kimball » Wed Dec 28, 2016 9:48 pm

I came across an interesting feature of the GPIO BSRR registers. The BSRR register allows you to modify both the reset (BSRR_H) and set (BSRR_L) registers for the same pin in a single C statement. Probably obvious to some, but I've not seen it mentioned or used much. What this allows you to do is to set the final state of multiple pins with one c statement, even if you are clearing one and setting another. You don't have to load and modify, you just modify. This saves a few cycles and makes the pin setting atomic.

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.

Code: Select all

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);
  }
}


The BSRR register applies the reset action first (the 0b11 << 16) and then applies the set action next ( either 0b01 or 0b10 ).

-rick
-rick

User avatar
RogerClark
Posts: 5462
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Synchronized multiple pin setting

Postby RogerClark » Wed Dec 28, 2016 10:00 pm

Rick

That's how the libmaple core handles digitalWrite

https://github.com/rogerclarkmelbourne/ ... gpio.h#L92

User avatar
Rick Kimball
Posts: 722
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Synchronized multiple pin setting

Postby Rick Kimball » Wed Dec 28, 2016 10:06 pm

Heh .. ok well we have a very efficient core :)

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.
Last edited by Rick Kimball on Wed Dec 28, 2016 10:09 pm, edited 1 time in total.
-rick

User avatar
RogerClark
Posts: 5462
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Synchronized multiple pin setting

Postby RogerClark » Wed Dec 28, 2016 10:09 pm

I did look at it some time ago, as I wast sure about the efficiency of having to invert the bit and then do the shifting, so I tried a few other ways to do it, but everything else was slow ;-)

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.

User avatar
Rick Kimball
Posts: 722
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Synchronized multiple pin setting

Postby Rick Kimball » Wed Dec 28, 2016 11:00 pm

RogerClark wrote: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.

Yeah that was the point of this post. Also, using the ODR register isn't atomic.

-rick
-rick

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

Re: Synchronized multiple pin setting

Postby stevestrong » Wed Dec 28, 2016 11:10 pm

This feature is used in the 8/16 bit parallel-driven display modules.

victor_pv
Posts: 945
Joined: Mon Apr 27, 2015 12:12 pm

Re: Synchronized multiple pin setting

Postby victor_pv » Fri Dec 30, 2016 4:34 am

Rick Kimball wrote:

Code: Select all

  while(1) {
    _GPIOA->BSRR = 0b11 << 16 | 0b01;
    delay(1);
    _GPIOA->BSRR = 0b11 << 16 | 0b10;
    delay(1);
  }
}


The BSRR register applies the reset action first (the 0b11 << 16) and then applies the set action next ( either 0b01 or 0b10 ).

-rick


Rick, I think I am not understanding something.
I get that the top half and bottom half work on the same pins, and the top half is for resetting, and the bottom for setting, but why would not you use this instead?

Code: Select all

  while(1) {
    _GPIOA->BSRR = 0b10 << 16 | 0b01;
    delay(1);
    _GPIOA->BSRR = 0b01 << 16 | 0b10;
    delay(1);
  }
}


I do not understand why in the first one you set the same pin to reset and set (first bit) (0b1 << 16 | 0b1). And same thing with the second bit in the second statement.
What is the purpose of resetting and setting the same pin at once?

User avatar
Rick Kimball
Posts: 722
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Synchronized multiple pin setting

Postby Rick Kimball » Fri Dec 30, 2016 5:17 am

Yes in this case you could do it like that.

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:

Code: Select all

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;
  }
}

The code above produces 125ns pulses on the PA0, 250ns pulses on PA1, and 500ns pulses on PA2.

-rick
Last edited by Rick Kimball on Fri Dec 30, 2016 2:07 pm, edited 1 time in total.
-rick

racemaniac
Posts: 325
Joined: Sat Nov 07, 2015 9:09 am

Re: Synchronized multiple pin setting

Postby racemaniac » Fri Dec 30, 2016 7:07 am

Rick Kimball wrote:Heh .. ok well we have a very efficient core :)

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.

here's the dma version ;)
viewtopic.php?f=18&t=1042

victor_pv
Posts: 945
Joined: Mon Apr 27, 2015 12:12 pm

Re: Synchronized multiple pin setting

Postby victor_pv » Sat Dec 31, 2016 7:11 am

Rick, I think I understand, you reset them all "by default", and then set whatever needs to be set. Rather than have to specifically reset some pins, you reset all, and set what's needed to be set.
Then the set, 16 lower bits, take precedence, correct?
Last edited by victor_pv on Sun Jan 01, 2017 9:22 pm, edited 1 time in total.


Return to “Code snipplets”

Who is online

Users browsing this forum: No registered users and 1 guest