Missing 3V3 on JTAG/SWD connector on Portenta breakout board?

Hello, I am using your Portenta module with your Portenta breakout board, STM32CubeIDE and ST-Link SWD emulator.

Sometimes the ST-Link works OK and I can debug my application, but sometimes the ST-Link doesn't connect.
When I am unable to connect, the reason is that the ST-Link sees no 3V3 on the BREAKOUT_BOARD.JTAG_CONNECTOR.1 pin, where 3V3 are expected.
So I checked on the Portenta the voltages generated by the U10 PMIC: while 3V1 are generated OK by the PMIC, VCAP and 3V3 are NOT output.
If there is no 3V3, I cannot use the JTAG/SWD, and I am stuck.

I wonder what is the reason why the PMIC won't output the 3V3 voltage on the SW2LX pin of the PMIC U10 MC34PF1550A , while the 3V1 are generated OK?
Maybe an I2C setting is needed?
But I can't access the JTAG interface, so I am stuck.

Have you any hints?

Many thanks for your help

Best regards
Michele Sponchiado

I checked the PMIC chip, and while the sch is reporting a MC34PF1550A4, it is really a MC34PF1550A0 one, so it seems not a pre-programmed one.
I confirm that the only voltage generated at startup is 3V1 from SW3, so it seems that the PMIC is programmed to generate just the 3V1 at startup, the other voltages need a runtime programming of the chip, as stated in GitHub - olback/h7-bootloader-rev.
Now, I will try to force the 3V3 con the ST-Linkv3 to check if I can access the SWD.

Yes I have the same problem, which I described here. One possibility that could work is to supply a 3V3 pin of the breakout board by an external power supply.

Is your orange LED also turned on?

Hi, Eschi!
Thanks for your hint!

ATM I am out of office, I'll let you know if the orange LED is lit or not, I just do not remember right now.

About the 3V3:

  • if I supply the voltage from an external power,
  • then I connect through JTAG and program the processor
  • then finally I send the I2C commands to program the PMIC,

the 3V3 voltage would be supplied from both the PMIC and the external supply: wouldn't they conflict with each other? How did you solve?

Many thanks again for your help!

I didn't solve the problem yet :sweat_smile: Maybe something else on my Portenta is broken.
I don't think that it is recommended to program the the PMIC by yourself. What you should try is to burn the bootloader via JTAG.

  • supply the 3V3 by external power supply
  • connect the board via JTAG
  • maybe use the STM32CubeProgrammer to check if you can connect to the STM32
  • use the Arduino IDE and burn the bootloader using the STLink as programmer

You can also burn the bootloader using the STM32CubeProgrammer. Therfore, you have to download the Bootloader file (.bin or .elf) from Github here.

  1. Then follow these instructions
    Connect your Portenta H7 to the Breakout board and power via USB.
  2. Connect the STM programmer to your PC via USB and to the JTAG connector on
    the Portenta Breakout.
  3. Open STM32Cube and click on the 'connect' green button to establish
    connection between the PC and the programmer (upgrade firmware if
    necessary).
  4. Head over the icons on the left hand side and click 'Erasing and Programming'
    icon (marked with an orange rectangle in the image below).
  5. Load the bootloader file.
  6. Click 'Start Programming' button.

If you want to program the PMIC yourself, i don't think that there will be a conflict of the external supply and the PMIC, since they are on the same voltage level.

Hi, I finally managed to boot and debug both the Portenta cores using STM32Cube IDE and Programmer and a ST-Linkv3 emulator!

In the following a brief todo list

The 3V3 must be supplied externally using a power supply; I have used the breakout board and the 3V3 and GND pins from the I2S connector.
Then, check that the breakout BOOT dip switch is set on the same side of the "ARDUINO PRO" writing on the breakout board.
Connect the ST-Link v3 SWD header to the strip on the breakout, the flat on the header must be placed aligned with the strip suide toward the PWM/SPDIF strips, not toward the USB connector.
Power up the Portenta using the USB C connector.
Press the reset button on the Portenta (IDK if this is necessary)
Then, using the STM32 programmer you should be able to connect with the M7 core.
Check that the option byte BCM4 is set; if not, set it and program the user option bytes.
Disconnect the STM32 programmer.
The previous check obviously is needed just only the first time; please check:

if you want further details

Then, be sure to follow the STM32 cube debug setup described here:

https://www.st.com/resource/en/application_note/dm00629855-getting-started-with-projects-based-on-dualcore-stm32h7-microcontrollers-in-stm32cubeide-stmicroelectronics.pdf

You must include in the startup code the PMIC programming, as described in:

Anyway the codes you must send to the PMIC (the I2C address to use is: (0x8 <<1)) are the following:

// we set the 3V3 externally
#define def_3V3_SW2_externally_supplied 1

const uint8_t PMIC_ADDRESS= (0x08 << 1);

