/*****************************************************************************

  Copyright (C) 2024 Texas Instruments Incorporated - http://www.ti.com/

  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 "msp.h"

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

/*
 * Linker symbols for BSS section (uninitialized data)
 * These are used to clear BSS to zero during startup
 */
extern unsigned char __ghsbegin_bss[];
extern unsigned char __ghsend_bss[];

/* Main function prototype */
extern int main(void);

/*
 * Simple memset implementation for GHS
 * This avoids relying on the GHS library memset which may require
 * additional runtime initialization that is not performed in our
 * minimal startup code.
 */
void *memset(void *dest, int c, unsigned int n)
{
    unsigned char *d = (unsigned char *)dest;
    unsigned char val = (unsigned char)c;
    
    while (n > 0U) {
        *d++ = val;
        n--;
    }
    
    return dest;
}

/*
 * Simple memcpy implementation for GHS
 * This avoids relying on the GHS library memcpy which may require
 * additional runtime initialization.
 */
void *memcpy(void *dest, const void *src, unsigned int n)
{
    unsigned char *d = (unsigned char *)dest;
    const unsigned char *s = (const unsigned char *)src;
    
    while (n > 0U) {
        *d++ = *s++;
        n--;
    }
    
    return dest;
}

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

/* Processor Exceptions */
#pragma weak NMI_Handler = Default_Handler
#pragma weak HardFault_Handler = Default_Handler
#pragma weak SVC_Handler = Default_Handler
#pragma weak PendSV_Handler = Default_Handler
#pragma weak SysTick_Handler = Default_Handler

extern void NMI_Handler(void);
extern void HardFault_Handler(void);
extern void SVC_Handler(void);
extern void PendSV_Handler(void);
extern void SysTick_Handler(void);

/* Device Specific Interrupt Handlers */
#pragma weak SYSCTL_IRQHandler = Default_Handler
#pragma weak DEBUGSS_IRQHandler = Default_Handler
#pragma weak FLASHCTL_IRQHandler = Default_Handler
#pragma weak WWDT0_IRQHandler = Default_Handler
#pragma weak GPIOA_IRQHandler = Default_Handler
#pragma weak GPIOB_IRQHandler = Default_Handler
#pragma weak GPIOC_IRQHandler = Default_Handler
#pragma weak ADC0_SEQ0_IRQHandler = Default_Handler
#pragma weak ADC0_SEQ1_IRQHandler = Default_Handler
#pragma weak ADC0_SEQ2_IRQHandler = Default_Handler
#pragma weak ADC0_SEQ3_IRQHandler = Default_Handler
#pragma weak ADC0_DCOMP_IRQHandler = Default_Handler
#pragma weak ADC1_SEQ0_IRQHandler = Default_Handler
#pragma weak ADC1_SEQ1_IRQHandler = Default_Handler
#pragma weak ADC1_SEQ2_IRQHandler = Default_Handler
#pragma weak ADC1_SEQ3_IRQHandler = Default_Handler
#pragma weak ADC1_DCOMP_IRQHandler = Default_Handler
#pragma weak CANFD0_IRQHandler = Default_Handler
#pragma weak TIMA0_0_IRQHandler = Default_Handler
#pragma weak TIMG4_0_IRQHandler = Default_Handler
#pragma weak TIMG4_1_IRQHandler = Default_Handler
#pragma weak TIMG8_0_IRQHandler = Default_Handler
#pragma weak TIMG12_0_IRQHandler = Default_Handler
#pragma weak UC1_0_IRQHandler = Default_Handler
#pragma weak UC1_1_IRQHandler = Default_Handler
#pragma weak UC2_IRQHandler = Default_Handler
#pragma weak UC15_0_IRQHandler = Default_Handler
#pragma weak UC15_1_IRQHandler = Default_Handler
#pragma weak UC12_IRQHandler = Default_Handler
#pragma weak UC13_0_IRQHandler = Default_Handler
#pragma weak UC14_IRQHandler = Default_Handler
#pragma weak CANFD1_IRQHandler = Default_Handler
#pragma weak TIMA0_1_IRQHandler = Default_Handler
#pragma weak TIMG4_2_IRQHandler = Default_Handler
#pragma weak TIMG4_3_IRQHandler = Default_Handler
#pragma weak TIMG8_1_IRQHandler = Default_Handler
#pragma weak COMP0_IRQHandler = Default_Handler
#pragma weak COMP1_IRQHandler = Default_Handler
#pragma weak TRNG_IRQHandler = Default_Handler
#pragma weak AESADV_IRQHandler = Default_Handler
#pragma weak LFSS_IRQHandler = Default_Handler
#pragma weak DMA0_IRQHandler = Default_Handler
#pragma weak DMA1_IRQHandler = Default_Handler
#pragma weak I2S0_IRQHandler = Default_Handler
#pragma weak I2S1_IRQHandler = Default_Handler
#pragma weak QSPI_IRQHandler = Default_Handler
#pragma weak SHAW_IRQHandler = Default_Handler
#pragma weak PKA_IRQHandler = Default_Handler
#pragma weak UC13_1_IRQHandler = Default_Handler
#pragma weak UC13_2_IRQHandler = Default_Handler
#pragma weak UC13_3_IRQHandler = Default_Handler

