Decoding Portenta Register Babble from Microcontroller Datasheet

My current understanding is that register manipulation has not yet been explored with the Portenta because the macros to do it have not been coded within the Arduino environment.
For example, for the UNO, register manipulation is easy because the macros to do it have been coded into "Arduinish language" to make it easy. There are only two registers there to fiddle with, PORT and DDR which make it even easier still to write quickly executed code.

If we look at the datasheet for the GPIOs From the Portenta microcontroller datasheet however under section 12 "General Purpose I/Os (GPIO)" it states:

Each general-purpose I/O port has four 32-bit configuration registers (GPIOx_MODER,
GPIOx_OTYPER, GPIOx_OSPEEDR and GPIOx_PUPDR), two 32-bit data registers
(GPIOx_IDR and GPIOx_ODR) and a 32-bit set/reset register (GPIOx_BSRR). In addition
all GPIOs have a 32-bit locking register (GPIOx_LCKR) and two 32-bit alternate function
selection registers (GPIOx_AFRH and GPIOx_AFRL).

Which is evidently more complicated that other Arduino microcontroller architectures. Can anyone shed light as to what the STM32H747 registers do, or perhaps more importantly, which ones (if at all) can be ignored?

Register manipulation will be hugely advantageous for the Portenta. Of course I don't need to stress too much that the fast clock speeds should be taken full advantage of by dispensing with slow code.

The MODER registers determine whether your GPIO is

input
general purpose output
alternate function
analog

OTYPER is for

push-pull
open drain

OSPEEDR
low
medium
high
very high speed

PUPDR
if you want to enable pull-ups

IDR and ODR are the state (input data or output data)

BSRR - bit set/reset register

AFRH/AFRL determines the alternate function if you have "alternate function" in MODER

Sample code would look something like this


void periphInit_UART1(void)
{
	// enable UART1 clock
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

	// set alternate GPIO functions for UART1 TX and RX
	GPIOB->MODER &= ~(GPIO_MODER_MODER7 | GPIO_MODER_MODER6);
	GPIOB->MODER |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER6_1;
	GPIOB->AFR[0] |= 7<<GPIO_AFRL_AFSEL7_Pos | 7<<GPIO_AFRL_AFSEL6_Pos;

	// USART1 is on APB2 with Fclk of 120 MHz
	// set baud rate to 115200 bps
	USART1->BRR = 1042;

I wrote this example to turn a led on and off via the registers. Maybe this can help you further.

// LEDR -> connected with port K pin 5 (see schematic: https://content.arduino.cc/assets/Arduino-PortentaH7-schematic-V1.0.pdf)
volatile uint32_t* const GPIOD_MODER = (uint32_t *)0x58022800; // GPIO port mode register
volatile uint32_t* const GPIOD_ODR = (uint32_t *)0x58022814; // GPIO port output data register
int dataFromRegister = 0;

void setup(){
  Serial.begin(115200);
  // set GPIO port mode register
  uint32_t moder = *GPIOD_MODER;
  moder |= (1 << 10); // set to 1
  moder &= ~(1 << 11); // set to 0
  *GPIOD_MODER = moder;
}

void loop(){
  *GPIOD_ODR |= (1 << 5);   // led-off
  dataFromRegister = *GPIOD_ODR;
  Serial.print("off ");
  Serial.println(dataFromRegister, BIN);
  delay(500);
  *GPIOD_ODR &= ~(1 << 5);  // led-on
  delay(2000);
  dataFromRegister = *GPIOD_ODR;
  Serial.print("on  ");
  Serial.println(dataFromRegister, BIN);
}
1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.