#define PMIC_1550_DEVICE_ID 0b01111100 // 0x7c

typedef struct _type_struct_PMIC_register_address_value
{
	uint8_t address;
	uint8_t value;
}__attribute__((packed)) type_struct_PMIC_register_address_value;

const type_struct_PMIC_register_address_value PMIC_SETUP[] =
{
	{.address = 0x4F, .value = 0x00}, 	// LDO2_VOLT: 1.80V
	{.address = 0x50, .value = 0x0F},	// LDO2_CTRL: VLDO2_EN = 1, VLDO2_STBY_EN = 1, VLDO2_OMODE = 1, VLDO2_LPWR = 1
	{.address = 0x4C, .value = 0x05},	// LDO1_VOLT: 1.00V
	{.address = 0x4D, .value = 0x03},	// LDO1_CTRL: VLDO1_EN = 1, VLDO1_STBY_EN = 1
	{.address = 0x52, .value = 0x09},	// LDO3_VOLT: 1.20V
	{.address = 0x53, .value = 0x0F},	// LDO3_CTRL: VLDO3_EN = 1, VLDO3_STBY_EN = 1, VLDO3_OMODE = 1, VLDO3_LPWR = 1
	{.address = 0x9C, .value = 0x80},	// enable LED drive --> Not documented? No mention of 0x9C in the datasheet.
	{.address = 0x9E, .value = 0x20},	// LED drive controlled by software --> Not documented? No mention of 0x9E in the datasheet.
	{.address = 0x42, .value = 0x02},	// SW3_CTRL1: SW3_ILIM = 1.5A
	{.address = 0x94, .value = 0xA0},	// VBUS Current limit = 1500mA

#if !def_3V3_SW2_externally_supplied
	{.address = 0x3B, .value = 0x0F},	// SW2_CTRL: SW2_EN = 1, SW2_STBY_EN = 1, SW2_OMODE = 1, SW2_LPWR = 1
#endif
	{.address = 0x35, .value = 0x0F},	// SW1_CTRL: SW1_EN = 1, SW1_STBY_EN = 1, SW1_OMODE = 1, SW1_LPWR = 1
	{.address = 0x42, .value = 0x01},	// This write is not part of the bootloader itself but it’s sent just before your Arduino code runs. fixup3V1Rail

};

Remember that the OSCEN signal must be set to enable the 27MHz and 32kHz oscillators, so set PH1 as GPIO output and set its value to high to remove the standby from the frequency generators U17 and U18 on the Portenta.
Please note that the oscillators must be programmed in "Bypass clock source" mode because you have external frequency generators, do NOT select the "Crystal/Ceramic resonator" option!

I use the launch group as described in the ST pdf app note dm00629855 previously referred and it works OK.

Easy...! :frowning:

Hi,

Thank you for the solution, I'm trying to implement it. Would you be able to provide an example?

When I connect power to the device, it seems to not have time for the I2C communication before the PMIC already cuts power.

  /* USER CODE BEGIN SysInit */
	MX_I2C1_Init();
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x4F, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x00, 1, HAL_MAX_DELAY); //LDO2_VOLT: 1.8V
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x50, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x0F, 1, HAL_MAX_DELAY); //LDO2_CTRL: VLDO2_EN:=1, VLDO2_STBY_EN:=1, VLDO2_OMODE:=1, VLDO2_LPWER:=1
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x4C, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x05, 1, HAL_MAX_DELAY); //LDO1_VOLT: 1.00V
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x4D, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x03, 1, HAL_MAX_DELAY); //LDO1_CTRL: VLDO1_EN = 1, VLDO1_STBY_EN = 1
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x52, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x09, 1, HAL_MAX_DELAY); //LDO3_VOLT: 1.20V
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x53, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x0F, 1, HAL_MAX_DELAY); //LDO3_CTRL: VLDO3_EN = 1, VLDO3_STBY_EN = 1, VLDO3_OMODE = 1, VLDO3_LPWR = 1
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x9C, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x80, 1, HAL_MAX_DELAY); //0x80
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x9E, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x20, 1, HAL_MAX_DELAY); //0x20
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x42, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x02, 1, HAL_MAX_DELAY); //SW3_CTRL1: SW3_ILIM = 1.5A
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x94, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0xA0, 1, HAL_MAX_DELAY); //VBUS Current limit = 1500mA
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x3B, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x0F, 1, HAL_MAX_DELAY); //SW2_CTRL: SW2_EN = 1, SW2_STBY_EN = 1, SW2_OMODE = 1, SW2_LPWR = 1
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x35, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x0F, 1, HAL_MAX_DELAY); //SW1_CTRL: SW1_EN = 1, SW1_STBY_EN = 1, SW1_OMODE = 1, SW1_LPWR = 1
	HAL_I2C_Mem_Write(&hi2c1, (uint8_t)PMIC_ADDRESS, 0x42, I2C_MEMADD_SIZE_8BIT, (uint8_t *)0x01, 1, HAL_MAX_DELAY); //3V1 Rail
  /* USER CODE END SysInit */

