/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : stm32f10x_vector.c
* Author             : MCD Tools Team
* Date First Issued  : 05/14/2007
* Description        : This file contains the vector table for STM32F10x.
*                     	 After Reset the Cortex-M3 processor is in Thread mode,
*                     	 priority is Privileged, and the Stack is set to Main.
********************************************************************************
* History:
* 05/14/2007: V0.2
*
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#define RESERVED 0
#define IAP_BOOTLOADER_APP_SWITCH_SIGNATURE  0xb001204d
#define IAP_BOOTLOADER_MODE_UART  0
/* Includes ----------------------------------------------------------------------*/
#include PLATFORM_HEADER

/* Exported types --------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
extern unsigned long _etext;
extern unsigned long _sidata;		/* start address for the initialization values of the .data section. defined in linker script */
extern unsigned long _sdata;		/* start address for the .data section. defined in linker script */
extern unsigned long _edata;		/* end address for the .data section. defined in linker script */

extern unsigned long _sbss;			/* start address for the .bss section. defined in linker script */
extern unsigned long _ebss;			/* end address for the .bss section. defined in linker script */

extern unsigned long _estack;		/* init value for the stack pointer. defined in linker script */

#include "hal/micro/cortexm3/memmap.h"
VAR_AT_SEGMENT(const HalFixedAddressTableType halFixedAddressTable, __FAT__);


/* Private typedef -----------------------------------------------------------*/

/* function prototypes ------------------------------------------------------*/
void Reset_Handler(void) __attribute__((__interrupt__));
extern int main(void);
extern void  halInternalSwitchToXtal(void);
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/

/* Weak definitions of handlers point to Default_Handler if not implemented */
void NMI_Handler() __attribute__ ((weak, alias("Default_Handler")));
void HardFault_Handler() __attribute__ ((weak, alias("Default_Handler")));
void MemManage_Handler() __attribute__ ((weak, alias("Default_Handler")));
void BusFault_Handler() __attribute__ ((weak, alias("Default_Handler")));
void UsageFault_Handler() __attribute__ ((weak, alias("Default_Handler")));
void SVC_Handler() __attribute__ ((weak, alias("Default_Handler")));
void DebugMonitor_Handler() __attribute__ ((weak, alias("Default_Handler")));
void PendSV_Handler() __attribute__ ((weak, alias("Default_Handler")));
void SysTick_Handler() __attribute__ ((weak, alias("Default_Handler")));
void halTimer1Isr() __attribute__ ((weak, alias("Default_Handler")));
void halTimer2Isr() __attribute__ ((weak, alias("Default_Handler")));
void halManagementIsr() __attribute__ ((weak, alias("Default_Handler")));
void halBaseBandIsr() __attribute__ ((weak, alias("Default_Handler")));
void halSleepTimerIsr() __attribute__ ((weak, alias("Default_Handler")));
void halSc1Isr() __attribute__ ((weak, alias("Default_Handler")));
void halSc2Isr() __attribute__ ((weak, alias("Default_Handler")));
void halSecurityIsr() __attribute__ ((weak, alias("Default_Handler")));
void halStackMacTimerIsr() __attribute__ ((weak, alias("Default_Handler")));
void stmRadioTransmitIsr() __attribute__ ((weak, alias("Default_Handler")));
void stmRadioReceiveIsr() __attribute__ ((weak, alias("Default_Handler")));
void halAdcIsr() __attribute__ ((weak, alias("Default_Handler")));
void halIrqAIsr() __attribute__ ((weak, alias("Default_Handler")));
void halIrqBIsr() __attribute__ ((weak, alias("Default_Handler")));
void halIrqCIsr() __attribute__ ((weak, alias("Default_Handler")));
void halIrqDIsr() __attribute__ ((weak, alias("Default_Handler")));
void halDebugIsr() __attribute__ ((weak, alias("Default_Handler")));

void __attribute__ ((weak)) Default_Handler()
{
	/* Hang here */
	while(1)
	{
	}
}


