cancel
Showing results for 
Search instead for 
Did you mean: 

Questions on what's happning before main() is called

arnold_w
Senior
Posted on June 01, 2016 at 16:19

I am working with the STM32F405/STM32F407 microcontrollers.I am trying to understand what's happening inside the microcontroller before main() is called and I would like to get rid of as much as possible to minimize risk that something is happening ''behind my back''.I don't plan to use the HAL-layer much, but I think it's useful for small tasks such as initializing GPIO-pins, timers, UART:s, etc because of the type safeness with struct and enums. I do not plan to use any sort of realtime operating system and I don't want the HAL to keep track of what resources are in use for me, I will do that myself.My HSE_VALUE is defined to 0 and HSI_VALUE is defined to 16000000 and I want to use internal clock.Below I have tried to write down what is being called when the microcontroller is powered-up and I would like to know what is safe to remove. For sure I don't like rows 053-057, I mean is the microcontroller using a timer and ''ticking'' every 1 ms!?!?! Anything else I can rid of?

001 __initialize_hardware_early()
002 
003 
void
SystemInit(
void
)
004 {
005 
/* Reset the RCC clock configuration to the default reset state ------------*/
006 
/* Set HSION bit */
007 RCC->CR |= (uint32_t)0x00000001;
008 
009 
/* Reset CFGR register */
010 RCC->CFGR = 0x00000000;
011 
012 
/* Reset HSEON, CSSON and PLLON bits */
013 RCC->CR &= (uint32_t)0xFEF6FFFF;
014 
015 
/* Reset PLLCFGR register */
016 RCC->PLLCFGR = 0x24003010;
017 
018 
/* Reset HSEBYP bit */
019 RCC->CR &= (uint32_t)0xFFFBFFFF;
020 
021 
/* Disable all interrupts */
022 RCC->CIR = 0x00000000;
023 
024 
/* Configure the Vector Table location add offset address ------------------*/
025 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; 
/* Vector Table Relocation in Internal FLASH */
026 }
027 
028 #
if
defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
029 
// Set VTOR to the actual address, provided by the linker script.
030 
// Override the manual, possibly wrong, SystemInit() setting.
031 SCB->VTOR = (uint32_t)(&__vectors_start);
032 #endif
033 
034 
void
__initialize_hardware(
void
) 
035 {
036 
// Initialise the HAL Library; it must be the first function
037 
// to be executed before the call of any HAL function.
038 HAL_StatusTypeDef HAL_Init(
void
)
039 {
040 
/* Configure Flash prefetch, Instruction cache, Data cache */
041 #
if
(INSTRUCTION_CACHE_ENABLE != 0U)
042 __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
043 #endif 
/* INSTRUCTION_CACHE_ENABLE */
044 
045 #
if
(DATA_CACHE_ENABLE != 0U)
046 __HAL_FLASH_DATA_CACHE_ENABLE();
047 #endif 
/* DATA_CACHE_ENABLE */
048 
049 #
if
(PREFETCH_ENABLE != 0U)
050 __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
051 #endif 
/* PREFETCH_ENABLE */
052 
053 
/* Set Interrupt Group Priority */
054 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
055 
056 
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
057 HAL_InitTick(TICK_INT_PRIORITY);
058 
059 
/* Init the low level hardware */
060 HAL_MspInit();
061 
062 
/* Return function status */
063 
return
HAL_OK;
064 }
065 
066 
// Enable HSE Oscillator and activate PLL with HSE as source
067 
void
__attribute__((weak)) SystemClock_Config(
void
)
068 {
069 
// Enable Power Control clock
070 __PWR_CLK_ENABLE();
071 
072 
// The voltage scaling allows optimizing the power consumption when the
073 
// device is clocked below the maximum system frequency, to update the
074 
// voltage scaling value regarding system frequency refer to product
075 
// datasheet.
076 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
077 
078 #warning 
''Please check if the SystemClock_Config() settings match your board!''
079 
// Comment out the warning after checking and updating.
080 
081 RCC_OscInitTypeDef RCC_OscInitStruct;
082 
083 
// Use HSI and activate PLL with HSI as source.
084 
// This is tuned for NUCLEO-F411; update it for your board.
085 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
086 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
087 
// 16 is the average calibration value, adjust for your own board.
088 RCC_OscInitStruct.HSICalibrationValue = 16;
089 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
090 
// This assumes the HSI_VALUE is a multiple of 1 MHz. If this is not
091 
// your case, you have to recompute these PLL constants.
092 RCC_OscInitStruct.PLL.PLLM = (HSI_VALUE/1000000u);
093 
094 RCC_OscInitStruct.PLL.PLLN = 336;
095 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
/* 168 MHz */
096 RCC_OscInitStruct.PLL.PLLQ = 7; 
/* To make USB work. */
097 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
098 HAL_RCC_OscConfig(&RCC_OscInitStruct);
099 
100 RCC_ClkInitTypeDef RCC_ClkInitStruct;
101 
// Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
102 
// clocks dividers
103 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
104 | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
105 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
106 
// This is expected to work for most large cores.
107 
// Check and update it for your own configuration.
108 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
109 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
110 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
111 HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
112 
113 HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
114 
115 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
116 }
117 
118 
119 
// Call the CSMSIS system clock routine to store the clock frequency
120 
// in the SystemCoreClock global RAM location.
121 
void
SystemCoreClockUpdate(
void
)
122 {
123 uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
124 
125 
/* Get SYSCLK source -------------------------------------------------------*/
126 tmp = RCC->CFGR & RCC_CFGR_SWS;
127 
128 
switch
(tmp)
129 {
130 
case
0x00: 
/* HSI used as system clock source */
131 SystemCoreClock = HSI_VALUE;
132 
break
;
133 
case
0x04: 
/* HSE used as system clock source */
134 SystemCoreClock = HSE_VALUE;
135 
break
;
136 
case
0x08: 
/* PLL used as system clock source */
137 
138 
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
139 SYSCLK = PLL_VCO / PLL_P
140 */
141 pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
142 pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
143 
144 
if
(pllsource != 0)
145 {
146 
/* HSE used as PLL clock source */
147 pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
148 }
149 
else
150 {
151 
/* HSI used as PLL clock source */
152 pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
153 }
154 
155 pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
156 SystemCoreClock = pllvco/pllp;
157 
break
;
158 
default
:
159 SystemCoreClock = HSI_VALUE;
160 
break
;
161 }
162 
/* Compute HCLK frequency --------------------------------------------------*/
163 
/* Get HCLK prescaler */
164 tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
165 
/* HCLK frequency */
166 SystemCoreClock >>= tmp;
167 }
168 }

