Project

General

Profile

/*******************************************************************************
* File Name: Cm0Start.c
* Version 5.0
*
* Description:
* Startup code for the ARM CM0.
*
********************************************************************************
* Copyright 2010-2015, 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 || CYDEV_PROJ_TYPE == CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)
/* 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 == CYDEV_PROJ_TYPE_LOADABLE || CYDEV_PROJ_TYPE == CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)*/

#if(CY_IP_SRSSLT)
CySysWdtDisable();
#endif /* (CY_IP_SRSSLT) */

#if ((CYDEV_BOOTLOADER_ENABLE) && (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER))
CyBtldr_CheckLaunch();
#endif /* ((CYDEV_BOOTLOADER_ENABLE) && (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)) */

__main();
}

/*******************************************************************************
* Function Name: $Sub$$main
********************************************************************************
*
* Summary:
* This function is called immediately before the users main
*
* Parameters:
* None
*
* Return:
* None
*
*******************************************************************************/
__attribute__ ((noreturn, __noinline__))
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)
{
CyHalt((uint8) status);

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, noinline));
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 || CYDEV_PROJ_TYPE == CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)

/* 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) && (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER))
CyBtldr_CheckLaunch();
#endif /* ((CYDEV_BOOTLOADER_ENABLE) && (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)) */
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;
*
*******************************************************************************/
#pragma inline = never
int __low_level_init(void)
{
#if(CY_IP_SRSSLT)
CySysWdtDisable();
#endif /* (CY_IP_SRSSLT) */

#if ((CYDEV_BOOTLOADER_ENABLE) && (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER))
CyBtldr_CheckLaunch();
#endif /* ((CYDEV_BOOTLOADER_ENABLE) && (CYDEV_PROJ_TYPE != CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER)) */

/* 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 */
(54-54/102)