SetSysClock fail on my own board similar to Nucleo- STM32L476

Hello,

  1. I made my motherboard having various interfaces and plug in Nucleo-STM32L476 board. The code runs very well reliably for about 2 years. I use mbed Studio on desktop and OS ver 5.15.

  2. I copied the Nucleo circuit components such as MCU chip, switches, resistors, capacitors and crystals ( 8MHZ and 32.768 Khz) and made my own PCB. I am using a squarish 8 MHz metal can crystal (surface mounted) and a tubular metal 32.768 crystal with leads. I broke up the upper part of Nucleo board as a flasher/programmer and connected it with 4 wires to my board. The code compiles well, downloads well but does not start as the SysClock failed. I got the following message on console at 9600 baud.

++ MbedOS Error Info ++
Error Status: 0x80FF0100 Code: 256 Module: 255
Error Message: Fatal Run-time error
Location: 0x800501F
Error Value: 0x0
Current Thread: Id: 0x0 Entry: 0x8000451 StackSize: 0x0 StackMem: 0x8000481 SP: 0x20017F78
For more info, visit: mbedos-error
– MbedOS Error Info –
SetSysClock failed

  1. I felt that my external crystals and capacitors may not be doing exactly the same as they are doing in Nucleo board so I decided to use internal HSi or MSI clocks.
  2. I looked up such issues raised by many users in 2020 and tried their tricks as follows:
  3. I added a file called “mbed_app.json” and added an over ride so that internal HSI with PLL option is selected . the error continued. i used second option if MSI with PLL. that also failed.
  4. I tinkered with sysclock.c as suggested in one posts so that MSI is never selected and HSI is always enabled and selected.
  5. I always got the same error code.
  6. I tested the board for "blink " & “Hellow World” on standard console UART examples, using ST’s proprietory IDE called CubeIDE. That allows internal 8 MHz crystal and 80 MHz sysclock operation. that shows that internal clocks are working fine.
  7. My issue is that mbed’s sysclock looks up for working 32 KHz clock and unless it is there, it does not allow use of internal clocks. How to work with internal clocks without worrying about external crystals, capacitance loading and all that stuff?
  8. I know this is not a good practice, but can I tinker with sysclock.c such that whenever a function is called it always runs the code of SetSysClock_PLL_HSI()?

Hello,

if you made your own board and it is not 1:1 with Nucleo board, then you need to set up Custom target what will inherit from same MCU like is on Nucleo but with different pinout, clock etc.

BR, Jan

Thank you Jan Kamidra. I will go through these links carefully.

I have a fundamental question:

If I make a ditto copy of Nucleo board’s circuit and keep all components such as MCU chip, crystals, resistors & capacitors , then do I have to still select “custom target”.

How would the STLink programmer/ debugger portion in Nucleo board know that what follows it, is not manufactured by ST but by a random person like me?

I do not think this is important, but I believe for the ST-link is important the MCU and not the board or autor name. However in MbedStudio (I do not use it) you was able to set custom settings for probe.
For example i use ST-Link from Nucleo-L152 for uploading Blackpill-F411. STM32CubeProgrammer still show Nucleo-L152 as board name but with correct MCU F411 and it is working.

More about clock

  • You see this error because every variant of clock settings failed (in your case just one because MSI is one and default settings for STM32L4)
  • You wrote that your board runs with STm32CubeIDE settings. Did you do a comparison between Cube and Mbed Os clock settings? All clock functions are MBED_WEAK so can be easily overridden directly in main. So most easy is copy&paste function from system_clock.c into your main and modified settings according to Cube.
  • oh and be sure your code is completely re-compiled when you change something in a .json file or you have to run Clean build

BR, Jan

Thanks Jan.

  1. I do not know where exactly teh clock settings are initiated in mbed.

  2. I opened CubeIDE, selected internal high speed RC clock (probably 16 MHz) and using PLL made it 80 MHz system clock that L476 can run at comfortably.
    Next I wrote a simple UART code to print Hello World at 115200 baud with a counter getting incremented and counter value printed every 1 second. I also used an LED and a buzzer to turn for 100 ms. The CubeIDE code ran successfully.

  3. I copied the SystemClock_Config function that sets clock registers in CubeIDE in a text file and have attached it here for you. The registers seem ok to carry the values which I wanted.

  4. Next I opened mbed Studio and added function SystemClock_Config to main.cpp. I also invoked it first thing inside main() function. The result was the same. The Sysclock failed to start. I have put error handler empty function as i was not sure what output device (console or LED) to use to signal error condition since clock itself has not started.

  5. I took a Nucleo 476 board where my code runs perfectly and ran this code with SystemClock_Config. teh code compiled and downlaoded but did not run. When i commented SystemClock_Config() in main(), my code ran alright.