4 REPLIES 4
Posted on June 01, 2016 at 17:28

The model is that SystemInit() is called to initialize the clocks to operating speed, and any pins, interfaces, and external memory chips that the C code is going to use. ie what you described as regions and load regions in the scatter file or linker script.

Then prior to calling main() the C runtime code initializes the statics, ie the variables you have created, either with zeros or specific values, int global = 123

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arnold_w
Senior
Posted on June 02, 2016 at 09:48

What can I remove from HAL_Init()? I would like to throw it out altogether, but it seems dangerous to fiddle with cache and pre-fetch things. Under all circumstances I must not have a timer waking the microcontroller up ever so often doing ''ticks'' in the background!!!

036 
// Initialise the HAL Library; it must be the first function
037 
// to be executed before the call of any HAL function.
038 HAL_StatusTypeDef HAL_Init(
void
)
039 {
040 
/* Configure Flash prefetch, Instruction cache, Data cache */
041 #
if
(INSTRUCTION_CACHE_ENABLE != 0U)
042 __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
043 #endif 
/* INSTRUCTION_CACHE_ENABLE */
044 
045 #
if
(DATA_CACHE_ENABLE != 0U)
046 __HAL_FLASH_DATA_CACHE_ENABLE();
047 #endif 
/* DATA_CACHE_ENABLE */
048 
049 #
if
(PREFETCH_ENABLE != 0U)
050 __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
051 #endif 
/* PREFETCH_ENABLE */
052 
053 
/* Set Interrupt Group Priority */
054 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
055 
056 
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
057 HAL_InitTick(TICK_INT_PRIORITY);
058 
059 
/* Init the low level hardware */
060 HAL_MspInit();
061 
062 
/* Return function status */
063 
return
HAL_OK;
064 }

