Contiki 3.x
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(uint32_t address)
42 {
43  asm("MOVS SP, r0");
44 }
45 
46 static const uint16_t 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 = (uint32_t)__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 ((*((uint32_t *)RAM_BOTTOM) == IAP_BOOTLOADER_APP_SWITCH_SIGNATURE) && (*((uint8_t *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART)){
173  uint8_t cut = *(volatile uint8_t *) 0x08040798;
174  uint16_t offset = 0;
175  typedef void (*EntryPoint)(void);
176  offset = (halFixedAddressTable.baseTable.version == 3) ? blOffset[cut - 2] : 0;
177  *((uint32_t *)RAM_BOTTOM) = 0;
178  if (offset) {
180  }
181  EntryPoint entryPoint = (EntryPoint)(*(uint32_t *)(FIB_BOTTOM+4) - offset);
182  setStackPointer(*(uint32_t *)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
STM32W108 series memory map definitions used by the full hal.
void halInternalSwitchToXtal(void)
Switches to running off of the 24MHz crystal, including changing the CPU to be 24MHz (FCLK sourced fr...
Definition: clocks.c:397
#define INTERRUPTS_OFF()
Disable global interrupts without regard to the current or previous state.
Definition: gnu.h:438
#define IAP_BOOTLOADER_MODE_UART
IAP bootloader uart mode.
#define IAP_BOOTLOADER_APP_SWITCH_SIGNATURE
Signature used for switch to application.