/*
 * Copyright (c) 2024, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdint.h>
#include <ti/devices/msp/msp.h>
#include "flashBSL_invocation.h"

/* Linker variable that marks the top of the stack. */
extern unsigned long __STACK_END;

/* External declaration for the reset handler that is to be called when the */
/* processor is started                                                     */
extern __NO_RETURN void __PROGRAM_START(void);

/* Forward declaration of the default fault handlers. */
void Default_Handler(void) __attribute__((weak));
//extern void Reset_Handler(void) __attribute__((weak));
extern void Invocation_Reset_Handler(void) __attribute__((weak));

/* Processor Exceptions */
extern void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
extern void HardFault_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void MemManage_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void BusFault_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void UsageFault_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void SecureFault_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void SVC_Handler(void) __attribute__((weak, alias("Default_Handler")));
extern void DebugMon_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void PendSV_Handler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void SysTick_Handler(void)
    __attribute__((weak, alias("Default_Handler")));

/* Device Specific Interrupt Handlers */
extern void GROUP0_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void GPIOA_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void TIMG8_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void ADC0_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void SPI0_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void UART0_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void TIMG14_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void TIMA0_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void I2C0_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));
extern void DMA_IRQHandler(void)
    __attribute__((weak, alias("Default_Handler")));


/* Interrupt vector table.  Note that the proper constructs must be placed on this to */
/* ensure that it ends up at physical address 0x0000.0000 or at the start of          */
/* the program if located at a start address other than 0.                            */
#if defined(__ARM_ARCH) && (__ARM_ARCH != 0)
void (*const interruptVectors[])(void) __attribute((used))
__attribute__((section(".intvecs"))) =
#elif defined(__TI_ARM__)
#pragma RETAIN(interruptVectors)
#pragma DATA_SECTION(interruptVectors, ".intvecs")
void (*const interruptVectors[])(void) =
#else
#error "Compiler not supported"
#endif
    {
        (void (*)(void))((uint32_t) &__STACK_END),
        /* The initial stack pointer */
        Invocation_Reset_Handler, /* The reset handler         */
        NMI_Handler,              /* The NMI handler           */
        HardFault_Handler,        /* The hard fault handler    */
        MemManage_Handler,        /* The MPU fault handler     */
        BusFault_Handler,         /* The bus fault handler     */
        UsageFault_Handler,       /* The usage fault handler   */
        SecureFault_Handler,      /* The secure fault handler  */
        0,                        /* Reserved                  */
        0,                        /* Reserved                  */
        0,                        /* Reserved                  */
        SVC_Handler,              /* SVCall handler            */
        DebugMon_Handler,         /* Debug monitor handler     */
        0,                        /* Reserved                  */
        PendSV_Handler,           /* The PendSV handler        */
        SysTick_Handler,           /* SysTick handler           */
        GROUP0_IRQHandler, /* GROUP0 interrupt handler  */
        GPIOA_IRQHandler,  /* GPIOA interrupt handler   */
        TIMG8_IRQHandler,  /* TIMG8 interrupt handler   */
        0,                 /* Reserved                  */
        ADC0_IRQHandler,   /* ADC0 interrupt handler    */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        SPI0_IRQHandler,   /* SPI0 interrupt handler    */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        UART0_IRQHandler,  /* UART0 interrupt handler   */
        TIMG14_IRQHandler, /* TIMG14 interrupt handler  */
        0,                 /* Reserved                  */
        TIMA0_IRQHandler,  /* TIMA0 interrupt handler   */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        I2C0_IRQHandler,   /* I2C0 interrupt handler    */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        0,                 /* Reserved                  */
        DMA_IRQHandler,    /* DMA interrupt handler     */
    };

/* Forward declaration of the default fault handlers. */
/* 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 entry() routine is called.  Any fancy  */
/* actions (such as making decisions based on the reset cause register, and    */
/* resetting the bits in that register) are left solely in the hands of the    */
/* application.                                                                */

__attribute__((retain)) __attribute__((section(".flashBSL_start"))) void
FlashBSL_Reset_Handler(void)
{
    SCB->VTOR = (volatile uint32_t) interruptVectors;

    /* Jump to the ticlang C Initialization Routine. */
    __asm(
        "    .global _c_int00\n"
        "    b       _c_int00");
}
__attribute__((retain)) __attribute__((section(".invStart"))) void
Invocation_Reset_Handler(void)
{
    invocation_check();
}

/* This is the code that gets called when the processor receives an unexpected  */
/* interrupt.  This simply enters an infinite loop, preserving the system state */
/* for examination by a debugger.                                               */
void Default_Handler(void)
{
    /* Enter an infinite loop. */
    while (1) {
    }
}