Kind regards,

Rick

Hi, Rick_HFX!

In the following a snippet of the code in the H7 main.c file, please let me know if you need further info.

Please take note that the RCC Power parameters must be set as/similar to the one in the next screen grab, else the HAL_PWREx_ConfigSupply routine in SystemClock_Config() will hang.

Anyway in my code the PMIC is programmed BEFORE calling the SystemClock_Config() routine: voilà:

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

#define def_program_PMIC 1

#if def_program_PMIC

// we set the 3V3 externally
#define def_3V3_SW2_externally_supplied 1

const uint8_t PMIC_ADDRESS= (0x08 << 1);
#define PMIC_1550_DEVICE_ID 0b01111100 // 0x7c

typedef struct _type_struct_PMIC_register_address_value
{
	uint8_t address;
	uint8_t value;
}__attribute__((packed)) type_struct_PMIC_register_address_value;

const type_struct_PMIC_register_address_value PMIC_SETUP[] =
{
	{.address = 0x4F, .value = 0x00}, 	// LDO2_VOLT: 1.80V
	{.address = 0x50, .value = 0x0F},	// LDO2_CTRL: VLDO2_EN = 1, VLDO2_STBY_EN = 1, VLDO2_OMODE = 1, VLDO2_LPWR = 1
	{.address = 0x4C, .value = 0x05},	// LDO1_VOLT: 1.00V
	{.address = 0x4D, .value = 0x03},	// LDO1_CTRL: VLDO1_EN = 1, VLDO1_STBY_EN = 1
	{.address = 0x52, .value = 0x09},	// LDO3_VOLT: 1.20V
	{.address = 0x53, .value = 0x0F},	// LDO3_CTRL: VLDO3_EN = 1, VLDO3_STBY_EN = 1, VLDO3_OMODE = 1, VLDO3_LPWR = 1
	{.address = 0x9C, .value = 0x80},	// enable LED drive --> Not documented? No mention of 0x9C in the datasheet.
	{.address = 0x9E, .value = 0x20},	// LED drive controlled by software --> Not documented? No mention of 0x9E in the datasheet.
	{.address = 0x42, .value = 0x02},	// SW3_CTRL1: SW3_ILIM = 1.5A
	{.address = 0x94, .value = 0xA0},	// VBUS Current limit = 1500mA

#if !def_3V3_SW2_externally_supplied
	{.address = 0x3B, .value = 0x0F},	// SW2_CTRL: SW2_EN = 1, SW2_STBY_EN = 1, SW2_OMODE = 1, SW2_LPWR = 1
#endif
	{.address = 0x35, .value = 0x0F},	// SW1_CTRL: SW1_EN = 1, SW1_STBY_EN = 1, SW1_OMODE = 1, SW1_LPWR = 1
	{.address = 0x42, .value = 0x01},	// This write is not part of the bootloader itself but it’s sent just before your Arduino code runs. fixup3V1Rail

};

typedef union _type_union_PMIC_register_address_value
{
	type_struct_PMIC_register_address_value s;
	uint8_t v[2];
}type_union_PMIC_register_address_value;

static void PMIC_program(void)
{
#define def_I2C_timeout_ms 10
	// let's check if I2C is OK
	// the PMIC ID is 0111 1100 = 0x7c
	// we read the device ID and check if it is OK
	// Register DEVICE_ID - ADDR 0x00
	uint32_t device_id_checked_OK = 0;
	uint8_t device_id = 0;
	{
		if (HAL_OK ==  HAL_I2C_Mem_Read(&hi2c1, PMIC_ADDRESS, 0, 1, &device_id, sizeof(device_id) / sizeof(uint8_t), def_I2C_timeout_ms))
		{
			if (PMIC_1550_DEVICE_ID == device_id)
			{
				device_id_checked_OK = 1;
			}
		}
	}
	if (!device_id_checked_OK)
	{
		Error_Handler();
	}

	uint32_t num_errors = 0;
	for (uint32_t i = 0; i < sizeof(PMIC_SETUP) / sizeof(PMIC_SETUP[0]); i++)
	{
		type_union_PMIC_register_address_value u;

		// readout the current table entry we have to set
		u.s = PMIC_SETUP[i];

		// write the register value
		{
			HAL_StatusTypeDef h = HAL_I2C_Mem_Write(&hi2c1, PMIC_ADDRESS, u.s.address, sizeof(u.s.address) / sizeof(uint8_t), &u.s.value, sizeof(u.s.value) / sizeof(uint8_t), def_I2C_timeout_ms);
			if (HAL_OK != h)
			{
				num_errors++;
				break;
			}
		}

		// re-read the register value just written
		uint8_t value = 0;
		{
			// read the register into the variable, the register address is taken from the table
			HAL_StatusTypeDef h = HAL_I2C_Mem_Read(&hi2c1, PMIC_ADDRESS, u.s.address, sizeof(u.s.address) / sizeof(uint8_t), &value, sizeof(value) / sizeof(uint8_t), def_I2C_timeout_ms);
			if (HAL_OK != h)
			{
				num_errors++;
				break;
			}
		}

		// check if the value is the one we have written
		{
			if (value != u.s.value)
			{
				num_errors++;
				break;
			}
		}
	}

	if (num_errors)
	{
		 Error_Handler();
	}
}
#endif