It means that whatever I am doing to clock registers is disturbing what was correctly set by mbed drivers.

  1. What is the correct way to use code of SystemClock_Config in mbed main() function?

Hardware Difference between Nucleo 476 and my custom built target board:
I am connecting only 4 wires from CN11 of STLink programmer board and my target board Clock, data, GND and RESET. I am leaving open pin 1 VDD target and SWO. Could this be the cause of clock not starting in custom board? I guess in Nucleo board - all 6 wires are connected by pcb tracks.

(Attachment SystemClockConfig.txt is missing)

The text file I attached was rejected by your email server, so I copy pasting the code here:

void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}

/** 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_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    RCC_OscInitStruct.PLL.PLLM = 1;
    RCC_OscInitStruct.PLL.PLLN = 10;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
    RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

I believe the way to place the clock config into main is right because… how i wrote above.

#include "mbed.h"

extern void SystemClock_Config(void){
   // here place your working clock from CubeIDE
}

// rest of main

Try to place the settings below to your mbed_app.json.This will allow you to try all 3 variants of clock settings. HSI and MSI should work because that is not depend on external hardware. And for sure disable LSE (maybe LP APIs like LPticker will be also necessary to remove).

{
    "target_overrides": {
        "*": {
            "target.clock_source": "USE_PLL_HSE_XTAL | USE_PLL_HSI | USE_PLL_MSI",
            "target.lse_available": 0
        }
    }
}

BR, Jan

Sorry Jan,

Despite your best advice and my trials, it still remains blocked.

General: In mbed studio I selected "STM32Link(S.No…) as a device to configure and NUCLEO-L476RG as target name and build target.
In build target there is a massive drop-down menu including custom boards but I could not find anything that was close to STM32L4 or L476 board. most of the custom boards are branded boards from manufacturer and there is no scope fo homegrown board.

I tried out following options:

  1. I added extern to my SystemClock_Config function definition. Placed SystemClock_Config() and error handler at the bottom of main(). First task in main was to invoke SystemClock_Config().
    I kept mbed_app.json empty by commenting out all code.
    Got the same error at 9600 baud as before.

  2. I set baud rate at 9600. Earlier my code used baud = 500000 but under error condition it always defaulted to 9600. I inserted several printf() at many strategic locations inside SystemClock_Config(). There was no print on the screen.
    It seems the crash is at initialization code generated by mbed and the CPU never enters main() at all.

  3. I added your code mbed_app.json with all 3 options. this time the error message did not come but the CPU also did not start.

  4. I edited your statement to

// Solution given by Jan Kamidra
{
“target_overrides”: {
“*”: {
“target.clock_source”: “USE_PLL_HSE_XTAL | USE_PLL_HSI | USE_PLL_MSI”,
//“target.clock_source”: “USE_PLL_HSI”,
//“target.clock_source”: “USE_PLL_MSI”,
“target.lse_available”: 0
}
}
}

and chose 2nd or 3rd line, keeping 2 other lines commented.

Ok, if you still get the error SetSysClock failed then your program does not jump to clock function in the main, because your version in main does not have this error line.

Try to change from this

extern void SystemClock_Config(void){
   // here place your working clock from CubeIDE
}

to this

extern "C" void SystemClock_Config(void){
   // here place your working clock from CubeIDE
}

That is because the main is usually main.cpp and the clock is in system_clock.c and not .cpp

And for sure did you perform Clean build time to time?

BR, Jan

Hello,

I added “C” to declaration as suggested and also did clean build. I enabled PLL_HSI

//“target.clock_source”: “USE_PLL_HSE_XTAL | USE_PLL_HSI | USE_PLL_MSI”,
“target.clock_source”: “USE_PLL_HSI”,
//“target.clock_source”: “USE_PLL_MSI”,

I have set baudrate as 9600.
I still got the same error.

I guess I will have to get inside the mbed startup code where clok registers are initialized.

Can you please tell me where to start.

BTW, I am a very very ancient machine language and assembly language programmer so you can ask me to try out anything.

Hello Jan,

  1. I checked that board is not damaged. With CodeIDE, it runs LED blink and prints HelloWorld on Serial port.

  2. As a double check, I programmed it using Arduino IDE. I ran a blink code. If I define my board as a Nucleo board 64 then the code gets compiled and downloaded but the LED does not blink. If I define it as a generic board using STM32L476RET chip then it runs the code well and LED on PC_7 blinks as directed. In both cases Arduino uses STLink as STCubeProgrammer and downloads code.

Ok, then you can edit the clock settings directly in MbedOS (in your local copy) which is in this location - …/mbed-os/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/system_clock.c

Ok, but this not exactly same chip… So what chip you exactly have?
NUCLEO-L476RG uses STM32L476RG and yor custom board is equiped with STM32L476RE which has half size of flash memory - STM32 Part_number_decoding - Wikipedia. This could be the issue why your clock can not start under Mbed.

BR, Jan