text: /*******************************************************************************
  * File Name: Cm0Start.c
  * Version 4.20
  *
  *  Description:
  *  Startup code for the ARM CM0.
  *
  ********************************************************************************
  * Copyright 2010-2014, Cypress Semiconductor Corporation.  All rights reserved.
  * You may use this file only in accordance with the license, terms, conditions,
  * disclaimers, and limitations in the end user license agreement accompanying
  * the software package with which this file was provided.
  *******************************************************************************/
  
  #include <limits.h>
  #include "cydevice_trm.h"
  #include "cytypes.h"
  #include "cyfitter_cfg.h"
  #include "CyLib.h"
  #include "cyfitter.h"
  
  #define CY_NUM_VECTORS              (CY_INT_IRQ_BASE + CY_NUM_INTERRUPTS)
  #define CY_CPUSS_CONFIG_VECT_IN_RAM (( uint32 ) 0x01)
  
  /* CPUSS Configuration register */
  #define CY_CPUSS_CONFIG_REG         (*(reg32 *) CYREG_CPUSS_CONFIG)
  #define CY_CPUSS_CONFIG_PTR         ( (reg32 *) CYREG_CPUSS_CONFIG)
  
  
  #if defined (__ICCARM__)
      #define CY_NUM_ROM_VECTORS      (CY_NUM_VECTORS)
  #else
      #define CY_NUM_ROM_VECTORS      (4u)
  #endif  /* defined (__ICCARM__) */
  
  #if defined(__ARMCC_VERSION)
      #define INITIAL_STACK_POINTER ((cyisraddress)(uint32)&Image$$ARM_LIB_STACK$$ZI$$Limit)
  #elif defined (__GNUC__)
      #define INITIAL_STACK_POINTER (&__cy_stack)
  #elif defined (__ICCARM__)
      #pragma language=extended
      #pragma segment="CSTACK"
      #define INITIAL_STACK_POINTER  { .__ptr = __sfe( "CSTACK" ) }
  
      extern void __iar_program_start( void );
      extern void __iar_data_init3 (void);
  #endif  /* (__ARMCC_VERSION) */
  
  #if defined(__GNUC__)
      #include <errno.h>
      extern int  errno;
      extern int  end;
  #endif  /* defined(__GNUC__) */
  
  /* Extern functions */
  extern void CyBtldr_CheckLaunch(void);
  
  /* Function prototypes */
  void initialize_psoc(void);
  
  /* Global variables */
  #if !defined (__ICCARM__)
      CY_NOINIT static uint32 cySysNoInitDataValid;
  #endif  /* !defined (__ICCARM__) */
  
  
  #if (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_STANDARD)
  
      /*******************************************************************************
      This variable is used by the Bootloader/Bootloadable components to schedule
      what application will be started after a software reset.
      *******************************************************************************/
      #if (__ARMCC_VERSION)
          __attribute__ ((section(".bootloaderruntype"), zero_init))
      #elif defined (__GNUC__)
          __attribute__ ((section(".bootloaderruntype")))
      #elif defined (__ICCARM__)
          #pragma location=".bootloaderruntype"
      #endif /* (__ARMCC_VERSION) */
      volatile uint32 cyBtldrRunType;
  
  #endif  /* (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_STANDARD) */
  
  
  /*******************************************************************************
  * Function Name: IntDefaultHandler
  ********************************************************************************
  *
  * Summary:
  *  This function is called for all interrupts, other than a reset that is called
  *  before the system is setup.
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None
  *
  * Theory:
  *   Any value other than zero is acceptable.
  *
  *******************************************************************************/
  CY_NORETURN
  CY_ISR(IntDefaultHandler)
  {
      /***************************************************************************
      * We must not get here. If we do, a serious problem occurs, so go into
      * an infinite loop.
      ***************************************************************************/
      while(1)
      {
  
      }
  }
  
  #if defined(__ARMCC_VERSION)
  
  /* Local function for device reset. */
  extern void Reset(void);
  
  /* Application entry point. */
  extern void $Super$$main(void);
  
  /* Linker-generated Stack Base addresses, Two Region and One Region */
  extern unsigned long Image$$ARM_LIB_STACK$$ZI$$Limit;
  
  /* RealView C Library initialization. */
  extern int __main(void);
  
  
  /*******************************************************************************
  * Function Name: Reset
  ********************************************************************************
  *
  * Summary:
  *  This function handles the reset interrupt for the RVDS/MDK toolchains.
  *  This is the first bit of code that is executed at startup.
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  void Reset(void)
  {
      #if (CYDEV_PROJ_TYPE == CYDEV_PROJ_TYPE_LOADABLE)
          /* The bootloadable application image is started at Reset() handler
          * as a result of a branch instruction execution from the bootloader.
          * So, the stack pointer needs to be reset to be sure that
          * there is no garbage in the stack.
          */
          register uint32_t msp __asm("msp");
          msp = (uint32_t)&Image$$ARM_LIB_STACK$$ZI$$Limit;
      #endif /* CYDEV_PROJ_TYPE_LOADABLE */
  
      #if(CY_IP_SRSSLT)
          CySysWdtDisable();
      #endif  /* (CY_IP_SRSSLT) */
  
      #if (CYDEV_BOOTLOADER_ENABLE)
          CyBtldr_CheckLaunch();
      #endif /* CYDEV_BOOTLOADER_ENABLE */
  
      __main();
  }
  
  /*******************************************************************************
  * Function Name: $Sub$$main
  ********************************************************************************
  *
  * Summary:
  *  This function is called immediately before the users main
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  __attribute__ ((noreturn))
  void $Sub$$main(void)
  {
      initialize_psoc();
  
      /* Call original main */
      $Super$$main();
  
      while (1)
      {
          /* If main returns it is undefined what we should do. */
      }
  }
  
  #elif defined(__GNUC__)
  
  /* Stack Base address */
  extern void __cy_stack(void);
  
  /* Application entry point. */
  extern int main(void);
  
  /* The static objects constructors initializer */
  extern void __libc_init_array(void);
  
  typedef unsigned char __cy_byte_align8 __attribute ((aligned (8)));
  
  struct __cy_region
  {
      __cy_byte_align8 *init; /* Initial contents of this region.  */
      __cy_byte_align8 *data; /* Start address of region.  */
      size_t init_size;       /* Size of initial data.  */
      size_t zero_size;       /* Additional size to be zeroed.  */
  };
  
  extern const struct __cy_region __cy_regions[];
  extern const char __cy_region_num __attribute__((weak));
  #define __cy_region_num ((size_t)&__cy_region_num)
  
  
  /*******************************************************************************
  * System Calls of the Red Hat newlib C Library
  *******************************************************************************/
  
  
  /*******************************************************************************
  * Function Name: _exit
  ********************************************************************************
  *
  * Summary:
  *  Exit a program without cleaning up files. If your system doesn't provide
  *  this, it is best to avoid linking with subroutines that require it (exit,
  *  system).
  *
  * Parameters:
  *  status: Status caused program exit.
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  __attribute__((weak))
  void _exit(int status)
  {
      /* Cause divide by 0 exception */
      int x = status / (int) INT_MAX;
      x = 4 / x;
  
      while(1)
      {
  
      }
  }
  
  
  /*******************************************************************************
  * Function Name: _sbrk
  ********************************************************************************
  *
  * Summary:
  *  Increase program data space. As malloc and related functions depend on this,
  *  it is useful to have a working implementation. The following suffices for a
  *  standalone system; it exploits the symbol end automatically defined by the
  *  GNU linker.
  *
  * Parameters:
  *  nbytes: The number of bytes requested (if the parameter value is positive)
  *  from the heap or returned back to the heap (if the parameter value is
  *  negative).
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  __attribute__((weak))
  void * _sbrk (int nbytes)
  {
      extern int  end;            /* Symbol defined by linker map. Start of free memory (as symbol). */
      void *      returnValue;
  
      /* The statically held previous end of the heap, with its initialization. */
      static void *heapPointer = (void *) &end;                 /* Previous end */
  
      if (((heapPointer + nbytes) - (void *) &end) <= CYDEV_HEAP_SIZE)
      {
          returnValue  = heapPointer;
          heapPointer += nbytes;
      }
      else
      {
          errno = ENOMEM;
          returnValue = (void *) -1;
      }
  
      return (returnValue);
  }
  
  
  /*******************************************************************************
  * Function Name: Start_c
  ********************************************************************************
  *
  * Summary:
  *  This function handles initializing the .data and .bss sections in
  *  preparation for running the standard c code.  Once initialization is complete
  *  it will call main().  This function will never return.
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  void Start_c(void)  __attribute__ ((noreturn));
  void Start_c(void)
  {
      unsigned regions = __cy_region_num;
      const struct __cy_region *rptr = __cy_regions;
  
      /* Initialize memory */
      for (regions = __cy_region_num; regions != 0u; regions--)
      {
          uint32 *src = (uint32 *)rptr->init;
          uint32 *dst = (uint32 *)rptr->data;
          unsigned limit = rptr->init_size;
          unsigned count;
  
          for (count = 0u; count != limit; count += sizeof (uint32))
          {
              *dst = *src;
              dst++;
              src++;
          }
          limit = rptr->zero_size;
          for (count = 0u; count != limit; count += sizeof (uint32))
          {
              *dst = 0u;
              dst++;
          }
  
          rptr++;
      }
  
      /* Invoke static objects constructors */
      __libc_init_array();
      (void) main();
  
      while (1)
      {
          /* If main returns, make sure we don't return. */
      }
  }
  
  
  /*******************************************************************************
  * Function Name: Reset
  ********************************************************************************
  *
  * Summary:
  *  This function handles the reset interrupt for the GCC toolchain.  This is
  *  the first bit of code that is executed at startup.
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  void Reset(void)
  {
      #if (CYDEV_PROJ_TYPE == CYDEV_PROJ_TYPE_LOADABLE)
          /* The bootloadable application image is started at Reset() handler
          * as a result of a branch instruction execution from the bootloader.
          * So, the stack pointer needs to be reset to be sure that
          * there is no garbage in the stack.
          */
          __asm volatile ("MSR msp, %0\n" : : "r" ((uint32)&__cy_stack) : "sp");
      #endif /* CYDEV_PROJ_TYPE_LOADABLE */
  
      #if(CY_IP_SRSSLT)
          CySysWdtDisable();
      #endif  /* (CY_IP_SRSSLT) */
  
      #if (CYDEV_BOOTLOADER_ENABLE)
          CyBtldr_CheckLaunch();
      #endif /* CYDEV_BOOTLOADER_ENABLE */
      Start_c();
  }
  
  #elif defined (__ICCARM__)
  
  
  /*******************************************************************************
  * Function Name: __low_level_init
  ********************************************************************************
  *
  * Summary:
  *  This function performs early initializations for the IAR Embedded
  *  Workbench IDE. It is executed in the context of reset interrupt handler
  *  before the data sections are initialized.
  *
  * Parameters:
  *  None
  *
  * Return:
  *  The value that determines whether or not data sections should be initialized
  *  by the system startup code:
  *    0 - skip data sections initialization;
  *    1 - initialize data sections;
  *
  *******************************************************************************/
  int __low_level_init(void)
  {
      #if(CY_IP_SRSSLT)
          CySysWdtDisable();
      #endif  /* (CY_IP_SRSSLT) */
  
  #if (CYDEV_BOOTLOADER_ENABLE)
      CyBtldr_CheckLaunch();
  #endif /* CYDEV_BOOTLOADER_ENABLE */
  
      /* Initialize data sections */
      __iar_data_init3();
  
      initialize_psoc();
  
      return 0;
  }
  
  #endif /* __GNUC__ */
  
  
  /*******************************************************************************
  * Ram Interrupt Vector table storage area. Must be placed at 0x20000000.
  *******************************************************************************/
  
  #if defined (__ICCARM__)
      #pragma location=".ramvectors"
  #else
      CY_SECTION(".ramvectors")
  #endif  /* defined (__ICCARM__) */
  cyisraddress CyRamVectors[CY_NUM_VECTORS];
  
  
  /*******************************************************************************
  * Rom Interrupt Vector table storage area. Must be 256-byte aligned.
  *******************************************************************************/
  
  #if defined(__ARMCC_VERSION)
      /* Suppress diagnostic message 1296-D: extended constant initialiser used */
      #pragma diag_suppress 1296
  #endif  /* defined(__ARMCC_VERSION) */
  
  #if defined (__ICCARM__)
      #pragma location=".romvectors"
      const intvec_elem __vector_table[CY_NUM_ROM_VECTORS] =
  #else
      CY_SECTION(".romvectors")
      const cyisraddress RomVectors[CY_NUM_ROM_VECTORS] =
  #endif  /* defined (__ICCARM__) */
  {
      INITIAL_STACK_POINTER,   /* The initial stack pointer  0 */
      #if defined (__ICCARM__) /* The reset handler          1 */
          __iar_program_start,
      #else
          (cyisraddress)&Reset,
      #endif  /* defined (__ICCARM__) */
      &IntDefaultHandler,      /* The NMI handler            2 */
      &IntDefaultHandler,      /* The hard fault handler     3 */
  };
  
  #if defined(__ARMCC_VERSION)
      #pragma diag_default 1296
  #endif  /* defined(__ARMCC_VERSION) */
  
  
  /*******************************************************************************
  * Function Name: initialize_psoc
  ********************************************************************************
  *
  * Summary:
  *  This function is used to initialize the PSoC chip before calling main.
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None
  *
  *******************************************************************************/
  #if(defined(__GNUC__) && !defined(__ARMCC_VERSION))
  __attribute__ ((constructor(101)))
  #endif  /* (defined(__GNUC__) && !defined(__ARMCC_VERSION)) */
  void initialize_psoc(void)
  {
      uint32 indexInit;
  
      #if(CY_IP_CPUSSV2)
          /***********************************************************************
          * Make sure that Vector Table is located at 0000_0000 in Flash, before
          * accessing RomVectors or calling functions that may be placed in
          * .psocinit (cyfitter_cfg and ClockSetup). Note The CY_CPUSS_CONFIG_REG
          * register is retention for the specified device family.
          ***********************************************************************/
          CY_CPUSS_CONFIG_REG &= (uint32) ~CY_CPUSS_CONFIG_VECT_IN_RAM;
      #endif  /* (CY_IP_CPUSSV2) */
  
      /* Set Ram interrupt vectors to default functions. */
      for (indexInit = 0u; indexInit < CY_NUM_VECTORS; indexInit++)
      {
          CyRamVectors[indexInit] = (indexInit < CY_NUM_ROM_VECTORS) ?
              #if defined (__ICCARM__)
                  __vector_table[indexInit].__fun : &IntDefaultHandler;
              #else
                  RomVectors[indexInit] : &IntDefaultHandler;
              #endif  /* defined (__ICCARM__) */
      }
  
      /* Initialize configuration registers. */
      cyfitter_cfg();
  
      #if !defined (__ICCARM__)
          /* Actually, no need to clean this variable, just to make compiler happy. */
          cySysNoInitDataValid = 0u;
      #endif  /* !defined (__ICCARM__) */
  
      #if (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_STANDARD)
  
          /* Need to make sure that this variable will not be optimized out */
          if (0u == cyBtldrRunType)
          {
              cyBtldrRunType = 0u;
          }
  
      #endif  /* (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_STANDARD) */
  
      /* Vector Table is located at 0x2000:0000 in SRAM */
      CY_CPUSS_CONFIG_REG |= CY_CPUSS_CONFIG_VECT_IN_RAM;
  }
  
  
  /* [] END OF FILE */
  