cancel
Showing results for 
Search instead for 
Did you mean: 

Optimization crazyness (H733, STM32CubeIDE 1.10.1)

LCE
Principal II

Heyho,

I had some really strange error, which went away when turning optimization from "fast" to "off".

The function EthPhyInit() always returned 166 = 0xA6 - it should return "HAL_StatusTypeDef", something between 0 .. 3.

So I changed all the return values to some integer between 1..8 to find out where things go wrong, then added the last line:

uart_printf("EthPhyInit() good ->return 0\n\r");

before returning 0 when all went well.
Still, always got 166 back, even when I got "EthPhyInit() good ->return 0\n\r" on the terminal.

Until I turned optimization OFF, now all is good.

WTF is happening there? Can optimization be that bad?

 

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
 /**
  * @brief  all PHY, ETH MAC & DMA reset and init:
  *			1) EthBaseInit()	GPIO, clocks, basic stuff
  *			2) EthPhyInit()		PHY
  *			3) EthMacInit()		MAC registers
  *			4) EthDmaInit()		DMA registers
  * @PAram  -
  * @retval HAL status
  */
uint8_t EthAllInit(uint8_t u8SkipBase)
{
	static uint32_t u32CallCount = 0;
	uint8_t u8RetInit = 0xFF;

	u32CallCount++;

/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* base init */
	if( 0 == u8SkipBase )
	{
		u8RetInit = EthBaseInit();
		if( u8RetInit != HAL_OK )
		{
			#if( 1 )	// DEBUG_ETHNETIF
				uart_printf(SZC_TEXT_ERR "EthBaseInit() = %u\n\r", u8RetInit);
			#endif 	/* DEBUG_ETHNETIF */

			return u8RetInit;
		}
	}

/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* PHY initialization and configuration */
	u8RetInit = EthPhyInit();
	if( u8RetInit != HAL_OK )
	{
		#if( 1 )	// DEBUG_ETHNETIF
			uart_printf(SZC_TEXT_ERR "EthPhyInit() = %u\n\r", u8RetInit);	// ##### <- always 166 = 0xA6
			uart_printf("u32CallCount = %lu\n\r", u32CallCount);
		#endif 	/* DEBUG_ETHNETIF */

		/* do NOT return error
		 *	-> to NOT block other inits
		 */
		//return u8RetInit;
	}

/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* MACCR: more MAC registers */
	u8RetInit = EthMacInit();

...

	return u8RetInit;
}


/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 /**
  * @brief  ETH PHY initialization and configuration
  * @PAram 	none
  * @retval HAL status
  */
