00001 /************************************************** 00002 * 00003 * This module contains the function `__low_level_init', a function 00004 * that is called before the `main' function of the program. Normally 00005 * low-level initializations - such as setting the prefered interrupt 00006 * level or setting the watchdog - can be performed here. 00007 * 00008 * Note that this function is called before the data segments are 00009 * initialized, this means that this function cannot rely on the 00010 * values of global or static variables. 00011 * 00012 * When this function returns zero, the startup code will inhibit the 00013 * initialization of the data segments. The result is faster startup, 00014 * the drawback is that neither global nor static data will be 00015 * initialized. 00016 * 00017 * Copyright 1999-2004 IAR Systems. All rights reserved. 00018 * Customized by STMicroelectronics for STM32W 00019 * 00020 **************************************************/ 00021 00022 #include PLATFORM_HEADER 00023 00024 #ifdef __cplusplus 00025 extern "C" { 00026 #endif 00027 00028 #pragma language=extended 00029 00030 #include "hal/micro/cortexm3/memmap.h" 00031 __root __no_init const HalFixedAddressTableType halFixedAddressTable @ __FAT__; 00032 00033 extern const HalVectorTableType __vector_table[]; 00034 extern void halInternalSwitchToXtal(void); 00035 00036 #define IAP_BOOTLOADER_APP_SWITCH_SIGNATURE 0xb001204d 00037 #define IAP_BOOTLOADER_MODE_UART 0 00038 00039 __interwork int __low_level_init(void); 00040 00041 static void setStackPointer(int32u address) 00042 { 00043 asm("MOVS SP, r0"); 00044 } 00045 00046 static const int16u blOffset[] = { 00047 0x0715 - 0x03ad - 0x68, 00048 0x0719 - 0x03ad - 0x6C 00049 }; 00050 00051 00052 __interwork int __low_level_init(void) 00053 { 00054 //Ensure there is enough margin on VREG_1V8 for stable RAM reads by 00055 //setting it to a code of 6. VREG_1V2 can be left at its reset value. 00056 VREG = 0x00000307; 00057 00058 // This code should be careful about the use of local variables in case the 00059 // reset type happens to be a deep sleep reset. If the reset is not from 00060 // deep sleep, then locals can be freely used 00061 00062 //When the Cortex-M3 exits reset, interrupts are enable. Explicitely 00063 //disable them immediately using the standard set PRIMASK instruction. 00064 //Injecting an assembly instruction this early does not effect optimization. 00065 asm("CPSID i"); 00066 00067 //It is quite possible that when the Cortex-M3 begins executing code the 00068 //Core Reset Vector Catch is still left enabled. Because this VC would 00069 //cause us to halt at reset if another reset event tripped, we should 00070 //clear it as soon as possible. If a debugger wants to halt at reset, 00071 //it will set this bit again. 00072 DEBUG_EMCR &= ~DEBUG_EMCR_VC_CORERESET; 00073 00074 //Configure flash access for optimal current consumption early 00075 //during boot to save as much current as we can. 00076 FLASH_ACCESS = (FLASH_ACCESS_PREFETCH_EN | 00077 (1<<FLASH_ACCESS_CODE_LATENCY_BIT)); 00078 00079 ////---- Always remap the vector table ----//// 00080 // We might be coming from a bootloader at the base of flash, or even in the 00081 // NULL_BTL case, the BAT/AAT will be at the beginning of the image 00082 SCS_VTOR = (int32u)__vector_table; 00083 00084 ////---- Always Configure Interrupt Priorities ----//// 00085 //The STM32W support 5 bits of priority configuration. 00086 // The cortex allows this to be further divided into preemption and a 00087 // "tie-breaker" sub-priority. 00088 //We configure a scheme that allows for 3 bits (8 values) of preemption and 00089 // 2 bits (4 values) of tie-breaker by using the value 4 in PRIGROUP. 00090 //The value 0x05FA0000 is a special key required to write to this register. 00091 SCS_AIRCR = (0x05FA0000 | (4 <<SCS_AIRCR_PRIGROUP_BIT)); 00092 00093 //A few macros to help with interrupt priority configuration. Really only 00094 // uses 6 of the possible levels, and ignores the tie-breaker sub-priority 00095 // for now. 00096 //Don't forget that the priority level values need to be shifted into the 00097 // top 5 bits of the 8 bit priority fields. (hence the <<3) 00098 // 00099 // NOTE: The ATOMIC and DISABLE_INTERRUPTS macros work by setting the 00100 // current priority to a value of 12, which still allows CRITICAL and 00101 // HIGH priority interrupts to fire, while blocking MED and LOW. 00102 // If a different value is desired, spmr.s79 will need to be edited. 00103 #define CRITICAL (0 <<3) 00104 #define HIGH (8 <<3) 00105 #define MED (16 <<3) 00106 #define LOW (28 <<3) 00107 #define NONE (31 <<3) 00108 00109 //With optimization turned on, the compiler will indentify all the values 00110 //and variables used here as constants at compile time and will truncate 00111 //this entire block of code to 98 bytes, comprised of 7 load-load-store 00112 //operations. 00113 //vect00 is fixed //Stack pointer 00114 //vect01 is fixed //Reset Vector 00115 //vect02 is fixed //NMI Handler 00116 //vect03 is fixed //Hard Fault Handler 00117 SCS_SHPR_7to4 = ((CRITICAL <<SCS_SHPR_7to4_PRI_4_BIT) | //Memory Fault Handler 00118 (CRITICAL <<SCS_SHPR_7to4_PRI_5_BIT) | //Bus Fault Handler 00119 (CRITICAL <<SCS_SHPR_7to4_PRI_6_BIT) | //Usage Fault Handler 00120 (NONE <<SCS_SHPR_7to4_PRI_7_BIT)); //Reserved 00121 SCS_SHPR_11to8 = ((NONE <<SCS_SHPR_11to8_PRI_8_BIT) | //Reserved 00122 (NONE <<SCS_SHPR_11to8_PRI_9_BIT) | //Reserved 00123 (NONE <<SCS_SHPR_11to8_PRI_10_BIT) | //Reserved 00124 (HIGH <<SCS_SHPR_11to8_PRI_11_BIT)); //SVCall Handler 00125 SCS_SHPR_15to12 = ((MED <<SCS_SHPR_15to12_PRI_12_BIT) | //Debug Monitor Handler 00126 (NONE <<SCS_SHPR_15to12_PRI_13_BIT) | //Reserved 00127 (HIGH <<SCS_SHPR_15to12_PRI_14_BIT) | //PendSV Handler 00128 (MED <<SCS_SHPR_15to12_PRI_15_BIT)); //SysTick Handler 00129 NVIC_IPR_3to0 = ((MED <<NVIC_IPR_3to0_PRI_0_BIT) | //Timer 1 Handler 00130 (MED <<NVIC_IPR_3to0_PRI_1_BIT) | //Timer 2 Handler 00131 (HIGH <<NVIC_IPR_3to0_PRI_2_BIT) | //Management Handler 00132 (MED <<NVIC_IPR_3to0_PRI_3_BIT)); //BaseBand Handler 00133 NVIC_IPR_7to4 = ((MED <<NVIC_IPR_7to4_PRI_4_BIT) | //Sleep Timer Handler 00134 (MED <<NVIC_IPR_7to4_PRI_5_BIT) | //SC1 Handler 00135 (MED <<NVIC_IPR_7to4_PRI_6_BIT) | //SC2 Handler 00136 (MED <<NVIC_IPR_7to4_PRI_7_BIT)); //Security Handler 00137 NVIC_IPR_11to8 = ((MED <<NVIC_IPR_11to8_PRI_8_BIT) | //MAC Timer Handler 00138 (MED <<NVIC_IPR_11to8_PRI_9_BIT) | //MAC TX Handler 00139 (MED <<NVIC_IPR_11to8_PRI_10_BIT) | //MAC RX Handler 00140 (MED <<NVIC_IPR_11to8_PRI_11_BIT)); //ADC Handler 00141 NVIC_IPR_15to12 = ((MED <<NVIC_IPR_15to12_PRI_12_BIT) | //GPIO IRQA Handler 00142 (MED <<NVIC_IPR_15to12_PRI_13_BIT) | //GPIO IRQB Handler 00143 (MED <<NVIC_IPR_15to12_PRI_14_BIT) | //GPIO IRQC Handler 00144 (MED <<NVIC_IPR_15to12_PRI_15_BIT)); //GPIO IRQD Handler 00145 NVIC_IPR_19to16 = ((LOW <<NVIC_IPR_19to16_PRI_16_BIT)); //Debug Handler 00146 //vect33 not implemented 00147 //vect34 not implemented 00148 //vect35 not implemented 00149 00150 ////---- Always Configure System Handlers Control and Configuration ----//// 00151 SCS_CCR = SCS_CCR_DIV_0_TRP_MASK; 00152 SCS_SHCSR = ( SCS_SHCSR_USGFAULTENA_MASK 00153 | SCS_SHCSR_BUSFAULTENA_MASK 00154 | SCS_SHCSR_MEMFAULTENA_MASK ); 00155 00156 00157 if((RESET_EVENT&RESET_DSLEEP) == RESET_DSLEEP) { 00158 //Since the 13 NVIC registers above are fixed values, they are restored 00159 //above (where they get set anyways during normal boot sequences) instead 00160 //of inside of the halInternalSleep code: 00161 00162 void halTriggerContextRestore(void); 00163 extern volatile boolean halPendSvSaveContext; 00164 halPendSvSaveContext = 0; //0 means restore context 00165 SCS_ICSR |= SCS_ICSR_PENDSVSET; //pend halPendSvIsr to enable later 00166 halTriggerContextRestore(); //sets MSP, enables interrupts 00167 //if the context restore worked properly, we should never return here 00168 while(1) { ; } 00169 } 00170 00171 //USART bootloader software activation check 00172 if ((*((int32u *)RAM_BOTTOM) == IAP_BOOTLOADER_APP_SWITCH_SIGNATURE) && (*((int8u *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART)){ 00173 int8u cut = *(volatile int8u *) 0x08040798; 00174 int16u offset = 0; 00175 typedef void (*EntryPoint)(void); 00176 offset = (halFixedAddressTable.baseTable.version == 3) ? blOffset[cut - 2] : 0; 00177 *((int32u *)RAM_BOTTOM) = 0; 00178 if (offset) { 00179 halInternalSwitchToXtal(); 00180 } 00181 EntryPoint entryPoint = (EntryPoint)(*(int32u *)(FIB_BOTTOM+4) - offset); 00182 setStackPointer(*(int32u *)FIB_BOTTOM); 00183 entryPoint(); 00184 } 00185 00186 INTERRUPTS_OFF(); 00187 asm("CPSIE i"); 00188 00189 /*==================================*/ 00190 /* Choose if segment initialization */ 00191 /* should be done or not. */ 00192 /* Return: 0 to omit seg_init */ 00193 /* 1 to run seg_init */ 00194 /*==================================*/ 00195 return 1; 00196 } 00197 00198 #pragma language=default 00199 00200 #ifdef __cplusplus 00201 } 00202 #endif