Contiki 2.5
low_level_init.c
1 /**************************************************
2  *
3  * This module contains the function `__low_level_init', a function
4  * that is called before the `main' function of the program. Normally
5  * low-level initializations - such as setting the prefered interrupt
6  * level or setting the watchdog - can be performed here.
7  *
8  * Note that this function is called before the data segments are
9  * initialized, this means that this function cannot rely on the
10  * values of global or static variables.
11  *
12  * When this function returns zero, the startup code will inhibit the
13  * initialization of the data segments. The result is faster startup,
14  * the drawback is that neither global nor static data will be
15  * initialized.
16  *
17  * Copyright 1999-2004 IAR Systems. All rights reserved.
18  * Customized by STMicroelectronics for STM32W
19  *
20  **************************************************/
21 
22 #include PLATFORM_HEADER
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 #pragma language=extended
29 
31 __root __no_init const HalFixedAddressTableType halFixedAddressTable @ __FAT__;
32 
33 extern const HalVectorTableType __vector_table[];
34 extern void halInternalSwitchToXtal(void);
35 
36 #define IAP_BOOTLOADER_APP_SWITCH_SIGNATURE 0xb001204d
37 #define IAP_BOOTLOADER_MODE_UART 0
38 
39 __interwork int __low_level_init(void);
40 
41 static void setStackPointer(int32u address)
42 {
43  asm("MOVS SP, r0");
44 }
45 
46 static const int16u blOffset[] = {
47  0x0715 - 0x03ad - 0x68,
48  0x0719 - 0x03ad - 0x6C
49 };
50 
51 
52 __interwork int __low_level_init(void)
53 {
54  //Ensure there is enough margin on VREG_1V8 for stable RAM reads by
55  //setting it to a code of 6. VREG_1V2 can be left at its reset value.
56  VREG = 0x00000307;
57 
58  // This code should be careful about the use of local variables in case the
59  // reset type happens to be a deep sleep reset. If the reset is not from
60  // deep sleep, then locals can be freely used
61 
62  //When the Cortex-M3 exits reset, interrupts are enable. Explicitely
63  //disable them immediately using the standard set PRIMASK instruction.
64  //Injecting an assembly instruction this early does not effect optimization.
65  asm("CPSID i");
66 
67  //It is quite possible that when the Cortex-M3 begins executing code the
68  //Core Reset Vector Catch is still left enabled. Because this VC would
69  //cause us to halt at reset if another reset event tripped, we should
70  //clear it as soon as possible. If a debugger wants to halt at reset,
71  //it will set this bit again.
72  DEBUG_EMCR &= ~DEBUG_EMCR_VC_CORERESET;
73 
74  //Configure flash access for optimal current consumption early
75  //during boot to save as much current as we can.
76  FLASH_ACCESS = (FLASH_ACCESS_PREFETCH_EN |
77  (1<<FLASH_ACCESS_CODE_LATENCY_BIT));
78 
79  ////---- Always remap the vector table ----////
80  // We might be coming from a bootloader at the base of flash, or even in the
81  // NULL_BTL case, the BAT/AAT will be at the beginning of the image
82  SCS_VTOR = (int32u)__vector_table;
83 
84  ////---- Always Configure Interrupt Priorities ----////
85  //The STM32W support 5 bits of priority configuration.
86  // The cortex allows this to be further divided into preemption and a
87  // "tie-breaker" sub-priority.
88  //We configure a scheme that allows for 3 bits (8 values) of preemption and
89  // 2 bits (4 values) of tie-breaker by using the value 4 in PRIGROUP.
90  //The value 0x05FA0000 is a special key required to write to this register.
91  SCS_AIRCR = (0x05FA0000 | (4 <<SCS_AIRCR_PRIGROUP_BIT));
92 
93  //A few macros to help with interrupt priority configuration. Really only
94  // uses 6 of the possible levels, and ignores the tie-breaker sub-priority
95  // for now.
96  //Don't forget that the priority level values need to be shifted into the
97  // top 5 bits of the 8 bit priority fields. (hence the <<3)
98  //
99  // NOTE: The ATOMIC and DISABLE_INTERRUPTS macros work by setting the
100  // current priority to a value of 12, which still allows CRITICAL and
101  // HIGH priority interrupts to fire, while blocking MED and LOW.
102  // If a different value is desired, spmr.s79 will need to be edited.
103  #define CRITICAL (0 <<3)
104  #define HIGH (8 <<3)
105  #define MED (16 <<3)
106  #define LOW (28 <<3)
107  #define NONE (31 <<3)
108 
109  //With optimization turned on, the compiler will indentify all the values
110  //and variables used here as constants at compile time and will truncate
111  //this entire block of code to 98 bytes, comprised of 7 load-load-store
112  //operations.
113  //vect00 is fixed //Stack pointer
114  //vect01 is fixed //Reset Vector
115  //vect02 is fixed //NMI Handler
116  //vect03 is fixed //Hard Fault Handler
117  SCS_SHPR_7to4 = ((CRITICAL <<SCS_SHPR_7to4_PRI_4_BIT) | //Memory Fault Handler
118  (CRITICAL <<SCS_SHPR_7to4_PRI_5_BIT) | //Bus Fault Handler
119  (CRITICAL <<SCS_SHPR_7to4_PRI_6_BIT) | //Usage Fault Handler
120  (NONE <<SCS_SHPR_7to4_PRI_7_BIT)); //Reserved
121  SCS_SHPR_11to8 = ((NONE <<SCS_SHPR_11to8_PRI_8_BIT) | //Reserved
122  (NONE <<SCS_SHPR_11to8_PRI_9_BIT) | //Reserved
123  (NONE <<SCS_SHPR_11to8_PRI_10_BIT) | //Reserved
124  (HIGH <<SCS_SHPR_11to8_PRI_11_BIT)); //SVCall Handler
125  SCS_SHPR_15to12 = ((MED <<SCS_SHPR_15to12_PRI_12_BIT) | //Debug Monitor Handler
126  (NONE <<SCS_SHPR_15to12_PRI_13_BIT) | //Reserved
127  (HIGH <<SCS_SHPR_15to12_PRI_14_BIT) | //PendSV Handler
128  (MED <<SCS_SHPR_15to12_PRI_15_BIT)); //SysTick Handler
129  NVIC_IPR_3to0 = ((MED <<NVIC_IPR_3to0_PRI_0_BIT) | //Timer 1 Handler
130  (MED <<NVIC_IPR_3to0_PRI_1_BIT) | //Timer 2 Handler
131  (HIGH <<NVIC_IPR_3to0_PRI_2_BIT) | //Management Handler
132  (MED <<NVIC_IPR_3to0_PRI_3_BIT)); //BaseBand Handler
133  NVIC_IPR_7to4 = ((MED <<NVIC_IPR_7to4_PRI_4_BIT) | //Sleep Timer Handler
134  (MED <<NVIC_IPR_7to4_PRI_5_BIT) | //SC1 Handler
135  (MED <<NVIC_IPR_7to4_PRI_6_BIT) | //SC2 Handler
136  (MED <<NVIC_IPR_7to4_PRI_7_BIT)); //Security Handler
137  NVIC_IPR_11to8 = ((MED <<NVIC_IPR_11to8_PRI_8_BIT) | //MAC Timer Handler
138  (MED <<NVIC_IPR_11to8_PRI_9_BIT) | //MAC TX Handler
139  (MED <<NVIC_IPR_11to8_PRI_10_BIT) | //MAC RX Handler
140  (MED <<NVIC_IPR_11to8_PRI_11_BIT)); //ADC Handler
141  NVIC_IPR_15to12 = ((MED <<NVIC_IPR_15to12_PRI_12_BIT) | //GPIO IRQA Handler
142  (MED <<NVIC_IPR_15to12_PRI_13_BIT) | //GPIO IRQB Handler
143  (MED <<NVIC_IPR_15to12_PRI_14_BIT) | //GPIO IRQC Handler
144  (MED <<NVIC_IPR_15to12_PRI_15_BIT)); //GPIO IRQD Handler
145  NVIC_IPR_19to16 = ((LOW <<NVIC_IPR_19to16_PRI_16_BIT)); //Debug Handler
146  //vect33 not implemented
147  //vect34 not implemented
148  //vect35 not implemented
149 
150  ////---- Always Configure System Handlers Control and Configuration ----////
151  SCS_CCR = SCS_CCR_DIV_0_TRP_MASK;
152  SCS_SHCSR = ( SCS_SHCSR_USGFAULTENA_MASK
153  | SCS_SHCSR_BUSFAULTENA_MASK
154  | SCS_SHCSR_MEMFAULTENA_MASK );
155 
156 
157  if((RESET_EVENT&RESET_DSLEEP) == RESET_DSLEEP) {
158  //Since the 13 NVIC registers above are fixed values, they are restored
159  //above (where they get set anyways during normal boot sequences) instead
160  //of inside of the halInternalSleep code:
161 
162  void halTriggerContextRestore(void);
163  extern volatile boolean halPendSvSaveContext;
164  halPendSvSaveContext = 0; //0 means restore context
165  SCS_ICSR |= SCS_ICSR_PENDSVSET; //pend halPendSvIsr to enable later
166  halTriggerContextRestore(); //sets MSP, enables interrupts
167  //if the context restore worked properly, we should never return here
168  while(1) { ; }
169  }
170 
171  //USART bootloader software activation check
172  if ((*((int32u *)RAM_BOTTOM) == IAP_BOOTLOADER_APP_SWITCH_SIGNATURE) && (*((int8u *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART)){
173  int8u cut = *(volatile int8u *) 0x08040798;
174  int16u offset = 0;
175  typedef void (*EntryPoint)(void);
176  offset = (halFixedAddressTable.baseTable.version == 3) ? blOffset[cut - 2] : 0;
177  *((int32u *)RAM_BOTTOM) = 0;
178  if (offset) {
180  }
181  EntryPoint entryPoint = (EntryPoint)(*(int32u *)(FIB_BOTTOM+4) - offset);
182  setStackPointer(*(int32u *)FIB_BOTTOM);
183  entryPoint();
184  }
185 
186  INTERRUPTS_OFF();
187  asm("CPSIE i");
188 
189  /*==================================*/
190  /* Choose if segment initialization */
191  /* should be done or not. */
192  /* Return: 0 to omit seg_init */
193  /* 1 to run seg_init */
194  /*==================================*/
195  return 1;
196 }
197 
198 #pragma language=default
199 
200 #ifdef __cplusplus
201 }
202 #endif