Posted on June 02, 2016 at 12:02

> What can I remove from HAL_Init()?

Everything.

> I would like to throw it out altogether, but it seems dangerous to fiddle with cache and pre-fetch things.

Why? There is no magic in them. Read the user manual.

#define XTAL_FREQ 12

int main(void) {

    RCC->CR |= ((uint32_t)RCC_CR_HSEON);  // enable HSE

  while((RCC->CR & RCC_CR_HSERDY) == 0);  // wait until up

  // before firing up PLL, one word of caution: the VOS bit in PWR_CR register must be 1 for fSYS>144MHz

  // that's the reset value so there's no need to change it here (VOS=0 brings some 10% reduction in power consumption between 30MHz-144MHz)

  // if we'd need to change it, the power module's clock would have to be fired up, too - see the STM-supplied ''systemInit'' code

  RCC->CFGR |=    RCC_CFGR_HPRE_DIV1    // AHB prescaler set to 1 -> AHB clock = 160MHz

               | RCC_CFGR_PPRE1_DIV4   // APB1 prescaler set to 4 -> APB1 clock = 40MHz (required to be < 42MHz)

               | RCC_CFGR_PPRE2_DIV2;  // APB2 prescaler set to 2 -> APB2 clock = 80MHz (required to be < 84MHz)

  RCC->PLLCFGR =    ( XTAL_FREQ  * RCC_PLLCFGR_PLLM_0)     // M = XTAL divider - the PLL needs 1MHz to 2MHz at its input

                 | (( 160  * 2) * RCC_PLLCFGR_PLLN_0)    // N = PLL multiplier (feedback divider) - the VCO's output needs to fall between 64MHz and 432MHz

//                 | (0 * RCC_PLLCFGR_PLLP_0)      // P = divider for SYSCLK - 0 = /2, 1 = /4, 2 = /6, 3 = /8

                 | (1 * RCC_PLLCFGR_PLLP_0)      // P = divider for SYSCLK - 0 = /2, 1 = /4, 2 = /6, 3 = /8

                 | (7 * RCC_PLLCFGR_PLLQ_0)      // Q = divider for USB (and SDIO and RNG), should result in 48MHz but that's unattainable with this setup - we won't use it anyway - for SDIO and RNG it should be below 48MHz

                 | (RCC_PLLCFGR_PLLSRC_HSE);     // PLL source is HSE

  RCC->CR |= RCC_CR_PLLON;  // fire up PLL

  while((RCC->CR & RCC_CR_PLLRDY) == 0);  // and wait until up

  FLASH->ACR =  0

               | FLASH_ACR_ICEN          // meantime, configure flash for maximum performance - enable both caches

               | FLASH_ACR_DCEN

               | FLASH_ACR_PRFTEN        // errata says this is ''unavailable'' for A-revision devices - should we selectively disable this through reading DBGMCU_IDCODE?

               | FLASH_ACR_LATENCY_5WS;  // for VCC>2.7V and FSYS>144MHz, 5 waitstate is appropriate

  RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_SW))) | RCC_CFGR_SW_PLL;  // switch clock source to PLL

  while ((RCC->CFGR & RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);  // wait until switches

  // and that's it.

This too was written with the assumption of  the registers being at their reset value.

JW

arnold_w
Senior
Posted on June 02, 2016 at 12:36

After further investigations it seems (correct me if I'm wrong) the SysTick is needed for the HAL_Delay() function and this function is called in stm32f4xx_hal_eth.c, stm32f4xx_hal_sd.c and stm32f4xx_ll_usb.c. Since I don't use those files, I am very tempted to throw out the HAL altogether (not just the call to HAL_Init(), but all files as well), but the problem is that I am using STSW-STM32066 (EEPROM emulation in STM32F40x/STM32F41x microcontrollers (AN3969)) which is depending on HAL.