uint8_t EthPhyInit(void)
{
	/* KSZ8863RLL dual port PHY */

	/* wait after reset */
	HAL_Delay(50);

/* ++++++++++++++++++++++++++++++++++++++++++++++++ */
	if( EthPhyKszAlive() != HAL_OK )
	{
uart_printf(SZC_TEXT_ERR "EthPhyInit() 1\n\r");
		return 1U;	//HAL_ERROR;
	}

	/* ++++++++++++++++++++++++++++++++++++++++++++++++ */
	#if DEBUG_ETHNETIF
		uart_printf("PHY KSZ set RMII clock to internal...\n\r");
	#endif 	/* DEBUG_ETHNETIF */

	if( EthPhyKszClockSource(1) != HAL_OK )
	{
uart_printf(SZC_TEXT_ERR "EthPhyInit() 2\n\r");
		return 2U;	//HAL_ERROR;
	}

	/* PHY needs a little time after clock change */
	HAL_Delay(50);

	/* ++++++++++++++++++++++++++++++++++++++++++++++++ */
	/* check LINK status of BOTH PHY ports */
	#if DEBUG_ETHNETIF
		uart_printf("PHY link check...\n\r");
	#endif 	/* DEBUG_ETHNETIF */

	u8PhyPortActive = PHY_PORT_NONE;

	/* ETH */
	if( EthPhyLinkStatus((uint8_t)PHY_PORT_ETH, ETH_LINK_CHECK_LONG) == HAL_OK )
	{
		u8PhyPortActive = PHY_PORT_ETH;
	}

	/* USB if ETH not LINKed */
	if( PHY_PORT_NONE == u8PhyPortActive )
	{
		if( EthPhyLinkStatus((uint8_t)PHY_PORT_USB, ETH_LINK_CHECK_LONG) == HAL_OK )
		{
			u8PhyPortActive = PHY_PORT_USB;
		}
	}

	#if( 1 )	// DEBUG_ETHNETIF
		uart_printf("u8PhyPortActive = %u\n\r", u8PhyPortActive);
	#endif 	/* DEBUG_ETHNETIF */


	/* ++++++++++++++++++++++++++++++++++++++++++++++++ */
	/* power down unused port */
	if( PHY_PORT_NONE != u8PhyPortActive )
	{
		uint32_t u32PhyRegVal = 0;
		volatile uint8_t u8PhyPortUnused = PHY_PORT_NONE;
		uint8_t u8RetVal = 0;
		UNUSED(u8RetVal);

		if( PHY_PORT_ETH == u8PhyPortActive ) u8PhyPortUnused = PHY_PORT_USB;
		else u8PhyPortUnused = PHY_PORT_ETH;

		u8RetVal = EthPhyPowerDown(u8PhyPortUnused);
		#if DEBUG_ETHNETIF
			if( u8RetVal != HAL_OK ) uart_printf(SZC_TEXT_ERR "EthPhyPowerDown()\n\r");
			else uart_printf("PWRDWN unused port set\n\r");
		#endif 	/* DEBUG_ETHNETIF */

		/* check */
		HAL_Delay(10);
		u8RetVal = EthPhyReadReg(PHY_REG_PWR_DOWN, &u32PhyRegVal, u8PhyPortUnused);
		#if DEBUG_ETHNETIF
			if( u8RetVal != HAL_OK ) uart_printf(SZC_TEXT_ERR "EthPhyReadReg(PHY_REG_PWR_DOWN)\n\r");
			else
			{
				uart_printf("PHY_REG_PWR_DOWN = %04lX of unused port\n\r", u32PhyRegVal);
				if( (u32PhyRegVal & (uint32_t)PHY_REG_BIT_PWR_DOWN) == 0 ) uart_printf(SZC_TEXT_ERR "EthPhyPowerDown() failed\n\r");
			}
		#endif 	/* DEBUG_ETHNETIF */
	}

	/* ++++++++++++++++++++++++++++++++++++++++++++++++ */
	/* wait for auto-negotiation complete */
	if( PHY_PORT_NONE != u8PhyPortActive )
	{
		if( EthPhyAutoNegStatus(u8PhyPortActive) == HAL_OK )
		{
			#if DEBUG_ETHNETIF
				uart_printf("AUTO-NEGOTIATION 0 complete\n\r");
			#endif 	/* DEBUG_ETHNETIF */
		}
		else
		{
			/* re-start Auto-Negotiation */
			if( EthPhyAutoNegRestart(u8PhyPortActive) != HAL_OK )
			{
				#if( 1 )	// DEBUG_ETHNETIF
					uart_printf(SZC_TEXT_ERR "EthPhyAutoNegRestart()\n\r");
				#endif 	/* DEBUG_ETHNETIF */

				return 6U;	//HAL_ERROR;
			}

		/* wait for auto-negotiation complete */
			if( EthPhyAutoNegStatus(u8PhyPortActive) == HAL_OK )
			{
				#if DEBUG_ETHNETIF
					uart_printf("AUTO-NEGOTIATION 1 complete\n\r");
				#endif 	/* DEBUG_ETHNETIF */
			}
			else
			{
				#if( 1 )	// DEBUG_ETHNETIF
					uart_printf(SZC_TEXT_ERR "EthPhyAutoNegStatus() TIMEOUT\n\r");
				#endif 	/* DEBUG_ETHNETIF */

				return 7U;	//HAL_TIMEOUT;
			}
		}
	}
	else
	{
		#if( 1 )	// DEBUG_ETHNETIF
			uart_printf(SZC_TEXT_ERR "u8PhyPortActive = PHY_PORT_NONE\n\r");
		#endif 	/* DEBUG_ETHNETIF */

		return 8U;	//HAL_ERROR;
	}

uart_printf("EthPhyInit() good ->return 0\n\r");

	return 0U;	//HAL_OK;
}

 

PS:

- STM32H733 on a custom board

- working with that for > 1 year now, with lots of printf for debugging (UART DMA), never had something like this

- same on other boards

- still using STM32CubeIDE 1.10.1

4 REPLIES 4
Ozone
Principal III

> Until I turned optimization OFF, now all is good.
> WTF is happening there? Can optimization be that bad?

Rarely.
But code can be that "bad".

Just drop e.g. a few "volatile" specifiers for peripheral registers or variables in interrupt code, and any optimisation level > 0 will "break" it.

 

LCE
Principal II

... I played a lot with that.

In this case, all of the problems not happening in ISRs, just simple non-OS start-up code / inits, even before the main loop.

The horrifying thing is that this is so simple, telling a function to return 0, but what's coming back is some seemingly random number.

TDK
Super User

There's no problems with the code presented as far as I can tell, even with optimization or cache turned on.

How does uart_printf work? If you use DMA, you will need to handle cache appropriately. Technically, you should cast u8RetInit to (int) in your printf call, though I don't think that's the issue.

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

Have you tried stepping it at the instruction level ?

Have you tried any other optimisation settings ?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.