extern void SYSCTL_IRQHandler(void);
extern void DEBUGSS_IRQHandler(void);
extern void FLASHCTL_IRQHandler(void);
extern void WWDT0_IRQHandler(void);
extern void GPIOA_IRQHandler(void);
extern void GPIOB_IRQHandler(void);
extern void GPIOC_IRQHandler(void);
extern void ADC0_SEQ0_IRQHandler(void);
extern void ADC0_SEQ1_IRQHandler(void);
extern void ADC0_SEQ2_IRQHandler(void);
extern void ADC0_SEQ3_IRQHandler(void);
extern void ADC0_DCOMP_IRQHandler(void);
extern void ADC1_SEQ0_IRQHandler(void);
extern void ADC1_SEQ1_IRQHandler(void);
extern void ADC1_SEQ2_IRQHandler(void);
extern void ADC1_SEQ3_IRQHandler(void);
extern void ADC1_DCOMP_IRQHandler(void);
extern void CANFD0_IRQHandler(void);
extern void TIMA0_0_IRQHandler(void);
extern void TIMG4_0_IRQHandler(void);
extern void TIMG4_1_IRQHandler(void);
extern void TIMG8_0_IRQHandler(void);
extern void TIMG12_0_IRQHandler(void);
extern void UC1_0_IRQHandler(void);
extern void UC1_1_IRQHandler(void);
extern void UC2_IRQHandler(void);
extern void UC15_0_IRQHandler(void);
extern void UC15_1_IRQHandler(void);
extern void UC12_IRQHandler(void);
extern void UC13_0_IRQHandler(void);
extern void UC14_IRQHandler(void);
extern void CANFD1_IRQHandler(void);
extern void TIMA0_1_IRQHandler(void);
extern void TIMG4_2_IRQHandler(void);
extern void TIMG4_3_IRQHandler(void);
extern void TIMG8_1_IRQHandler(void);
extern void COMP0_IRQHandler(void);
extern void COMP1_IRQHandler(void);
extern void TRNG_IRQHandler(void);
extern void AESADV_IRQHandler(void);
extern void LFSS_IRQHandler(void);
extern void DMA0_IRQHandler(void);
extern void DMA1_IRQHandler(void);
extern void I2S0_IRQHandler(void);
extern void I2S1_IRQHandler(void);
extern void QSPI_IRQHandler(void);
extern void SHAW_IRQHandler(void);
extern void PKA_IRQHandler(void);
extern void UC13_1_IRQHandler(void);
extern void UC13_2_IRQHandler(void);
extern void UC13_3_IRQHandler(void);

