diff --git a/source/hic_hal/stm32/stm32h743xx/DAP_config.h b/source/hic_hal/stm32/stm32h743xx/DAP_config.h index 951316085..88036be1e 100644 --- a/source/hic_hal/stm32/stm32h743xx/DAP_config.h +++ b/source/hic_hal/stm32/stm32h743xx/DAP_config.h @@ -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. @@ -202,13 +210,13 @@ __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); @@ -216,7 +224,7 @@ __STATIC_INLINE void PORT_SWD_SETUP(void) 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) { @@ -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, @@ -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); } @@ -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; } @@ -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); } diff --git a/source/hic_hal/stm32/stm32h743xx/gpio.c b/source/hic_hal/stm32/stm32h743xx/gpio.c index 2b9462886..1331a171b 100644 --- a/source/hic_hal/stm32/stm32h743xx/gpio.c +++ b/source/hic_hal/stm32/stm32h743xx/gpio.c @@ -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] = @@ -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; +}