External oscillator hiccups

Because there is no support for HSE clock in the system_clock.c of TARGET_STM32U575xG I tried to add the right code:

#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) )
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0};
 
    __HAL_RCC_PWR_CLK_ENABLE();
    if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
        return 0; // FAIL
    }

    // Enable HSE oscillator and activate PLL with HSE as source
    RCC_OscInitStruct.OscillatorType        = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI48;
    if (bypass == 0) {
        RCC_OscInitStruct.HSEState            = RCC_HSE_ON; // External xtal on OSC_IN/OSC_OUT
    } else {
        RCC_OscInitStruct.HSEState            = RCC_HSE_BYPASS; // External clock on OSC_IN
    }
#if DEVICE_USBDEVICE
    RCC_OscInitStruct.HSI48State            = RCC_HSI48_ON;
#else
    RCC_OscInitStruct.HSI48State            = RCC_HSI48_OFF;
#endif /* DEVICE_USBDEVICE */
    RCC_OscInitStruct.PLL.PLLSource         = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLState          = RCC_PLL_ON;
#if HSE_VALUE==10000000
    RCC_OscInitStruct.PLL.PLLM              = 1; // VCO input clock = 10 MHz (10 MHz / 1)
#else
#error Unsupported externall clock value, check HSE_VALUE define
#endif
    RCC_OscInitStruct.PLL.PLLN              = 16; // VCO output clock = 160 MHz (10 MHz * 16)
    RCC_OscInitStruct.PLL.PLLP              = 2;
    RCC_OscInitStruct.PLL.PLLQ              = 2;
    RCC_OscInitStruct.PLL.PLLR              = 1;  // PLL clock = 160 MHz

    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        return 0; // FAIL
    }

#if DEVICE_USBDEVICE
    RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
    PeriphClkIniRCC_PeriphClkInittStruct.UsbClockSelection    = RCC_USBCLKSOURCE_HSI48; /* 48 MHz */
    if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) {
        return 0; // FAIL
    }
#endif /* DEVICE_USBDEVICE */

    // Select PLL clock as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
    RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK; // 160 MHz
    RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;         // 160 MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;           // 160 MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;           // 160 MHz
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
        return 0; // FAIL
    }
    return 1; // OK
}
#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */

But the external oscillator won’t startup with the config:

        "overrides": {
            "clock_source" : "USE_PLL_HSE_XTAL",
            "lse_available" : "1"
        },
        "macros_add": [
            "HSE_VALUE=10000000"
        ],

If I measure on one of the osc pins with the scope, the oscillation begins at 380Hz and fades down.

This is cycling. However the test Hello world is working. I think there is a fallback to internal osc. I did a test with CumbeMX and there it works if you do the right clock config. There I had 10MHz as expected. It means that my hardware is OK. What I’m missing here?

Hmm… you might try comparing all of the RCC registers from the Mbed project vs the CubeMX project, to see what got set differently. Or you could try swapping out the system_clock.c file entirely and, if that works, swapping pieces between the Mbed and CubeMX versions until it works.

I have seen that if you zoom in on the scope there is a 10MHz added to the 300Hz that is fading out. It means that there is a stability issue with the oscillator. Maybe due to a missing setting? I will do the check as you propose.

Two other issues are:

1/ I use STM32CubeProgrammer with a ST-link2 clone with not working HW reset pin (as I can measure and read on the net). Sometimes the MCU is locking up and cannot connect anymore. If I move the USB cable to another PC (Linux) and do several times the following command I can erase the chip and unblock the lockup. Also, sometimes the reset line of the chip stays low for an unknown reason.

sam@elitebook-845:~/git/hmipanel$ sudo st-flash --connect-under-reset erase 0x08000000 0x100000
st-flash 1.7.0-352-g8c581c3
2024-01-08T18:57:22 WARN common.c: NRST is not connected
2024-01-08T18:57:22 ERROR common.c: Soft reset failed: error write to AIRCR
2024-01-08T18:57:22 INFO common.c: STM32U575_U585: 786 KiB SRAM, 1024 KiB flash in at least 8 KiB pages.
-> Flash page at 0x80fe000 erased (size: 0x2000)
Mass erase completed successfully.
2024-01-08T18:57:23 INFO common.c: NRST is not connected --> using software reset via AIRCR

2/ Putty is very sensitive to unexpected fall downs of the Tx pin or some deviating serial info. It happens ofthen that I can read the serial data on the scope but it is not appearing in Putty, even with the right serial settings.

There are several points:

1/ Issues with Putty. There was first an issue with a connector that was not aligned in the right way in the socket. That’s the danger if you use one row FTDI and a header with wide gap. Another thing is that the speed on the scope shows kbit/s which is misleading the same as the baudrate in Putty. If I measure 9.600 kbit/s (9600Hz or 104µs) it’s in Putty a baudrate of 9600 and not (9600 / 8) baud as you would expect. (Baud = symbols per second)