/******************************************************************************
*
* The minimal vector table for a Cortex M3.  Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/


__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
  (void (*)(void))&_estack,            // The initial stack pointer
  Reset_Handler,             // 1 The reset handler
  NMI_Handler,              // 2
  HardFault_Handler,         // 3
  MemManage_Handler,         // 4
  BusFault_Handler,          // 5
  UsageFault_Handler,        // 6
  RESERVED,                  // 7
  RESERVED,                  // 8
  RESERVED,                  // 9
  RESERVED,                  // 10
  SVC_Handler,               // 11
  DebugMonitor_Handler,      // 12
  RESERVED,                  // 13
  PendSV_Handler,            // 14
  SysTick_Handler,           // 15
  halTimer1Isr,              // 16
  halTimer2Isr,              // 17
  halManagementIsr,          // 18
  halBaseBandIsr,            // 19
  halSleepTimerIsr,          // 20
  halSc1Isr,                 // 21
  halSc2Isr,                 // 22
  halSecurityIsr,            // 23
  halStackMacTimerIsr,       // 24
  stmRadioTransmitIsr,       // 25
  stmRadioReceiveIsr,        // 26
  halAdcIsr,                 // 27
  halIrqAIsr,                // 28
  halIrqBIsr,                // 29
  halIrqCIsr,                // 30
  halIrqDIsr,                // 31
  halDebugIsr,               // 32
};

static  void setStackPointer(int32u address) __attribute__((noinline));
static void setStackPointer(int32u address)
{
  // This code is needed to generate the instruction below
  // that GNU ASM is refusing to add
  // asm("MOVS SP, r0");
  asm(".short 0x4685");
}

static const int16u blOffset[] = {
  0x0715 - 0x03ad - 0x68,
  0x0719 - 0x03ad - 0x6C
};

/*******************************************************************************
* 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) { ; }
  }

  //USART bootloader software activation check
  if ((*((int32u *)RAM_BOTTOM) == IAP_BOOTLOADER_APP_SWITCH_SIGNATURE) && (*((int8u *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART)){
    int8u cut = *(volatile int8u *) 0x08040798;
    int16u offset = 0;
    typedef void (*EntryPoint)(void);     
    offset = (halFixedAddressTable.baseTable.version == 3) ? blOffset[cut - 2] : 0;
    *((int32u *)RAM_BOTTOM) = 0;
    if (offset) {
      halInternalSwitchToXtal();
    }
    EntryPoint entryPoint = (EntryPoint)(*(int32u *)(FIB_BOTTOM+4) - offset);
    setStackPointer(*(int32u *)FIB_BOTTOM);
    entryPoint();
  }

  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();
}
#ifdef USE_HEAP
static unsigned char __HEAP_START[1024*3-560+0x200];
caddr_t _sbrk ( int incr )
{
  static unsigned char *heap = NULL;
  unsigned char *prev_heap;

  //printf ("_sbrk (%d)\n\r", incr);
  if (heap == NULL) {
    heap = (unsigned char *)__HEAP_START;
  }
  prev_heap = heap;
  /* check removed to show basic approach */
  if ((heap + incr) > (__HEAP_START + sizeof(__HEAP_START))) {
    prev_heap = NULL;
  } else {
    heap += incr;
  }
  if (prev_heap == NULL) {
    printf ("_sbrk %d return %p\n\r", incr, prev_heap);
  }
  return (caddr_t) prev_heap;
}
#else
caddr_t _sbrk ( int incr )
{
    return NULL;
}
#endif
int _lseek (int file,
	int ptr,
	int dir)
{
  return 0;
}
int _close (int file)
{
  return -1;
}

void _exit (int n)
{
  /* FIXME: return code is thrown away.  */
  while(1);
}



int _kill (int n, int m)
{
   return -1;
}
int _fstat(int file, struct stat *st)
{
  st->st_mode = S_IFCHR;
  return 0;
}
int _isatty (int fd)
{
  return 1;
  fd = fd;
}
int _getpid	(int n)
{
   return -1;
}
int _open (const char * path,
       int          flags,
       ...)
{
  return -1;
}
int _fflush_r(struct _reent *r, FILE *f)
{
  return 0;
}

/********************* (C) COPYRIGHT 2007 STMicroelectronics  *****END OF FILE****/


