/*--------------------------------------------------------------/
/  Startup Module for NXP LPC1100 Microcontrollers              /
/                                                               /
/ * This module defines vector table, startup code, default     /
/   exception handlers, main stack and miscellanous functions.  /
/ * This file is a non-copyrighted public domain software.      /
/--------------------------------------------------------------*/

#include "LPC1100.h"

/*-------------------------------------------------------------------*/
/* スタック・サイズとクロックの設定                                  */

#define STACK_SIZE 512  /* スタック・サイズ[バイト] (8の倍数であること. 0を設定するとRAMの最後尾から使う) */

#define CLK_SEL 3           /* メイン・クロック源 = 0:IRC(12MHz), 1:PLL-in, 2:WDT or 3:PLL-out */
#define OSC_SEL 0           /* PLL入力 = 0:IRC osc or 1:Main osc */
#define F_OSC   12000000    /* 発振器周波数(IRCを使う場合12M) */
#define PLL_M   4           /* PLL逓倍数 = 1..32 */
#define MCLK    48000000    /* メイン・クロックの想定値 = F_OSC * (CLK_SEL == 3 ? PLL_M : 1) */
#define	SYSCLK	(MCLK / 1)	/* システム・クロック (MCLKの1/n) */

/*-------------------------------------------------------------------*/


#if MCLK != F_OSC * (CLK_SEL == 3 ? PLL_M : 1)
#error MCLK does not match calcurated value
#endif

#if CLK_SEL == 3
#if F_OSC < 10000000 || F_OSC > 25000000
#error F_OSC is out of range for PLL input
#endif
#if MCLK * 2 >= 156000000
#define P_SEL 0
#elif MCLK * 4 >= 156000000
#define P_SEL 1
#elif MCLK * 8 >= 156000000
#define P_SEL 2
#else
#define P_SEL 3
#endif
#endif

#if   SYSCLK <= 20000000
#define FLASH_WAIT 0
#elif SYSCLK <= 40000000
#define FLASH_WAIT 1
#else
#define FLASH_WAIT 2
#endif



/*--------------------------------------------------------------------/
/ 各種宣言                                                            /
/--------------------------------------------------------------------*/

/* 外部シンボル */
extern long _sidata[], _sdata[], _edata[], _sbss[], _ebss[], _endof_sram[]; /* 各セクション (リンカ・スクリプトで定義) */
extern int main (void);

/* 割り込みハンドラの宣言 */
void Reset_Handler (void)      __attribute__ ((noreturn, naked));
void NMI_Handler (void)        __attribute__ ((weak, alias ("Exception_Trap")));
void HardFault_Hander (void)   __attribute__ ((weak, alias ("Exception_Trap")));
void SVC_Handler (void)        __attribute__ ((weak, alias ("Exception_Trap")));
void PendSV_Handler (void)     __attribute__ ((weak, alias ("Exception_Trap")));
void SysTick_Handler (void)    __attribute__ ((weak, alias ("Exception_Trap")));
void PIO0_0_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_1_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_2_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_3_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_4_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_5_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_6_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_7_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_8_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_9_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_10_IRQHandler (void) __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO0_11_IRQHandler (void) __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO1_0_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void C_CAN_IRQHandler (void)   __attribute__ ((weak, alias ("IRQ_Trap")));
void SPI1_IRQHandler (void)    __attribute__ ((weak, alias ("IRQ_Trap")));
void I2C_IRQHandler (void)     __attribute__ ((weak, alias ("IRQ_Trap")));
void CT16B0_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void CT16B1_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void CT32B0_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void CT32B1_IRQHandler (void)  __attribute__ ((weak, alias ("IRQ_Trap")));
void SPI0_IRQHandler (void)    __attribute__ ((weak, alias ("IRQ_Trap")));
void UART_IRQHandler (void)    __attribute__ ((weak, alias ("IRQ_Trap")));
void ADC_IRQHandler (void)     __attribute__ ((weak, alias ("IRQ_Trap")));
void WDT_IRQHandler (void)     __attribute__ ((weak, alias ("IRQ_Trap")));
void BOD_IRQHandler (void)     __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO_3_IRQHandler (void)   __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO_2_IRQHandler (void)   __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO_1_IRQHandler (void)   __attribute__ ((weak, alias ("IRQ_Trap")));
void PIO_0_IRQHandler (void)   __attribute__ ((weak, alias ("IRQ_Trap")));



/*--------------------------------------------------------------------/
/ メイン・スタック (スタック領域に配置)                               /
/--------------------------------------------------------------------*/