2/ Issues with lockup. I think that due to the oscillator issue the device is going in a lockup situation and the next programming cycle will be not valid (you have to ignore the programmed succesful message). In that case I reconnect and I do first a full erase before programming again. When the lockup in Windows is not recoverable I use the Linux pc. It’s a proof that there are some issues with the ST-Link clones. I ordered a real one and will put the clone away.

3/ The clock issue. I did a one by one line compare with working Cube-IDE code and came to a function that is almost exactly the same:

//#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) )
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};

#if DEVICE_USBDEVICE
    RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0};
#endif /* DEVICE_USBDEVICE */
    
    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOH_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_PWR_CLK_ENABLE();
    if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
        return 0; // FAIL
    }

    // Enable HSE oscillator and activate PLL with HSE as source
    RCC_OscInitStruct.OscillatorType        = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI48;
    if (bypass == 0) {
        RCC_OscInitStruct.HSEState            = RCC_HSE_ON; // External xtal on OSC_IN/OSC_OUT
    } else {
        RCC_OscInitStruct.HSEState            = RCC_HSE_BYPASS; // External clock on OSC_IN
    }
#if DEVICE_USBDEVICE
    RCC_OscInitStruct.HSI48State            = RCC_HSI48_ON;
#else
    RCC_OscInitStruct.HSI48State            = RCC_HSI48_OFF;
#endif /* DEVICE_USBDEVICE */
#if HSE_VALUE==10000000UL
    RCC_OscInitStruct.PLL.PLLState          = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource         = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMBOOST         = RCC_PLLMBOOST_DIV1;
    RCC_OscInitStruct.PLL.PLLM              = 1; // VCO input clock = 10 MHz (10 MHz / 1)
#else
#error Unsupported external clock value, check HSE_VALUE define
#endif
    RCC_OscInitStruct.PLL.PLLN              = 16; // VCO output clock = 160 MHz (10 MHz * 16)
    RCC_OscInitStruct.PLL.PLLP              = 2;
    RCC_OscInitStruct.PLL.PLLQ              = 2;
    RCC_OscInitStruct.PLL.PLLR              = 1;  // PLL clock = 160 MHz
    RCC_OscInitStruct.PLL.PLLRGE            = RCC_PLLVCIRANGE_1;
    RCC_OscInitStruct.PLL.PLLFRACN          = 0;

    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        return 0; // FAIL
    }

#if DEVICE_USBDEVICE
    RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
    PeriphClkIniRCC_PeriphClkInittStruct.UsbClockSelection    = RCC_USBCLKSOURCE_HSI48; /* 48 MHz */
    if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) {
        return 0; // FAIL
    }
#endif /* DEVICE_USBDEVICE */

    // Select PLL clock as system clock source and configure the HCLK, PCLK1 and PCLK2 clock dividers
    RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3);
    RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK; // 160 MHz???? the devil
    RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;         // 160 MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;           // 160 MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;           // 160 MHz
    RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;           // 160 MHz
    
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
        return 0; // FAIL
    }
   return 1; // OK

}
//#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */

After analysis the devil is in the line :

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 160 MHz??? the devil

As soon as this line is in the code, the external oscillator begins to hiccup and the sine wave is not continue anymore. The 300kHz effect is due to the fact that the timebase of the scope is too low and you get an undersampling effect on the 10Mhz. If I stay on 200ns/div the hiccup is better visible. As soon as I remove this line the hiccup is done, but I think this is not right because the selector must be obviously on PLL. You can clearly see it in the Cube config :

I found the solution. The difference is that there is no while(1){} in my main. That’s the default if you generate a new mbed program. And a while(1) is the default at CubeIDE. When you exit the main function, the controller is waking up at a certain rate and is restarting the HSE with a transition effect at the piont you connect the HSE source to the SysClk (the devil line). Strange that the Xtal signal stays stable if you use another clock source.

In the system_clock.c there is a note:

 * @note   This function is called in mbed_sdk_init() function (targets/TARGET_STM/mbed_overrides.c)
 *         and after each deepsleep period in hal_deepsleep() (targets/TARGET_STM/sleep.c)
 MBED_WEAK void SetSysClock(void) ...

My suggestion is to generate a Hello world demo program with a while loop after doing ‘mbed-tools new’.

The screenshot without a while loop. The Red data is the serial ‘Hello world’. The Oscillator runs during that period. (Yellow line) The sine wave is an undersampling effect. The envelope is the real 10Mhz signal that fades out when the main is finished and the controller sleeps. After a while there is a wake up and the HSE starts up again for a short time.

1 Like

How can I make sure that these pieces of code are going into the mbed project? What is the procedure to contribute?

Hello,

if you mean the clock settings and memory settings correction then you can mape Pull request on github - ARMmbed/mbed-os: Arm Mbed OS is a platform operating system designed for the internet of things (github.com)

For more Contributing to Mbed OS - Contributing | Mbed OS 6 Documentation

However keep in mind the Mbed team stopped development two years ago and it is up to community. That is reason why MbedCE was created.

BR, Jan