/* 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.                            */
#pragma ghs section rodata=".intvecs"
void (*const interruptVectors[])(void) =
    {
        (void (*)(void))((uint32_t) &__ghsend_stack),
        /* The initial stack pointer */
        Reset_Handler,         /* The reset handler         */
        NMI_Handler,           /* The NMI handler           */
        HardFault_Handler,     /* The hard fault handler    */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        SVC_Handler,           /* SVCall handler            */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        PendSV_Handler,        /* The PendSV handler        */
        SysTick_Handler,       /* SysTick handler           */
        SYSCTL_IRQHandler,     /* SYSCTL interrupt handler  */
        DEBUGSS_IRQHandler,    /* DEBUGSS interrupt handler */
        FLASHCTL_IRQHandler,   /* FLASHCTL interrupt handler */
        WWDT0_IRQHandler,      /* WWDT0 interrupt handler   */
        0,                     /* Reserved                  */
        0,                     /* Reserved                  */
        GPIOA_IRQHandler,      /* GPIOA interrupt handler   */
        GPIOB_IRQHandler,      /* GPIOB interrupt handler   */
        GPIOC_IRQHandler,      /* GPIOC interrupt handler   */
        ADC0_SEQ0_IRQHandler,  /* ADC0 interrupt handler    */
        ADC0_SEQ1_IRQHandler,  /* ADC0 interrupt handler    */
        ADC0_SEQ2_IRQHandler,  /* ADC0 interrupt handler    */
        ADC0_SEQ3_IRQHandler,  /* ADC0 interrupt handler    */
        ADC0_DCOMP_IRQHandler, /* ADC0 interrupt handler    */
        ADC1_SEQ0_IRQHandler,  /* ADC1 interrupt handler    */
        ADC1_SEQ1_IRQHandler,  /* ADC1 interrupt handler    */
        ADC1_SEQ2_IRQHandler,  /* ADC1 interrupt handler    */
        ADC1_SEQ3_IRQHandler,  /* ADC1 interrupt handler    */
        ADC1_DCOMP_IRQHandler, /* ADC1 interrupt handler    */
        CANFD0_IRQHandler,     /* CANFD0 interrupt handler  */
        TIMA0_0_IRQHandler,    /* TIMA0_0 interrupt handler */
        TIMG4_0_IRQHandler,    /* TIMG4_0 interrupt handler */
        TIMG4_1_IRQHandler,    /* TIMG4_1 interrupt handler */
        TIMG8_0_IRQHandler,    /* TIMG8_0 interrupt handler */
        TIMG12_0_IRQHandler,   /* TIMG12_0 interrupt handler */
        UC1_0_IRQHandler,      /* UC1_0 interrupt handler   */
        UC1_1_IRQHandler,      /* UC1_1 interrupt handler   */
        UC2_IRQHandler,        /* UC2 interrupt handler     */
        UC15_0_IRQHandler,     /* UC15_0 interrupt handler  */
        UC15_1_IRQHandler,     /* UC15_1 interrupt handler  */
        UC12_IRQHandler,       /* UC12 interrupt handler    */
        UC13_0_IRQHandler,     /* UC13_0 interrupt handler  */
        UC14_IRQHandler,       /* UC14 interrupt handler    */
        CANFD1_IRQHandler,     /* CANFD1 interrupt handler  */
        TIMA0_1_IRQHandler,    /* TIMA0_1 interrupt handler */
        TIMG4_2_IRQHandler,    /* TIMG4_2 interrupt handler */
        TIMG4_3_IRQHandler,    /* TIMG4_3 interrupt handler */
        TIMG8_1_IRQHandler,    /* TIMG8_1 interrupt handler */
        COMP0_IRQHandler,      /* COMP0 interrupt handler   */
        COMP1_IRQHandler,      /* COMP1 interrupt handler   */
        TRNG_IRQHandler,       /* TRNG interrupt handler    */
        AESADV_IRQHandler,     /* AESADV interrupt handler  */
        LFSS_IRQHandler,       /* LFSS interrupt handler    */
        DMA0_IRQHandler,       /* DMA0 interrupt handler    */
        DMA1_IRQHandler,       /* DMA1 interrupt handler    */
        I2S0_IRQHandler,       /* I2S0 interrupt handler    */
        I2S1_IRQHandler,       /* I2S1 interrupt handler    */
        QSPI_IRQHandler,       /* QSPI interrupt handler    */
        SHAW_IRQHandler,       /* SHAW interrupt handler    */
        PKA_IRQHandler,        /* PKA interrupt handler     */
        UC13_1_IRQHandler,     /* UC13_1 interrupt handler  */
        UC13_2_IRQHandler,     /* UC13_2 interrupt handler  */
        UC13_3_IRQHandler,     /* UC13_3 interrupt handler  */

    };
#pragma ghs section rodata=default

/* 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.  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.                                                                */
void Reset_Handler(void)
{
    unsigned char *dst;
    unsigned char *end;

    /*
     * Step 1: Clear BSS section to zero
     * BSS contains uninitialized global and static variables
     */
    dst = __ghsbegin_bss;
    end = __ghsend_bss;
    while (dst < end) {
        *dst++ = 0;
    }

    /*
     * Step 2: Call main()
     * The application entry point
     *
     * Note: For this embedded application, initialized data (.data section)
     * is handled by the linker placing it directly in RAM or the debugger
     * loading it. If ROM-to-RAM copy is needed, add ROMCOPY directive to
     * linker script and use __ghscopy_data symbol.
     */
    (void)main();

    /*
     * Step 3: Loop forever if main() returns
     * In embedded systems, main() should never return
     */
    while (1) {
        /* Infinite loop */
    }
}

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