/* USER CODE END 0 */

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

  /* USER CODE END 1 */
/* USER CODE BEGIN Boot_Mode_Sequence_0 */
  int32_t timeout;
/* USER CODE END Boot_Mode_Sequence_0 */

/* USER CODE BEGIN Boot_Mode_Sequence_1 */

#if !def_program_PMIC
  /* Wait until CPU2 boots and enters in stop mode or timeout*/
  timeout = 0xFFFF;
  while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
  if ( timeout < 0 )
  {
  Error_Handler();
  }
#endif
/* USER CODE END Boot_Mode_Sequence_1 */
  /* MCU Configuration--------------------------------------------------------*/

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

  /* USER CODE BEGIN Init */
#if def_program_PMIC
  // set OSCEN = PH1 to 1 to enable the oscillators
  __HAL_RCC_GPIOH_CLK_ENABLE();
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = 0;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  HAL_GPIO_WritePin(GPIOH, GPIO_PIN_1, 1);

  MX_I2C1_Init();
  PMIC_program();

  //not needed anymore, the RCC_BOOT_C2 bit is better set in the option bytes OB from the STM32 Programmer's menu --> allow cpu2 (CM4) boot
  //RCC->GCR |= 1 << 3;
  //HAL_RCCEx_EnableBootCore(RCC_BOOT_C2);

	// when debugging with the emulator, the clock won't stop!
	#if 0
	  /* Wait until CPU2 boots and enters in stop mode or timeout*/
	  timeout = 0xFFFF;
	  while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
	  if ( timeout < 0 )
	  {
		  Error_Handler();
	  }
	#endif
#endif

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();
/* USER CODE BEGIN Boot_Mode_Sequence_2 */

	/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
	HSEM notification */
	/*HW semaphore Clock enable*/
	__HAL_RCC_HSEM_CLK_ENABLE();
	/*Take HSEM */
	HAL_HSEM_FastTake(HSEM_ID_0);
	/*Release HSEM in order to notify the CPU2(CM4)*/
	HAL_HSEM_Release(HSEM_ID_0,0);

	/* wait until CPU2 wakes up from stop mode */
	timeout = 0xFFFF;
	while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
	if ( timeout < 0 )
	{
		Error_Handler();
	}
/* USER CODE END Boot_Mode_Sequence_2 */

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

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

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

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



I am not sure to fully understand the meaning of the phrase:

  • "When I connect power to the device, it seems to not have time for the I2C communication before the PMIC already cuts power."
  • Do you mean that the debugger disconnects while you execute the program?

Please let me know if you need further info.

BR
Michele

Hi Michele,

Thanks a lot for the example! I made a mistake in setting the SupplySource parameter incorrectly.

Only problem remaining now is that the 3v3 supply is not enabled even though I do send the command to boot it to the PMIC over I2C.

Any clue what this could be?

Kind regards,

Rick

Hi, Rick_HFX!

I use the externally supplied 3V3 voltage, so I have not checked the PMIC SW2 output.
Anyway, I think that maybe you need to set the registers:

  • SW2_VOLT - ADDR 0x38
  • SW2_STBY_VOLT - ADDR 0x39
  • SW2_SLP_VOLT - ADDR 0x3A

to the correct value to get the 3V3 voltage output.

I think that if you set the bits [5:0] to a value equal or greater than 7, the 3V3 will be output, please check:

  • Table 31. SW1 and SW2 output voltage setting

By default, they should be reset to 0, so I expect about 1V1 is generated right now from SW2.

Hi Michele,

Thanks, the problem turned out to be an old piece of code I did not remove. (stupid me)

Thanks a lot for your help!

kind regards,

Rick

Hi, Rick_HFX!

I am very happy that you solved!

But I wonder if you can tell me if the PMIC registers 0x38 through 0x3A programming was needed or not?

BR
Michele

Hi Michele,

You do not actually need to set these registers, it also works without setting them.

Next challenge, replacing the input resistor (100k) and capacitor (100nF) for the adc reference voltage, as it only allows 31uA of current and it starts dropping when using all three ADC's....

Kind regards,

Rick

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.