cancel
Showing results for 
Search instead for 
Did you mean: 

Undocumented behaviour STM32C011F4U6TR

ah2
Associate III

Hi,

We notice the startup time from power up can be affected by setting one GPIOB pin to input. The startup time here refers to the time from SystemInit() until main(). Basically it contains scatterload and __rt_entry to my understanding.

Specifically, the sample code below, built with ARM Compiler 6.16 Tool, would demonstrate that

#define MEASURE_PIN 5

int main(void)
{
  IO_SET_PIN(GPIOA, MEASURE_PIN, 1); 

  // Enable IWDG
  IWDG->KR = 0xCCCC;
  // Enable write access
  IWDG->KR = 0x5555;
  // Set prescaler
  IWDG->PR = 0;
  // Set reload
  IWDG->RLR = 1;

  // Wait for the registers reload
  while (IWDG->SR)
  {
  }
    
  // refresh the watchdog.
  IWDG->KR = 0xAAAA;

  while(1);
  return 0;
}
void SystemInit(void)
{
  // enable GPIOA clock
  RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;

  // set GPIOA pin5 to output
  IO_SET_PIN_DIR(GPIOA, MEASURE_PIN, 1);

  // set GPIOA pin5 to low
  IO_SET_PIN(GPIOA, MEASURE_PIN, 0);
  
  // Set GPIOB pin7 to input
  // GPIOB->MODER &= 0xffff3fff;  
} 

Basically GPIOA pin 5 is toggled to low and high for the time between SystemInit() and main() to be measured.

main() also has IWDG setup and ends with a while loop so that IWDG reset happens periodically since power up.

On the oscilloscope it looks like the screenshots below.

powerup_time_without_gpiob_input.png2nd_iwdg_reset_without_gpio.png

Respectively from the screenshots, it can be observed that the 1st startup(power up) takes 254 μs while the 2nd startup (IWDG reset) takes 132 μs.

Now if uncommenting this line GPIOB->MODER &= 0xffff3fff; and redo the measurement, we get the results below.

powerup_time_with_gpiob_input.png

We can see that having the GPIOB pin 7 set to input reduces the startup time from 254 μs to 132 μs and the rest startup remains taking the same time.

Could you please confirm the following:

  1. What causes the differences between 1st and 2nd startup?
  2. Why setting GPIOB ping 7 to input would affect the startup timing?

Just in case, this is how Reset_Handler looks like in our startup file. It is basically without any customization.

; Reset handler routine
Reset_Handler    PROC
                 EXPORT  Reset_Handler                 [WEAK]
        IMPORT  __main
        IMPORT  SystemInit  
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

  Anta

21 REPLIES 21

@Uwe Bonnes Just to add, the brownout level has not been changed so it's at whatever the default is.

ah2
Associate III

@Simon.T 

On the NRST pin we have a capacitor 10kΩ pull up and a resistor 100 nF to ground, and we program the options bytes NRST_MODE to have Reset Input only.

The scope pictures are as follows:

NRST_measurement_with_gpio.png

 

NRST_measurement_without_gpio.png

 

At what voltage does the first edge happen? For me it seems this is below minimum V(POR) = 1.9 Volt and probably also below minimum V(PDR) = 1.88 Volt . This would mean that the part is outside the "5.3.3
Embedded reset and power control block characteristics" specs. And "5.3.1 General operating conditions"  and so the whole part is only specified for operation from minimum V(PDR)  up to 3.6. Volt.

