AnsweredAssumed Answered

Microcontroller stops working when I slow down the clock - Where do I even begin to debug this?

Question asked by arnold_w on Jul 11, 2016
Latest reply on Jul 11, 2016 by peacock.jack
I am working with the STM32F405 microcntroller and in main() I have the following loop:

while (TRUE)
{
    UART_TransmitNullTerminatedString((uint8_t*) "\r\nMicrocontroller alive ");
}

I run this firmware on 2 different PCB:s and it's working fine on PCB #1, but on PCB #2 it hangs after 3-4 seconds. Now, it would be easy to conclude that PCB #2 is broken, but the strange thing is that PCB #2 starts working fine if I run the microcontroller faster. I use the following code to switch clock frequency: 

void ClockSwitch(ClockFreqType clockFreq)
{
    // The code below was taken from HAL_RCC_DeInit() in file stm32f4xx_hal_rcc_ex.c
 
    /* Set HSION bit */
    SET_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSITRIM_4);
 
    /* Reset CFGR register */
    CLEAR_REG(RCC->CFGR);
 
    /* Reset HSEON, CSSON, PLLON, PLLI2S */
    CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_CSSON | RCC_CR_PLLON| RCC_CR_PLLI2SON);
 
    /* Reset PLLCFGR register */
    CLEAR_REG(RCC->PLLCFGR);
    SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2);
 
    /* Reset PLLI2SCFGR register */
    CLEAR_REG(RCC->PLLI2SCFGR);
    SET_BIT(RCC->PLLI2SCFGR,  RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1);
 
    /* Reset HSEBYP bit */
    CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
 
    /* Disable all interrupts */
    RCC->CIR = 0x00000000;
 
    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
 
    // First, switch to HSI to bypass the PLL
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
 
    // The code below was generated with STM32CubeMX
    switch (clockFreq)
    {
        case CLOCK_FREQ_1_MHz:
        {
             RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                        |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
            RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV16;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_2_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                         |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
            RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV8;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_4_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                        |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
            RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV4;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_8_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                        |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
            RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_16_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                        |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
            RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_32_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
            RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
            RCC_OscInitStruct.PLL.PLLM = 8;
            RCC_OscInitStruct.PLL.PLLN = 64;
            RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
            RCC_OscInitStruct.PLL.PLLQ = 4;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            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_DIV2;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_64_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
            RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
            RCC_OscInitStruct.PLL.PLLM = 8;
            RCC_OscInitStruct.PLL.PLLN = 64;
            RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
            RCC_OscInitStruct.PLL.PLLQ = 4;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            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_DIV2;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            break;
        }
        case CLOCK_FREQ_128_MHz:
        {
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = 16;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
            RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
            RCC_OscInitStruct.PLL.PLLM = 8;
            RCC_OscInitStruct.PLL.PLLN = 128;
            RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
            RCC_OscInitStruct.PLL.PLLQ = 4;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
            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_DIV4;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
            break;
        }
        default:
        {
            break;
        }
    }
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, getNumWaitStates(clockFreq));
    SystemCoreClockUpdate();
}

At 8 MHz PCB #1 is working fine, but PCB #2 hangs after about 3-4 seconds. If I instead run at 16 MHz or faster, then both PCB:s work fine. Does anybody have any suggestions how I can tackle this problem? Are there any status registers I should pay attention to? I'm running off a power supply and power consumption doesn't seem to be an issue (it's not drawing too much current and, surprisingly, the current consumption doesn't go down after PCB #2 hangs).

Outcomes