cancel
Showing results for 
Search instead for 
Did you mean: 

GPIO read/write not working on custom STM32H735 board

Legacy member
Not applicable

Hello,

I'm using a custom board based on a STM32H735 with various GPIO inputs and outputs. The STM32 is packaged as a 0.5mil pitch BGA and the board assembly has been outsourced.

I'm able to flash a program on the MCU and debug it by adding breakpoints and visualizing registers values. However, none of the GPIO is working: I cannot drive a LED nor read a button input state. The registers are set as expected when using the HAL to set/reset a GPIO output. I've tried to bypass the HAL and write directly on the registers MODER and ODR, and the IDR register value change as expected. On top of that, I have no trouble driving a GPIO output on my STM32H735 demo board, so I don't think the issue come from the software.

I have 6 LEDs on different GPIO ports, and I cannot drive a single one of them. I also have three boards, I'm able to flash and debug all of them, but not a single GPIO.

It looks as if the GPIOs of the MCU where somehow not connected to the LEDs and buttons of my board. It could be explained if the 0.5mil BGA has been badly soldered, but I can communicate with my 3 boards through the JTAG, and not a single one of the GPIO I tested on my boards are working. This seems thus improbable to me that the issue come from some soldering/reflowing issue, as the JTAG is never impacted.

Do you have any idea on where the issue could come from, or any insight on where I should look at?

Thanks for your help.

T.

 

1 ACCEPTED SOLUTION

Accepted Solutions
Laurent BEYLY
ST Employee

You have only connected the LDO but in your code you have enabled the SMPS.

Try to use :  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); in system_clock config instead of your current setting :

HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);

This should help.

View solution in original post

11 REPLIES 11
FBL
ST Employee

Hello @Legacy member,

Based on the description, indeed, the issue is related to the hardware. You can refer to the datasheet of the STM32H735 to check the pinout.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


I'm out of offce with limited access to my emails.
Happy New Year!
Legacy member
Not applicable

Thanks for you quick reply @FBL.

The hardware pinout has been checked and everything looks as expected. There could be some reflowing issue, but this is odd, as except for the GPIOs, the MPU is running smoothly.

Is there something particular that needs to be wired for the GPIOs to work? Some power-related pins that are specific to the GPIOs for instance?

Regards,
T

Did you enable the GPIO clocks?

If you can program the board, debug it, etc, it has power. There's nothing else required other than enabling clocks, initializing GPIO pins, and using them.

Show your code.

If you feel a post has answered your question, please click "Accept as Solution".
Legacy member
Not applicable

Here's my code, most of it generated by CubeMx:

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2023 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void) {
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick.
   */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  uint8_t Status = 0;
  while (1) {
    HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin,
                      (GPIO_PinState)Status);
    GPIO_PinState PinRougeState =
        HAL_GPIO_ReadPin(LED0_GPIO_Port, LED0_Pin);
    GPIO_PinState TamperState =
        HAL_GPIO_ReadPin(TAMPER_SW_GPIO_Port, TAMPER_SW_Pin);
    GPIO_PinState Dip1State = HAL_GPIO_ReadPin(DIP1_GPIO_Port, DIP1_Pin);


    HAL_Delay(1000);
    Status = 1 - Status;
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void) {
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Supply configuration update enable
   */
  HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);

  /** Configure the main internal regulator output voltage
   */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
  }

  /** Initializes the RCC Oscillators according to the specified parameters
   * in the RCC_OscInitTypeDef structure.
   */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = 64;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
   */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                                RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 |
                                RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
    Error_Handler();
  }
}

/**
 * @brief GPIO Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_GPIO_Init(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN MX_GPIO_Init_1 */
  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);

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

  /*Configure GPIO pin : DIP1_Pin */
  GPIO_InitStruct.Pin = DIP1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(DIP1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : TAMPER_SW_Pin */
  GPIO_InitStruct.Pin = TAMPER_SW_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(TAMPER_SW_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN MX_GPIO_Init_2 */
  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void) {
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1) {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @PAram  file: pointer to the source file name
 * @PAram  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line) {
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line
     number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file,
     line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

The GPIO clock has indeed been enabled.

TDK
Guru

> I've tried to bypass the HAL and write directly on the registers MODER and ODR, and the IDR register value change as expected

Oh, if IDR/ODR are behaving as expected, the output pin on the STM32 is seeing the correct state. So no code bug, no need to look further into that.

Are the LEDs soldered backwards? Turn the chip off and do a diode test with a multimeter across them with correct polarity. Do they light up?

If you feel a post has answered your question, please click "Accept as Solution".
Legacy member
Not applicable

Oh, if IDR/ODR are behaving as expected, the output pin on the STM32 is seeing the correct state. So no code bug, no need to look further into that.

Thanks for confirming that.

Concerning the LEDs, I managed to turn them on manually, so they are working. By measuring with a multimeter on the copper track between the MPU GPIO and the LED, nothing seems to be outputed. I can't measure directly on the MPU obviously as it is a BGA, but it seems to confirm that the LEDs are not linked properly to the GPIO outputs of the STM32.

According to your responses the issue indeed seems to come from the BGA reflowing process, even though it appeared improbable that the JTAG and power of the MCU are well soldered but none of the GPIO. We confirmed that the issue does not come from software, so except if you have any other insight on what to investigate, I guess that I have to get another batch of boards, maybe from a different subcontractor.

I appreciate your help.

Regards,

T

BGA soldering is a frequent cause of issues. Board assemblers can x-ray it to verify the BGA is soldered correctly. Good ones will do this automatically, but of course they will cost more than the cheap ones.

No other insights here. Odd that ALL of the LED pins are not working though.

Can't see a scenario where IDR mirrors ODR correctly and yet the pin isn't actually being toggled. Input and output functionality is connected at the pin itself.

TDK_0-1692803273237.png

Good luck.

If you feel a post has answered your question, please click "Accept as Solution".

If you have a solder-sample board, or unpopulated PCB left, perhaps try probing. Make sure you ball table is not mixed up or reversed.

Dump a NETLIST from the schematic / PCB and walk it to be absolutely sure everything is connected as expected. That all you grounds have the same name, and you don't have random islands of pins not connected to where they should be. Say grounds or power with different net names, or symbols.

Revisit all your DRC, design check lists and due diligence work.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Legacy member
Not applicable

Appreciate your help @TDK, @Tesla DeLorean.
The boards haven't been x-rayed during production, we're looking for a supplier who could x-ray them soon enough.

In the meantime we did some hardware-related tests:

We initially based our board's design on the MB1520-H735I-C02 devkit. However, when it come to the power supplies of the MCU, we chose not to use the internal DCDC (SMPS) and supply the internal LDO by a 3.3V coming from an external LDO instead. This hardware gives us the faulty results described higher.

Trying to solve those issues, we changed the way the STM32H735 was powered on the devkit to make it like our own design. According to the schematic of the devkit, this is called "LDO mode". According to the STM32H735 datasheet, this is possible by decoupling VCAP. The MCU is now powered though 3.3V on both VDD and VDDLDO pins. However, this modified devkit then doesn't boot and there is no access to it when trying to flash it. ("can't connect to target").

The issue is not exactly the same as on our design we still can access the MPU, but it look like there is something wrong either with the internal LDO function or in the way we want to use it.

Would you have any insights on that?

Regards,

T