DAPLink icon indicating copy to clipboard operation
DAPLink copied to clipboard

Actually pull up nRESET on STM32F103

Open ducky64 opened this issue 2 years ago • 3 comments

Despite the comments in the STM32F103 HIC, the nRESET pin was never pulled up since the STM32F103 can't do simultaneous open drain and pull up. Previously, it relies on an external pullup resistor to not enter bootloader mode, which isn't present on some standalone debug probes.

This changes the code to initialize nRESET in input mode with pull up when nRESET is high, and configures it in open-drain mode when nRESET is asserted low.

Testing notes:

  • Previously, running DAPLink on a STM32F103-based standalone programmer without a nRESET pullup would cause it to always enter bootloader mode. Now, that only happens when nRESET is grounded.
  • STLink V2 clone note: these devices have a different nRESET pinning, on PB5 (through a resistor) and PB6 (direct on the nRESET pin). With this PR, they will always boot into the interface, but they can't be forced back into bootloader mode by grounding the nRESET pin.
    • Things behave as expected if the pinning is corrected (and the default CONNECTED_LED is moved elsewhere from the reset pin on these boards).

Resolves #824 (wasn't clear why that never made it into a PR).

ducky64 avatar Jun 15 '23 07:06 ducky64

@ducky64 Thanks for your work. I ran across this issue as well, and a more simple solution to me is to update the gpio_init() in gpio.c:

#ifdef DAPLINK_BL  // Bootloader needs to read nRESET_PIN to determine if stay in bootloader
    GPIO_InitStructure.Pin = nRESET_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(nRESET_PIN_PORT, &GPIO_InitStructure);
#else
    // reset button configured as gpio open drain
    HAL_GPIO_WritePin(nRESET_PIN_PORT, nRESET_PIN, GPIO_PIN_SET);
    GPIO_InitStructure.Pin = nRESET_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; 
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(nRESET_PIN_PORT, &GPIO_InitStructure);
#endif

Normally, a RESET_PIN should be OD for the electrical level is decided by the MCU itself. It got this issue because DAPLink shares the same gpio.c between bootloader and IF and luckly there are two macros DAPLINK_BL and DAPLINK_IF to identify which is which. Anyway it's only for your reference.

llinjupt avatar Apr 19 '24 12:04 llinjupt

@ducky64 Thanks for your work. I ran across this issue as well, and a more simple solution to me is to update the gpio_init() in gpio.c:

#ifdef DAPLINK_BL  // Bootloader needs to read nRESET_PIN to determine if stay in bootloader
    GPIO_InitStructure.Pin = nRESET_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(nRESET_PIN_PORT, &GPIO_InitStructure);
#else
    // reset button configured as gpio open drain
    HAL_GPIO_WritePin(nRESET_PIN_PORT, nRESET_PIN, GPIO_PIN_SET);
    GPIO_InitStructure.Pin = nRESET_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; 
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(nRESET_PIN_PORT, &GPIO_InitStructure);
#endif

Normally, a RESET_PIN should be OD for the electrical level is decided by the MCU itself. It got this issue because DAPLink shares the same gpio.c between bootloader and IF and luckly there are two macros DAPLINK_BL and DAPLINK_IF to identify which is which. Anyway it's only for your reference.

llinjupt avatar Apr 19 '24 12:04 llinjupt