Example #1
0
/**
  * @brief  Configures interupts levels
  * @param  None
  * @retval Init value
  * @note Important note: This function is critical for waking up from deep sleep 
  * and it should not use more that 2 stack position
  * otherwise a stack corruption will occur when waking up from deep sleep.
  * All the steps not related to deep sleep have been moved to low_level_init2.
  * Perhaps this function should be rewritten in assembler to avoid stack usage 
  * all together when waking up from deep sleep.
  */
int __low_level_init(void)
{
#ifdef CORTEXM3_STM32W108xB
  /* Ensure there is enough margin on VREG_1V8 for stable RAM reads by */
  /* setting it to a code of 6.  VREG_1V2 can be left at its reset value. */
  PWR->VREGCR = 0x00000307;
#endif
  
  /* This code should be careful about the use of local variables in case the
     reset type happens to be a deep sleep reset.  If the reset is not from
    deep sleep, then locals can be freely used */
  
  /* When the Cortex-M3 exits reset, interrupts are enable.  Explicitely
     disable them immediately using the standard set PRIMASK instruction.
     Injecting an assembly instruction this early does not effect optimization. */
      
/* asm("CPSID i"); */                                                              
 #if (defined (__ICCARM__) || defined (__GNUC__))  
	asm("CPSID i");
 #elif defined __CC_ARM
        CPSID();
 #else 
   #error "Inline assembler syntax expected"  
 #endif
  
  /* It is quite possible that when the Cortex-M3 begins executing code the
     Core Reset Vector Catch is still left enabled.  Because this VC would
     cause us to halt at reset if another reset event tripped, we should
     clear it as soon as possible.  If a debugger wants to halt at reset,
     it will set this bit again. */
  CoreDebug->DEMCR &= ~CoreDebug_DEMCR_VC_CORERESET_Msk;
  
  /* Configure flash access for optimal current consumption early
     during boot to save as much current as we can. */
  FLASH->ACR= (FLASH_ACR_PRFTBE | (1 << 0));
  
  /*****---- Always remap the vector table ----*****/
  /* We might be coming from a bootloader at the base of flash, or even in the
     NULL_BTL case, the BAT/AAT will be at the beginning of the image */

#ifdef __ICCARM__
  SCB->VTOR = (uint32_t)__vector_table;
#elif defined __CC_ARM
  SCB->VTOR = (uint32_t)__Vectors;
#elif __GNUC__
  SCB->VTOR = (uint32_t)g_pfnVectors;
#else
  #error "Vector table expected"
#endif

  /*****---- Always Configure Interrupt Priorities ----************************/
  /* The STM32W support 5 bits of priority configuration.
     The cortex allows this to be further divided into preemption and a
     "tie-breaker" sub-priority.
     We configure a scheme that allows for 3 bits (8 values) of preemption and
     2 bits (4 values) of tie-breaker by using the value 4 in PRIGROUP.
     The value 0x05FA0000 is a special key required to write to this register. */
  SCB->AIRCR = (0x05FA0000 | (4 <<8));
  
  /* A few macros to help with interrupt priority configuration.  Really only 
     uses 6 of the possible levels, and ignores the tie-breaker sub-priority
     for now.
     Don't forget that the priority level values need to be shifted into the
     top 5 bits of the 8 bit priority fields. (hence the <<3)
   
     NOTE: The ATOMIC and DISABLE_INTERRUPTS macros work by setting the 
          current priority to a value of 12, which still allows CRITICAL and 
          HIGH priority interrupts to fire, while blocking MED and LOW.
          If a different value is desired, INTERRUPTS_DISABLED_PRIORITY will need
          to be edited. */
#define CRITICAL (0  <<3)
#define HIGH     (8  <<3)
#define MED      (16 <<3)
#define LOW      (28 <<3)
#define NONE     (31 <<3)
  
/* With optimization turned on, the compiler will indentify all the values
   and variables used here as constants at compile time and will truncate
   this entire block of code to 98 bytes, comprised of 7 load-load-store
     operations. */
   /* vect00 is fixed                        Stack pointer */
   /* vect01 is fixed                        Reset Vector */
   /* vect02 is fixed                        NMI Handler */
   /* vect03 is fixed                        Hard Fault Handler */

  SCB->SHP[0] = CRITICAL;   /* Memory Fault Handler */ 
  SCB->SHP[1] = CRITICAL;   /* Bus Fault Handler */
  SCB->SHP[2] = CRITICAL;   /* Usage Fault Handler */
  SCB->SHP[3] = NONE;       /* Reserved */
  
  SCB->SHP[4] = NONE;       /* Reserved */
  SCB->SHP[5] = NONE;       /* Reserved */
  SCB->SHP[6] = NONE;       /* Reserved */
  SCB->SHP[7] = HIGH;       /* SVCall Handler */
  
  SCB->SHP[8] = MED;        /* Debug Monitor Handler */
  SCB->SHP[9] = NONE;       /* Reserved */
  SCB->SHP[10] = HIGH;      /* PendSV Handler */
  SCB->SHP[11] = HIGH;      /* halSysTickIsr */

  NVIC->IP[0] = MED;       /* Timer 1 Handler */
  NVIC->IP[1] = MED;       /* Timer 2 Handler */
  NVIC->IP[2] = HIGH;      /* Management Handler */
  NVIC->IP[3] = MED;       /* BaseBand Handler */
  
  NVIC->IP[4] = MED;      /* Sleep Timer Handler */
  NVIC->IP[5] = MED;      /* SC1 Handler */
  NVIC->IP[6] = MED;      /* SC2 Handler */
  NVIC->IP[7] = MED;      /* Security Handler */
  
  NVIC->IP[8] = MED;      /* MAC Timer Handler */
  NVIC->IP[9] = MED;      /* MAC TX Handler */
  NVIC->IP[10] = MED;     /* MAC RX Handler */
  NVIC->IP[11] = MED;     /* ADC Handler */
  
  NVIC->IP[12] = MED;     /* GPIO IRQA Handler */
  NVIC->IP[13] = MED;     /* GPIO IRQB Handler */
  NVIC->IP[14] = MED;     /* GPIO IRQC Handler */
  NVIC->IP[15] = MED;     /* GPIO IRQD Handler */
  NVIC->IP[16] = LOW;     /* Debug Handler */
  /* vect33 not implemented */
  /* vect34 not implemented */
  /* vect35 not implemented */
  
  /*****---- Always Configure System Handlers Control and Configuration ----*****/
  SCB->CCR = SCB_CCR_DIV_0_TRP_Msk;
  SCB->SHCSR = ( SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk);
  
  if((RST->SR&RST_SR_WKUP) == RST_SR_WKUP)
  {
    /* Since the 13 NVIC registers above are fixed values, they are restored
       above (where they get set anyways during normal boot sequences) instead
       of inside of the halInternalSleep code: */
    
    void halTriggerContextRestore(void);
    extern __IO boolean halPendSvSaveContext;
    halPendSvSaveContext = 0;       /* 0 means restore context */
    SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; /* pend halPendSvIsr to enable later */
    halTriggerContextRestore();     /* sets MSP, enables interrupts */
    /* if the context restore worked properly, we should never return here */
    while(1) { ; }
  }
  low_level_init2();
  /*==========================================================================*/
  /*                     Choose if segment initialization                     */
  /*                        should be done or not.                            */
  /*                      Return: 0 to omit seg_init                          */
  /*                         1 to run seg_init                                */
  /*==========================================================================*/
  return 1;
}
/*******************************************************************************
* Function Name  : Reset_Handler
* Description    : This is the code that gets called when the processor first starts execution
*		       following a reset event.  Only the absolutely necessary set is performed,
*		       after which the application supplied main() routine is called. 
* Input          :
* Output         :
* Return         :
*******************************************************************************/
void Reset_Handler(void)
{
  //Ensure there is enough margin on VREG_1V8 for stable RAM reads by
  //setting it to a code of 6.  VREG_1V2 can be left at its reset value.
  VREG = 0x00000307;
  
  // This code should be careful about the use of local variables in case the
  // reset type happens to be a deep sleep reset.  If the reset is not from
  // deep sleep, then locals can be freely used

  //When the Cortex-M3 exits reset, interrupts are enable.  Explicitely
  //disable them immediately using the standard set PRIMASK instruction.
  //Injecting an assembly instruction this early does not effect optimization.
  asm("CPSID i");

  //It is quite possible that when the Cortex-M3 begins executing code the
  //Core Reset Vector Catch is still left enabled.  Because this VC would
  //cause us to halt at reset if another reset event tripped, we should
  //clear it as soon as possible.  If a debugger wants to halt at reset,
  //it will set this bit again.
  DEBUG_EMCR &= ~DEBUG_EMCR_VC_CORERESET;

  //Configure flash access for optimal current consumption early
  //during boot to save as much current as we can.
  FLASH_ACCESS = (FLASH_ACCESS_PREFETCH_EN          |
                  (1<<FLASH_ACCESS_CODE_LATENCY_BIT));

  ////---- Always Configure Interrupt Priorities ----////
  //The STM32W support 5 bits of priority configuration.
  //  The cortex allows this to be further divided into preemption and a
  //  "tie-breaker" sub-priority.
  //We configure a scheme that allows for 3 bits (8 values) of preemption and
  //   2 bits (4 values) of tie-breaker by using the value 4 in PRIGROUP.
  //The value 0x05FA0000 is a special key required to write to this register.
  SCS_AIRCR = (0x05FA0000 | (4 <<SCS_AIRCR_PRIGROUP_BIT));
    
  //A few macros to help with interrupt priority configuration.  Really only 
  //  uses 6 of the possible levels, and ignores the tie-breaker sub-priority
  //  for now.
  //Don't forget that the priority level values need to be shifted into the
  //  top 5 bits of the 8 bit priority fields. (hence the <<3)
  //
  // NOTE: The ATOMIC and DISABLE_INTERRUPTS macros work by setting the 
  //       current priority to a value of 12, which still allows CRITICAL and 
  //       HIGH priority interrupts to fire, while blocking MED and LOW.
  //       If a different value is desired, spmr.s79 will need to be edited.
  #define CRITICAL (0  <<3)
  #define HIGH     (8  <<3)
  #define MED      (16 <<3)
  #define LOW      (28 <<3)
  #define NONE     (31 <<3)

  //With optimization turned on, the compiler will indentify all the values
  //and variables used here as constants at compile time and will truncate
  //this entire block of code to 98 bytes, comprised of 7 load-load-store
  //operations.
                    //vect00 is fixed                        //Stack pointer
                    //vect01 is fixed                        //Reset Vector
                    //vect02 is fixed                        //NMI Handler
                    //vect03 is fixed                        //Hard Fault Handler
  SCS_SHPR_7to4   = ((CRITICAL <<SCS_SHPR_7to4_PRI_4_BIT) |  //Memory Fault Handler 
                     (CRITICAL <<SCS_SHPR_7to4_PRI_5_BIT) |  //Bus Fault Handler
                     (CRITICAL <<SCS_SHPR_7to4_PRI_6_BIT) |  //Usage Fault Handler
                     (NONE <<SCS_SHPR_7to4_PRI_7_BIT));      //Reserved
  SCS_SHPR_11to8  = ((NONE <<SCS_SHPR_11to8_PRI_8_BIT)  |    //Reserved
                     (NONE <<SCS_SHPR_11to8_PRI_9_BIT)  |    //Reserved
                     (NONE <<SCS_SHPR_11to8_PRI_10_BIT) |    //Reserved
                     (HIGH <<SCS_SHPR_11to8_PRI_11_BIT));    //SVCall Handler
  SCS_SHPR_15to12 = ((MED  <<SCS_SHPR_15to12_PRI_12_BIT) |   //Debug Monitor Handler
                     (NONE <<SCS_SHPR_15to12_PRI_13_BIT) |   //Reserved
                     (HIGH <<SCS_SHPR_15to12_PRI_14_BIT) |   //PendSV Handler
                     (MED  <<SCS_SHPR_15to12_PRI_15_BIT));   //SysTick Handler
  NVIC_IPR_3to0   = ((MED  <<NVIC_IPR_3to0_PRI_0_BIT) |      //Timer 1 Handler
                     (MED  <<NVIC_IPR_3to0_PRI_1_BIT) |      //Timer 2 Handler
                     (HIGH <<NVIC_IPR_3to0_PRI_2_BIT) |      //Management Handler
                     (MED  <<NVIC_IPR_3to0_PRI_3_BIT));      //BaseBand Handler
  NVIC_IPR_7to4   = ((MED  <<NVIC_IPR_7to4_PRI_4_BIT) |      //Sleep Timer Handler
                     (MED  <<NVIC_IPR_7to4_PRI_5_BIT) |      //SC1 Handler
                     (MED  <<NVIC_IPR_7to4_PRI_6_BIT) |      //SC2 Handler
                     (MED  <<NVIC_IPR_7to4_PRI_7_BIT));      //Security Handler
  NVIC_IPR_11to8  = ((MED  <<NVIC_IPR_11to8_PRI_8_BIT)  |    //MAC Timer Handler
                     (MED  <<NVIC_IPR_11to8_PRI_9_BIT)  |    //MAC TX Handler
                     (MED  <<NVIC_IPR_11to8_PRI_10_BIT) |    //MAC RX Handler
                     (MED  <<NVIC_IPR_11to8_PRI_11_BIT));    //ADC Handler
  NVIC_IPR_15to12 = ((MED  <<NVIC_IPR_15to12_PRI_12_BIT) |   //GPIO IRQA Handler
                     (MED  <<NVIC_IPR_15to12_PRI_13_BIT) |   //GPIO IRQB Handler
                     (MED  <<NVIC_IPR_15to12_PRI_14_BIT) |   //GPIO IRQC Handler
                     (MED  <<NVIC_IPR_15to12_PRI_15_BIT));   //GPIO IRQD Handler
  NVIC_IPR_19to16 = ((LOW  <<NVIC_IPR_19to16_PRI_16_BIT));   //Debug Handler
                    //vect33 not implemented
                    //vect34 not implemented
                    //vect35 not implemented

  ////---- Always Configure System Handlers Control and Configuration ----////
  SCS_CCR = SCS_CCR_DIV_0_TRP_MASK;
  SCS_SHCSR = ( SCS_SHCSR_USGFAULTENA_MASK
                | SCS_SHCSR_BUSFAULTENA_MASK
                | SCS_SHCSR_MEMFAULTENA_MASK );


  if((RESET_EVENT&RESET_DSLEEP) == RESET_DSLEEP) {
    //Since the 13 NVIC registers above are fixed values, they are restored
    //above (where they get set anyways during normal boot sequences) instead
    //of inside of the halInternalSleep code:

    void halTriggerContextRestore(void);
    extern volatile boolean halPendSvSaveContext;
    halPendSvSaveContext = 0;       //0 means restore context
    SCS_ICSR |= SCS_ICSR_PENDSVSET; //pend halPendSvIsr to enable later
    halTriggerContextRestore();     //sets MSP, enables interrupts
    //if the context restore worked properly, we should never return here
    while(1) { ; }
  }

  INTERRUPTS_OFF();
  asm("CPSIE i");

  /*==================================*/
  /* Choose if segment initialization */
  /* should be done or not.           */
  /* Return: 0 to omit seg_init       */
  /*         1 to run seg_init        */
  /*==================================*/
  //return 1;
  unsigned long *pulSrc, *pulDest;

  //
  // Copy the data segment initializers from flash to SRAM.
  //
  pulSrc = &_sidata;
  for(pulDest = &_sdata; pulDest < &_edata; )
    {
      *(pulDest++) = *(pulSrc++);
    }
  
  //
  // Zero fill the bss segment.
  //
  for(pulDest = &_sbss; pulDest < &_ebss; )
    {
      *(pulDest++) = 0;
    }
  
  //
  // Call the application's entry point.
  //
  main();
}