Skip to content

Commit

Permalink
Optimize HAL_GPIO_Init
Browse files Browse the repository at this point in the history
This function is called frequently during DAP transactions and the
original implementation in the HAL loops through all the pins to arrive
at the one it wants to change.

Optimize the loop into a simple calculation to find the corrent bit
position to change.
  • Loading branch information
gaborcsapo authored and mbrossard committed Jun 27, 2023
1 parent f0e2201 commit dcf8dd1
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 8 deletions.
24 changes: 16 additions & 8 deletions source/hic_hal/stm32/stm32h743xx/DAP_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ of the same I/O port. The following SWDIO I/O Pin functions are provided:

// Configure DAP I/O pins ------------------------------

/** Fast functions to init GPIOs.
The original HAL implementation cycles through all the pins because it allows
configuring multiple pins in the same call. We don't need this feature and
would rather just speed up the execution for faster DAP communication by removing
the internal loop.
*/
void HAL_GPIO_Init_Optimized(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);

/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET.
Configures the DAP Hardware I/O pins for JTAG mode:
- TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
Expand Down Expand Up @@ -202,21 +210,21 @@ __STATIC_INLINE void PORT_SWD_SETUP(void)

// Set SWCLK HIGH
gpio_init.Pin = g_swd_dut_configs[g_cur_swd_dut].swclk.pin;
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].swclk.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].swclk.port, &gpio_init);
HAL_GPIO_WritePin(g_swd_dut_configs[g_cur_swd_dut].swclk.port,
g_swd_dut_configs[g_cur_swd_dut].swclk.pin, GPIO_PIN_SET);

// Set SWDIO HIGH
gpio_init.Pin = g_swd_dut_configs[g_cur_swd_dut].swdio.pin;
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].swdio.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].swdio.port, &gpio_init);
HAL_GPIO_WritePin(g_swd_dut_configs[g_cur_swd_dut].swdio.port,
g_swd_dut_configs[g_cur_swd_dut].swdio.pin, GPIO_PIN_SET);

// Set RESET HIGH
gpio_init.Pin = g_swd_dut_configs[g_cur_swd_dut].nreset.pin;
gpio_init.Mode = GPIO_MODE_INPUT;
gpio_init.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].nreset.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].nreset.port, &gpio_init);

if (g_cur_swd_dut == SWD_DUT0)
{
Expand Down Expand Up @@ -252,10 +260,10 @@ __STATIC_INLINE void PORT_OFF(void)
};

gpio_init.Pin = g_swd_dut_configs[g_cur_swd_dut].swclk.pin;
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].swclk.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].swclk.port, &gpio_init);

gpio_init.Pin = g_swd_dut_configs[g_cur_swd_dut].swdio.pin;
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].swclk.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].swclk.port, &gpio_init);

HAL_GPIO_WritePin(g_swd_dut_configs[g_cur_swd_dut].swd_en_buf.port,
g_swd_dut_configs[g_cur_swd_dut].swd_en_buf.pin,
Expand Down Expand Up @@ -343,7 +351,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void)
.Mode = GPIO_MODE_OUTPUT_PP,
.Speed = GPIO_SPEED_FREQ_VERY_HIGH,
};
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].swdio.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].swdio.port, &gpio_init);
g_swd_dut_configs[g_cur_swd_dut].swdio.port->BSRR = (g_swd_dut_configs[g_cur_swd_dut].swdio.pin << 16);
}

Expand All @@ -359,7 +367,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void)
.Mode = GPIO_MODE_INPUT,
.Pull = GPIO_PULLUP,
};
HAL_GPIO_Init(g_swd_dut_configs[g_cur_swd_dut].swdio.port, &gpio_init);
HAL_GPIO_Init_Optimized(g_swd_dut_configs[g_cur_swd_dut].swdio.port, &gpio_init);
g_swd_dut_configs[g_cur_swd_dut].swdio.port->BSRR = g_swd_dut_configs[g_cur_swd_dut].swdio.pin;
}

Expand Down Expand Up @@ -555,7 +563,7 @@ __STATIC_INLINE void DAP_SETUP(void)

PORT_SWD_SETUP();

HAL_GPIO_Init(CONNECTED_LED_PORT, &gpio_init);
HAL_GPIO_Init_Optimized(CONNECTED_LED_PORT, &gpio_init);
HAL_GPIO_WritePin(CONNECTED_LED_PORT, CONNECTED_LED_PIN, GPIO_PIN_SET);
}

Expand Down
61 changes: 61 additions & 0 deletions source/hic_hal/stm32/stm32h743xx/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

#define GPIO_INIT_STABILIZATION_DELAY_MS (100)

#define GPIO_OUTPUT_TYPE (0x00000010U)
#define GPIO_MODE (0x00000003U)

static const dut_pin_group_t s_dut_pin_group[DUT_PIN_GROUP_ID_COUNT] =
{
[DUT_PIN_GROUP_ID_UDC0_RST_L] =
Expand Down Expand Up @@ -423,3 +426,61 @@ bool gpio_dut_pin_group_is_active_high(dut_pin_group_id_t dut_pin_group_id)
{
return s_dut_pin_group[dut_pin_group_id].active_high;
}

// The fastest way to compute trailing zeros is using a lookup table
// For the source and more background pls see:
// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
static uint8_t count_trailing_zeros_optimized(uint32_t input)
{
static const uint32_t s_multiply_debruijn_bit_position[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
return s_multiply_debruijn_bit_position[((uint32_t)((input & -input) * 0x077CB531U)) >> 27];
}

void HAL_GPIO_Init_Optimized(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t temp;
uint32_t position = count_trailing_zeros_optimized(GPIO_Init->Pin);

/* Check the parameters */
util_assert(IS_GPIO_ALL_INSTANCE(GPIOx));
util_assert(IS_GPIO_PIN(GPIO_Init->Pin));
util_assert(IS_GPIO_MODE(GPIO_Init->Mode));
util_assert(IS_GPIO_PULL(GPIO_Init->Pull));
util_assert((GPIO_Init->Mode != GPIO_MODE_AF_PP) || (GPIO_Init->Mode != GPIO_MODE_AF_OD));
util_assert((GPIO_Init->Pin & ~(1 << position)) == 0);

/*--------------------- GPIO Mode Configuration ------------------------*/
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
temp = GPIOx->MODER;
temp &= ~(GPIO_MODER_MODE0 << (position * 2U));
temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2U));
GPIOx->MODER = temp;

/* In case of Output or Alternate function mode selection */
if ((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD))
{
/* Check the Speed parameter */
util_assert(IS_GPIO_SPEED(GPIO_Init->Speed));
/* Configure the IO Speed */
temp = GPIOx->OSPEEDR;
temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2U));
temp |= (GPIO_Init->Speed << (position * 2U));
GPIOx->OSPEEDR = temp;

/* Configure the IO Output Type */
temp = GPIOx->OTYPER;
temp &= ~(GPIO_OTYPER_OT0 << position) ;
temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4U) << position);
GPIOx->OTYPER = temp;
}

/* Activate the Pull-up or Pull down resistor for the current IO */
temp = GPIOx->PUPDR;
temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
temp |= ((GPIO_Init->Pull) << (position * 2U));
GPIOx->PUPDR = temp;
}

0 comments on commit dcf8dd1

Please sign in to comment.