cancel
Showing results for 
Search instead for 
Did you mean: 

[TrueStudio] What type is "XX_GPIO_Port" ?

JOF
Associate II

To minimalize migration from a current working atmel design to a new stm32 design, i desire to create a abstraction function in atollic true studio. Currently, it seems that when generating the project via cube, the MX_GPIO_Init function uses each code block for each output, which is not very efficient to me. The next problem is, that the function needs at least two arguments for a pin, which are pin_name and pin_port.

Here is an example of the current function

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

So what i'm planing to do is call a init by only a pin name

#define SENSOR 1
#define LED 2
 
const gpioPinDesctipion hwPinDescription[]={
***Pin no - pin port - pin mode - pin pullup - pin speed***
{GPIO_PIN_5, GPIOA,GPIO_MODE_OUTPUT_PP,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW}
{GPIO_PIN_6, GPIOA,GPIO_MODE_IT_FALLING,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW}
}

followed by the functon:

void pinInide(ID){
 
 GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = hwPinDescription[ID].pin;
  GPIO_InitStruct.Mode =hwPinDescription[ID].io;
  GPIO_InitStruct.Pull = hwPinDescription[ID].pull;
  HAL_GPIO_Init( hwPinDescription[ID].port, &GPIO_InitStruct);
}

But currently i'm struggling to find out what the data type is of "GPIO_PORT" when opening declaration in atollic i get

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

How can i assign this to a variable to use in a struct array?

I hope i have desicribed precise enough what i want to do, any help welcome! :)

4 REPLIES 4
alister
Lead

GPIO_TypeDef describes the GPIO peripheral's memory interface. It may differ slightly for each MCU type. So HAL declares it in a MCU-specific file with a name like stm32????xx.h. GPIOA_BASE is its memory address.

From reading your code that defines hwPinDescription, I expect gpioPinDesctipion's second member is of type GPIO_TypeDef *.

An improvement to your implementation might be to table each pin's configuration:

(1) Change gpioPinDesctipion to

typedef struct
{
  GPIO_TypeDef *gpioX;
  GPIO_InitTypeDef gpioInit;
} gpioPinDescription;

(2) Each member of the hwPinDescription array includes a pointer to the pin's GPIO peripheral and its configuration.

Pavel A.
Evangelist III

> Currently, it seems that when generating the project via cube, the MX_GPIO_Init function uses each code block for each output, which is not very efficient to me.

Maybe the generated code is not most efficient, but the tool does it automatically and STM32s have a plenty of code memory compared to 8-bits. It isn't worth optimization.

Anyway... the type of XX_GPIO_PORT is pointer to GPIO_TypeDef struct, and a "pin definition struct" can be optimized in following way: each GPIO port has 16 pins, so pin number can be encoded by 4 bits. The port number can be also encoded by 4 bits. So the pin can be encoded in one byte.

static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB... };
 GPIO_InitTypeDef GPIO_InitStruct;
 GPIO_TypeDef *gpioport = gpios[ (hwPinDescription[ID].pin >> 4) & 0xF ]; // high 4 bits
 GPIO_InitStruct.Pin = hwPinDescription[ID].pin & 0xF; // low 4 bits
 ........
HAL_GPIO_Init( gpioport, &GPIO_InitStruct);

-- pa

Not sure why yours has generated a HAL_GPIO_Init() for each output pin. This what STM32CubeMX V5.1.0 generated for one of my projects.

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, RF_CSB_Pin|RF_FCSB_Pin|AUDIO_MUTE_Pin, GPIO_PIN_SET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED_1_Pin|LED_2_Pin|LED_3_Pin|LED_4_Pin 
                          |WP_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pins : RF_CSB_Pin RF_FCSB_Pin AUDIO_MUTE_Pin */
  GPIO_InitStruct.Pin = RF_CSB_Pin|RF_FCSB_Pin|AUDIO_MUTE_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /*Configure GPIO pin : HP_DET_Pin */
  GPIO_InitStruct.Pin = HP_DET_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(HP_DET_GPIO_Port, &GPIO_InitStruct);
 
  /*Configure GPIO pin : RF_DATA_Pin */
  GPIO_InitStruct.Pin = RF_DATA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(RF_DATA_GPIO_Port, &GPIO_InitStruct);
 
  /*Configure GPIO pins : LED_1_Pin LED_2_Pin LED_3_Pin LED_4_Pin 
                           WP_Pin */
  GPIO_InitStruct.Pin = LED_1_Pin|LED_2_Pin|LED_3_Pin|LED_4_Pin 
                          |WP_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
  /*Configure GPIO pins : BUTTON_6_Pin BUTTON_5_Pin BUTTON_4_Pin BUTTON_3_Pin 
                           BUTTON_2_Pin BUTTON_1_Pin */
  GPIO_InitStruct.Pin = BUTTON_6_Pin|BUTTON_5_Pin|BUTTON_4_Pin|BUTTON_3_Pin 
                          |BUTTON_2_Pin|BUTTON_1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
}

Observe it's one HAL_GPIO_Init() call for each group of pins on the same GPIO peripheral with same Mode, Pull and Speed.

Generated code and HAL is generally good for fast development, not fast performance. You might check the STM32CubeMX version and its Project Manager settings. In V5.1.0 there's an option to "Generate peripheral initialization as a pair of '.c/.h' files per peripheral" (default off). It doesn't sound like what you're describing though.

In any case, I wouldn't consider the GPIO init optimization you're describing unless (a) you're out of flash or (b) you've lots of outputs and you're wanting to shave microseconds off the boot time.

JOF
Associate II

@alister​ 

Thanks this seems to help, will try out!

The goal is not primarily to speed up the code, its more that there is already a application that has functions for wrtingint port (IO_write(pin,level) and IO_init(pin,type). If i want to migrate, i would have to touch all the h and cpp files and change lines where the write functions are to the stm32 likes, which is alot of work. I want to create functions behind that functions that run the stm code.

In the hobby section, ARDUINO did the same thing, in their code its always "digitalWrite(pin,level)", it doesnt matter if there is an atmega 8bit, 32bit, or a stm32, or a fpga board used. There are just functions behind digitalWrite that run the processor specific code thats the point.

My current application is very similar