#if STACK_SIZE > 0  /* スタック領域を確保するとき */
static
char mstk[STACK_SIZE] __attribute__ ((aligned(8), section(".STACK")));
#define INITIAL_MSP	&mstk[STACK_SIZE]

#else               /* スタック領域を確保しないとき */
#define INITIAL_MSP	_endof_sram
#endif



/*--------------------------------------------------------------------/
/ ベクタ・テーブル (ROM先頭に配置)                                    /
/--------------------------------------------------------------------*/

const void* const vector[] __attribute__ ((section(".VECTOR"))) =
{
    INITIAL_MSP, /* MSPの初期値 (8バイト境界であること) */
    Reset_Handler,
    NMI_Handler,
    HardFault_Hander,
    0,
    0,
    0,
    0, /* チェック・サム NXP固有 (先頭からここまでを加算して0になるようにフラッシュ・プログラマが設定) */
    0,
    0,
    0,
    SVC_Handler,
    0,
    0,
    PendSV_Handler,
    SysTick_Handler,

    PIO0_0_IRQHandler,
    PIO0_1_IRQHandler,
    PIO0_2_IRQHandler,
    PIO0_3_IRQHandler,
    PIO0_4_IRQHandler,
    PIO0_5_IRQHandler,
    PIO0_6_IRQHandler,
    PIO0_7_IRQHandler,
    PIO0_8_IRQHandler,
    PIO0_9_IRQHandler,
    PIO0_10_IRQHandler,
    PIO0_11_IRQHandler,
    PIO1_0_IRQHandler,
    C_CAN_IRQHandler,
    SPI1_IRQHandler,
    I2C_IRQHandler,
    CT16B0_IRQHandler,
    CT16B1_IRQHandler,
    CT32B0_IRQHandler,
    CT32B1_IRQHandler,
    SPI0_IRQHandler,
    UART_IRQHandler,
    0,
    0,
    ADC_IRQHandler,
    WDT_IRQHandler,
    BOD_IRQHandler,
    0,
    PIO_3_IRQHandler,
    PIO_2_IRQHandler,
    PIO_1_IRQHandler,
    PIO_0_IRQHandler
};



/*---------------------------------------------------------------------/
/ リセット・ハンドラ                                                   /
/---------------------------------------------------------------------*/

void Reset_Handler (void)
{
    long *s, *d;

    BODCTRL = 0x13;   /* BODの設定 (2.7Vでリセット) */

   /* クロック周りの初期化 */

    MAINCLKSEL = 0;  /* メイン・クロックとして一時的にIRCを選択 */
    MAINCLKUEN = 0; MAINCLKUEN = 1;

    FLASHCFG = (FLASHCFG & 0xFFFFFFFC) | FLASH_WAIT;  /* フラッシュ・メモリのウェイト数 */

#if CLK_SEL == 1 || (CLK_SEL == 3 && OSC_SEL == 1)   /* 必要なら発振回路を起動 */
    SYSOSCCTRL = (F_OSC >= 17500000) ? 2 : 0;
    PDRUNCFG &= ~0x20;
#endif
#if CLK_SEL == 2  /* 必要ならWDT発振器を起動 */
    PDRUNCFG &= ~0x40;
#endif
#if CLK_SEL == 3  /* 必要ならPLLを初期化 */
    SYSPLLCLKSEL = OSC_SEL;
    SYSPLLCLKUEN = 0; SYSPLLCLKUEN = 1;
    SYSPLLCTRL = (PLL_M - 1) | (P_SEL << 6);
    PDRUNCFG &= ~0x80;
    while ((SYSPLLSTAT & 1) == 0) ; /* PLLのロックを待つ */
#endif

    SYSAHBCLKDIV = MCLK / SYSCLK; /* システム・クロック分周器を設定 */
    MAINCLKSEL = CLK_SEL;         /* 目的のクロック・ソースを選択 */
    MAINCLKUEN = 0; MAINCLKUEN = 1;

    SYSAHBCLKCTRL = 0x1005F;  /* 周辺モジュールへのクロック供給 (SYS, ROM, RAM, FLASH, GPIO と IOCON のみ) */


    /* .data/.bss セクションの初期化(これ以降静的変数が使用可) */
    for (s = _sidata, d = _sdata; d < _edata; *d++ = *s++) ;
    for (d = _sbss; d < _ebss; *d++ = 0) ;


    main();  /* main()へ制御を移す */

    for (;;) ;
}



/*--------------------------------------------------------------------/
/ 意図しない例外のトラップ                                            /
/--------------------------------------------------------------------*/

void Exception_Trap (void)
{
    for (;;) ;
}


void IRQ_Trap (void)
{
    for (;;) ;
}

