cancel
Showing results for 
Search instead for 
Did you mean: 

STM8 Manual Clock Switching Bug

Mehran Memarnejad
Associate III

Hi,

I guess there is a bug in manual clock switching (file: stm8s_clk.c function:CLK_ClockSwitchConfig:(

 /* Wait until the target clock source is ready */
 while((((CLK->SWCR & CLK_SWCR_SWIF) != 0 ) && (DownCounter != 0)))
 {
     DownCounter--;
 }

Must be changed to:

 /* Wait until the target clock source is ready */
 while((((CLK->SWCR & CLK_SWCR_SWIF) == 0) && (DownCounter != 0)))
 {
     DownCounter--;
 }

As stated in reference manual, SWIF becomes 1 when target clock source is ready, so we must loop on it till it becomes 1 or timeouts

4 REPLIES 4
Life_Cycle
Associate

I found a new bug: in auto mode, after give the SWR a new value, the SWBSY bit won't become 1 immediately, but it check this bit at once in the function CLK_ClockSwitchConfig(), so this function exit before the clock switch done, then i init the uart, it will get a wrong clk value, and then the baudrate is not correct

 

  /* Automatic switch mode management */
  if (CLK_SwitchMode == CLK_SWITCHMODE_AUTO)
  {
    /* Enables Clock switch */
    CLK->SWCR |= CLK_SWCR_SWEN;
    
    /* Enables or Disables Switch interrupt */
    if (ITState != DISABLE)
    {
      CLK->SWCR |= CLK_SWCR_SWIEN;
    }
    else
    {
      CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIEN);
    }
    
    /* Selection of the target clock source */
    CLK->SWR = (uint8_t)CLK_NewClock;
    //here is the bug????????????????
    /* Wait until the target clock source is ready */
    while((((CLK->SWCR & CLK_SWCR_SWBSY) != 0 )&& (DownCounter != 0)))
    {
      DownCounter--;
    }
    
    if(DownCounter != 0)
    {
      Swif = SUCCESS;
    }
    else
    {
      Swif = ERROR;
    }
  }
BillAinCT
Associate II

@Life_Cycle  did you try to add a loop while it is 0 before the loop checking for it to go to 0? That is adding this where your bug comment is:

 

 

 

 /* Wait until the target clock is switching */
while((((CLK->SWCR & CLK_SWCR_SWBSY) == 0 )&& (DownCounter != 0)))
{
DownCounter--;
}

 

 

Edit: It well could be that it only needs a few CPU cycles to go high so inserting a few NOPs might be all it takes to see the bit go high.

 

I do not want to edit the STM8S_StdPeriph_Driver, so I add the follow code after the function CLK_ClockSwitchConfig(), it work and my uart program also work in correct baudratio.

// switch clk to HSE without div, the fclk = HSE/1
  CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE); // should not disable current clk for bug
  // wait switch done(beacause there is a bug in fucntuion CLK_ClockSwitchConfig() when in auto mode)
  while ((CLK->SWCR & CLK_SWCR_SWBSY) != 0);

Your program will hang if the processor cannot switch the clock. They included the DownCounter part for a good reason.