GPIO registers and port manipulation

iwalpola
Sun Jul 03, 2016 9:35 pm
Sources:
http://embedded-lab.com/blog/stm32-gpio-ports-insights/
http://hertaville.com/stm32f0-gpio-tutorial-part-1.html

The libmaple libraries, on which STM32duino is based, provides access to registers by the syntax:

GPIOA->regs->REG


RogerClark
Sun Jul 03, 2016 10:42 pm
Did you see the post about individual bit access via different addresses.

( sorry I cant find the link to the thread at the moment as I am posting from my phone)


Ollie
Sun Jul 03, 2016 11:01 pm
Here is the post for accessing
– individual bits of the peripheral registers
– bit fields in peripheral registers

http://www.stm32duino.com/viewtopic.php … ing#p15081

In the first case the parameters are the register name and bit number. In the second case, the parameters are
– register name
– first bit number
– number of bits

Note: the bit number can go over 32 to make it easier to address bit fields that are stored in multiple 32 bit register words.

This method is the fastest way to access (read and write) peripheral register content. In addition, it is multi thread safe, when the mask based read-modify-write sequence is not.

Cheers, Ollie


RogerClark
Sun Jul 03, 2016 11:25 pm
@ollie

Thanks.

I should get into the habit of trying to remember something unique in those sorts of posts, so I stand a better chance of finding them again.
In this case it would be “bit banding”


iwalpola
Sun Jul 03, 2016 11:49 pm
Sounds interesting, at this rate I won’t get any sleep at all :D

smithy
Sun Sep 04, 2016 2:54 pm
Hmm maybe i misunderstood something but trying following did not give the results i expected:
void setup() {
GPIOA->regs->CRL = (GPIOA->regs->CRL & 0x33333333) ; //set PA0-PA7 output
//Set A0-A7 (HIGH)
GPIOA->regs->ODR |= 0b0000000011111111;
}

atacanteknik
Mon May 08, 2017 7:05 am
i want use a led gpioc port for PC13
how i can use witd direct registers and port manipulation
stm32f103 series

edogaldo
Mon May 08, 2017 9:57 am
void setup()
{
RCC_BASE->APB2ENR |= 0x10; // enable GPIOC clock
GPIOC->regs->CRH = (GPIOC->regs->CRH & 0xFF0FFFFF) | 0x00100000; // PC13 output push/pull (max speed 10MHz)
GPIOC->regs->CRH = (GPIOC->regs->CRH & 0xFF0FFFFF) | 0x00200000; // PC13 output push/pull (max speed 2MHz)
GPIOC->regs->CRH = (GPIOC->regs->CRH & 0xFF0FFFFF) | 0x00300000; // PC13 output push/pull (max speed 50MHz)
}
void loop()
{
GPIOC->regs->BSRR = 0x00002000; //PC13 = 1 (leave others unchanged)
GPIOC->regs->BSRR = 0x20000000; //PC13 = 0 (leave others unchanged)
GPIOC->regs->BSRR = 0x20002000; //PC13 = 1 (leave others unchanged - lower bits (set) have precedence over higher (clear))
GPIOC->regs->BRR = 0x00002000; //PC13 = 0 (leave others unchanged)
GPIOC->regs->ODR = 0x00002000; //PC13 = 1 (all others set to 0)
GPIOC->regs->ODR |= 0x00002000; //PC13 = 1 (leave others unchanged)
GPIOC->regs->ODR = 0x00000000; //PC13 = 0 (all others set to 0 too)
GPIOC->regs->ODR &= ~0x00002000; //PC13 = 0 (leave others unchanged)
}

atacanteknik
Mon May 08, 2017 11:22 am
can you made same PC15

edogaldo
Mon May 08, 2017 11:53 am
atacanteknik wrote:can you made same PC15

atacanteknik
Tue May 09, 2017 12:50 pm
how i add on integer port read like that

int state = DDRC & B00000011;

and write
DDRC = state | (bx<<5) | (by<<2);


edogaldo
Tue May 09, 2017 8:11 pm
atacanteknik wrote:how i add on integer port read like that

int state = DDRC & B00000011;

and write
DDRC = state | (bx<<5) | (by<<2);


dannyf
Fri Jun 16, 2017 12:06 am
atacanteknik wrote:how i add on integer port read like that

Ollie
Fri Jun 16, 2017 8:57 am
If your application is using interrupts that could manipulate the target GPIO ports, the read-modify-write operation is not safe. That is the reason, why STM has designed BSRR registers to set and reset selected pins.

The monotonic pin manipulations can be done with macros

#define gpio_clear(GpioPort, GpioPins) GpioPort->BSRR = ((GpioPins) << 16)
#define gpio_set(GpioPort, GpioPins) GpioPort->BSRR = (GpioPins)

These are the fastest way to do GPIO pin updates.


erinqvnm
Fri Sep 15, 2017 7:49 am
Hi, thanks for good explanation. Tried in my STM32F103 to increase bit-bang frequency instead of using digitalWrite. With a simple benchmarking:
unsigned long time = micros();
for (uint32_t i = 0; i < 1000000; i++) {
GPIOA->regs->BSRR = 0b0000000000000001;
GPIOA->regs->BRR = 0b0000000000000001;
}
time = micros() - time;

dannyf
Fri Sep 15, 2017 12:51 pm
the CRL settings are just for current drive capabilities.

the two measurements you got should be identical. the variation you saw is likely due to other factors and may go away if you run multiple trials.

edit:

as a test, I ran the following, to flip a pin using BSRR/BRR and tested speed for 1 million flips on a 48Mhz F103.

int main(void) {
int i;

mcu_init(); //reset the mcu
//systick_init();
coretick_init(); //reset coretick

//initialize the pins to outout
IO_OUT(LED_PORT, LED1 | LED2); //led1/2 as output @ 10Mhz
GPIO_DDR(LED_PORT, LED1 | LED2, 0x03); //led1/2 as output @ 50Mhz
IO_CLR(LED_PORT, LED1 | LED2);

ei(); //enable global interrupts
while (1) {
time0 = coreticks(); //time stamp
for (tmp=0; tmp < 1000000ul; tmp++) {FIO_SET(LED_PORT, LED2); FIO_CLR(LED_PORT, LED2);}
time0 = coreticks() - time0;
NOP();
};
}


Leave a Reply

Your email address will not be published. Required fields are marked *