So the question is: Why does your part work below minimum V(PDR at all!

Why are green and yellow voltages different? Are external pull-ups used on MCO and GPIO? Why the dropouts on MCO when GPIO is low? Show your schematics!

@Uwe Bonnes Just to clarify, TIM16 is not linked to MCO, rather just as an indicator of when the frequency becomes stable.

I'm checking various things and see if it has impact on the measurement, e.g. whether ground is valid, any accidental pull up.

But I doubt it would have an impact on the timing. Has anyone here tried it and can confirm whether seeing or not seeing the same?

Have you tried enabling the brown out? The MCU now boots before voltage reaches its max. Shouldn't affect it, but doesn't hurt to try. Perhaps it affects the internal clock. If it doesn't get enough voltage then doing anything might get it to do strange things.
Can you show disassembly of IO_SET_PIN? Is it a function or a macro? What clock frequency is the MCU running? Because a difference of 122μs seems like a lot.

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

I tried setting the brownout level to various settings but the timing behaves the same. The timing seems quite consistent.

From the attached asm file, IO_SET_PIN is as follows:

;;;46       // set GPIOA pin5 to low
;;;47       IO_SET_PIN(GPIOA, MEASURE_PIN, 0);
        0x08000136:    6008        .`      STR      r0,[r1,#0]
        0x08000138:    4903        .I      LDR      r1,[pc,#12] ; [0x8000148] = 0x50000400

and IO_SET_PIN is a macro

The MCU is running on HSI48 with the default DIV so at 12 MHz. One observation worth mentioning is that if I set the frequency to 48MHz in SystemInit(), both reset time (power up and IWDG reset) takes the same at around 40 μs.

 


@ah2 wrote:

I tried setting the brownout level to various settings but the timing behaves the same. The timing seems quite consistent.


Good. We can exclude voltage level as a cause. I do see a lot of voltage ripple in your scope images. Have you tried stronger decoupling?

@ah2 wrote:

 

 

;;;46       // set GPIOA pin5 to low
;;;47       IO_SET_PIN(GPIOA, MEASURE_PIN, 0);
        0x08000136:    6008        .`      STR      r0,[r1,#0]
        0x08000138:    4903        .I      LDR      r1,[pc,#12] ; [0x8000148] = 0x50000400

 

 


This probably takes just 2 CPU cycles. And initalizing the ram-variables (in __rt_entry) shouldn't take up any time as I don't see any global or static variable in your code. I suspect the internal clock is not fully stabilized yet.

 


@ah2 wrote:

One observation worth mentioning is that if I set the frequency to 48MHz in SystemInit(), both reset time (power up and IWDG reset) takes the same at around 40 μs.


Perhaps this code waits for the clock to stabilize. Does this use the PLL? Can you share this code?

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

@unsigned_char_array wrote:


Good. We can exclude voltage level as a cause. I do see a lot of voltage ripple in your scope images. Have you tried stronger decoupling?


Yes I'm trying that next.


This probably takes just 2 CPU cycles. And initalizing the ram-variables (in __rt_entry) shouldn't take up any time as I don't see any global or static variable in your code. I suspect the internal clock is not fully stabilized yet.

 


That was also our only guess but wanted to confirm, since 122μs it is quite a lot.



@ah2 wrote:

One observation worth mentioning is that if I set the frequency to 48MHz in SystemInit(), both reset time (power up and IWDG reset) takes the same at around 40 μs.


Perhaps this code waits for the clock to stabilize. Does this use the PLL? Can you share this code?


I have been checking it, in case I missed it but I think STM32C011F4 does not have PLL, does it?

The code is simply the same as shared in the original post but adding the following code in the SystemInit()

 

#define RCC_CR_HSIDIV_Pos            (11U)
#define RCC_CR_HSIDIV_Msk            (0x7UL << RCC_CR_HSIDIV_Pos)
#define RCC_CR_HSIDIV_FCT_1          (0b000 << RCC_CR_HSIDIV_Pos)
#define RCC_CR_HSIDIV_FCT_HIGH        RCC_CR_HSIDIV_FCT_1
void SystemInit(void)
{
  // Setting HSIDIV to 1 so 48 MHz
  RCC->CR = (((RCC->CR) & (~(RCC_CR_HSIDIV_Msk))) | (RCC_CR_HSIDIV_FCT_HIGH));

  // enable GPIOA clock
  RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
...
...
...

 

 

 

> And initalizing the ram-variables (in __rt_entry) shouldn't take up any time as I don't see any global or static variable in your code. I suspect the internal clock is not fully stabilized yet.

0x400 bytes starting at 0x20000020 are set to zero - there are 256 word writes.

If the loop takes 6 cycles to execute, which IMO it can, that's around 130us at 12MHz clock.

JW