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

  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.

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

/* StartUp()              - Executed whenever CCS is invoked         */
/* OnReset()              - Executed after Debug->Reset CPU          */
/* OnRestart()            - Executed after Debug->Restart            */
/* OnPreFileLoaded()      - Executed before File->Load Program       */
/* OnFileLoaded()         - Executed after File->Load Program        */
/* OnTargetConnect()      - Executed after Debug->Connect            */

menuitem "MSPM0L1117_Commands"

/* initialize CCS debugger memory map                                */
memorymap_init()
{
    /*
     * Syntax for GEL_MapAddStr.
     * GEL_MapAddStr(address, page, length, "attribute", waitstate);

    Basic Attribute Types           Derived Attribute Types
    String      Description         String      Description
    R           Read                NONE        No memory/protected
    W           Write               RAM         Read and write
    P           Port                ROM         Read only
    EX          External            WOM         Write only
    EM          Emulator            INPORT      Port read only
    PR          Programmable        OUTPORT     Port write only
    ER          Erasable            IOPORT      Port read and write
    DA          Dual access         SARAM       Single access RAM
    ASn         Access size         DARAM       Dual access RAM
    SHnC        Shared              FLASH       Flash ROM
    CACHE       Cache               EXRAM       External RAM
    TX          Text                EXROM       External ROM
    MN          Monitor             EPROM       Erasable write-able EPROM
    SA          Single access       MONITOR     Monitor ROM
    FL          Flash               PRAM        Program RAM
    MR          Memory mapped       PROM        Program ROM
    NULL        NULL                NULL        NULL
    */

    GEL_MapAddStr(0x00000000, 0, 0x00020000, "R|AS4", 0);   /* FLASH_Main */
    GEL_MapAddStr(0x20000000, 0, 0x00004000, "R|W|AS4", 0); /* SRAM_Default */
    GEL_MapAddStr(0x20100000, 0, 0x00004000, "R|W|AS4", 0); /* SRAM_Parity_Checked */
    GEL_MapAddStr(0x20200000, 0, 0x00004000, "R|W|AS4", 0); /* SRAM_Unchecked */
    GEL_MapAddStr(0x20300000, 0, 0x00004000, "R|W|AS4", 0); /* SRAM_Parity_ECC_Code */
    GEL_MapAddStr(0x40004000, 0, 0x00002000, "R|W|AS4", 0); /* ADC0 */
    GEL_MapAddStr(0x40030000, 0, 0x00001F00, "R|W|AS4", 0); /* VREF */
    GEL_MapAddStr(0x40080000, 0, 0x00001500, "R|W|AS4", 0); /* WWDT0 */
    GEL_MapAddStr(0x40084000, 0, 0x00001F00, "R|W|AS4", 0); /* TIMG0 */
    GEL_MapAddStr(0x40086000, 0, 0x00001F00, "R|W|AS4", 0); /* TIMG1 */
    GEL_MapAddStr(0x40090000, 0, 0x00001F00, "R|W|AS4", 0); /* TIMG8 */
    GEL_MapAddStr(0x40094000, 0, 0x00001600, "R|W|AS4", 0); /* LFSS */
    GEL_MapAddStr(0x400A0000, 0, 0x00001F00, "R|W|AS4", 0); /* GPIOA */
    GEL_MapAddStr(0x400A2000, 0, 0x00001F00, "R|W|AS4", 0); /* GPIOB */
    GEL_MapAddStr(0x400AC000, 0, 0x00002000, "R|W|AS4", 0); /* KEYSTORECTL */
    GEL_MapAddStr(0x400AF000, 0, 0x00003100, "R|W|AS4", 0); /* SYSCTL */
    GEL_MapAddStr(0x400C7000, 0, 0x00001F00, "R|W|AS4", 0); /* DEBUGSS */
    GEL_MapAddStr(0x400CD000, 0, 0x00002000, "R|W|AS4", 0); /* FLASHCTL */
    GEL_MapAddStr(0x400F0000, 0, 0x00001F00, "R|W|AS4", 0); /* I2C0 */
    GEL_MapAddStr(0x40100000, 0, 0x00001F00, "R|W|AS4", 0); /* UART1 */
    GEL_MapAddStr(0x40108000, 0, 0x00001F00, "R|W|AS4", 0); /* UART0 */
    GEL_MapAddStr(0x40400000, 0, 0x00001F00, "R|W|AS4", 0); /* CPUSS */
    GEL_MapAddStr(0x40424000, 0, 0x00000500, "R|W|AS4", 0); /* WUC */
    GEL_MapAddStr(0x40428000, 0, 0x00002000, "R|W|AS4", 0); /* IOMUX */
    GEL_MapAddStr(0x4042A000, 0, 0x00001F00, "R|W|AS4", 0); /* DMA */
    GEL_MapAddStr(0x40440000, 0, 0x00002000, "R|W|AS4", 0); /* CRCP0 */
    GEL_MapAddStr(0x40442000, 0, 0x00001200, "R|W|AS4", 0); /* AESADV */
    GEL_MapAddStr(0x40444000, 0, 0x00001E00, "R|W|AS4", 0); /* TRNG */
    GEL_MapAddStr(0x40468000, 0, 0x00001F00, "R|W|AS4", 0); /* SPI0 */
    GEL_MapAddStr(0x4055A000, 0, 0x00001000, "R|W|AS4", 0); /* ADC0_PERIPHERALREGIONSVT */
    GEL_MapAddStr(0x40860000, 0, 0x00001F00, "R|W|AS4", 0); /* TIMA0 */
    GEL_MapAddStr(0x41C00000, 0, 0x00000800, "R|AS4", 0);   /* FLASH_NonMain */
    GEL_MapAddStr(0x41C40000, 0, 0x00000200, "R|AS4", 0);   /* FLASH_Factory */

    /* ARM standard IPs */
    GEL_MapAddStr(0xE0000000, 0, 0x00001000, "R|W|AS4", 0);       /* itm */
    GEL_MapAddStr(0xE0001000, 0, 0x00001000, "R|W|AS4", 0);       /* dwt */
    GEL_MapAddStr(0xE0002000, 0, 0x00001000, "R|W|AS4", 0);       /* fpb */
    GEL_MapAddStr(0xE000EDF0, 0, 0x00000018, "R|W|AS4", 0);       /* dcb */
    GEL_MapAddStr(0xE0040000, 0, 0x00001000, "R|W|AS4", 0);       /* tpiu */
    GEL_MapAddStr(0xE0041004, 0, 0x00001000, "R|W|AS4", 0);       /* etm */
    GEL_MapAddStr(0xE0042000, 0, 0x00001000, "R|W|AS4", 0);       /* cti */
    GEL_MapAddStr(0xE0043000, 0, 0x00001000, "R|W|AS4", 0);       /* mtb */
    GEL_MapAddStr(0xE000E004, 0, 0x00000008, "R|W|AS4", 0);       /* icb */
    GEL_MapAddStr(0xE000E010, 0, 0x0000000C, "R|W|AS4", 0);       /* systick */
    GEL_MapAddStr(0xE000E100, 0, 0x00000444, "R|W|AS4", 0);       /* nvic */
    GEL_MapAddStr(0xE000ED00, 0, 0x00000014, "R|W|AS4", 0);       /* cpuidbr, icsr, vtor, aircr, scr */
    GEL_MapAddStr(0xE000ED90, 0, 0x00000034, "R|W|AS4", 0);       /* mpu */
    GEL_MapAddStr(0xE000EDD0, 0, 0x00000018, "R|W|AS4", 0);       /* sau */
    GEL_MapAddStr(0xE000EF00, 0, 0x00000004, "R|W|AS4", 0);       /* sig */
    GEL_MapAddStr(0xE000EF34, 0, 0x00000018, "R|W|AS4", 0);       /* fpu */

    GEL_TextOut("Memory Map Initialization Complete\n");
}

// Global variables to store device id and HW revision
unsigned int gGEL_DeviceID = 0;

int gGEL_Reset_Done;
int gGEL_ResetCalled = 0;
int gGEL_RemoteCmd_Done;

/*
 * Called during startup of device
 *  Sets a handler to force external reset if an error is detected
 */
StartUp(major, minor, revision, build)
{
    GEL_HandleTargetError( 
        ".*-613.*",
        "\nConnection to MSPM0 core failed.\n
Possible root causes:
1) Debug access within NONMAIN was disabled or enabled with password.\n2) Peripheral mis-configuration (e.g improper watchdog or clock).\n
To see a more detailed diagnostic of the issue, please press the 'Read boot diagnostic' button.",
        1,
        "Read boot diagnostic",
        "MSPM0_BootDiag_DebugRead()"
    );
    
    GEL_HandleTargetError(
        ".*-6305.*",
        "\nConnection to MSPM0 core failed.\n
Possible root causes:
1) Debug access within NONMAIN was disabled or enabled with password.\n2) Peripheral mis-configuration (e.g improper watchdog or clock).\n
To see a more detailed diagnostic of the issue, please press the 'Read boot diagnostic' button.",
        1,
        "Read boot diagnostic",
        "MSPM0_BootDiag_DebugRead()"
    );

    GEL_HandleTargetError(
        ".*-614.*",
        "\nConnection to MSPM0 core failed.\n
Possible root causes:
1) Debug access within NONMAIN was disabled or enabled with password.\n2) Peripheral mis-configuration (e.g improper watchdog or clock).\n
To see a more detailed diagnostic of the issue, please press the 'Read boot diagnostic' button.",
        1,
        "Read boot diagnostic",
        "MSPM0_BootDiag_DebugRead()"
    );

    GEL_HandleTargetError( ".*-2062.*", "\nDevice Connection Error.
This could be caused by the device having gone to low power mode.
Try forcing an external reset pressing the 'Force Reset' button.
If the error persists, try:
    1) Invoking BSL,
    2) Calling a DSSM Mass erase, or,
    3) Calling a DSSM Factory Reset.
Check device FAQs for more information.",
1, "Force Reset", "GEL_MSPM0_Board_Reset()" );
}

/*
 * Starts a board reset from the device
 *  It will call a function from CS_DAP to trigger the reset.
 *  Function won't return until reset is done.
 */
GEL_MSPM0_Board_Reset()
{
    if ('GEL'::gGEL_ResetCalled == 0)
    {
        'GEL'::gGEL_ResetCalled = 1;
        'GEL'::gGEL_Reset_Done = 0;
        GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remotePORReset()", 0 );
        while(!'GEL'::gGEL_Reset_Done)
            ;
        'GEL'::gGEL_ResetCalled = 0;
    }
}

/*
 * Returns true, if the device id reflects a MSPM0L111X variant
 */
GEL_isMSPM0L111X()
{
  int result = 0;
  if (
      ((gGEL_DeviceID&0xFFFFFFE) == 0x0BBB402E)
     )
  {
    result = 1;
  }
  return result;
}

/*
 * Returns true, if the device version is preliminary silicon
 */
GEL_isMSPM0Rev0()
{
    int result = 0;
    if ( (gGEL_DeviceID&0xF0000000) == 0x00000000 )
    {
        result = 1;
    }
    return result;
}

/*
 * Called after the parent router is connected, but before the target is connected.
 */
OnPreTargetConnect()
{
    if (GEL_MatchesConnection(".*XDS.*")) {
        if (GEL_GetBoolDebugProperty("EnableWaitForDebug") == 1) {
            MSPM0_ResetCtl_WaitForDebug();
            GEL_EvalOnTarget("CS_DAP_0", "PWRAP_DPREC0 = 0x00120008", 0);
        }
    }
}

OnFileLoaded()
{

}

/*
 * Called every time a target is connected.
 *  Validates the device ID and initializes the memory map.
 */
OnTargetConnect()
{
    GEL_MapReset();
    memorymap_init();
    GEL_MapOn();

    gGEL_DeviceID   = *(unsigned int *)(0x41C40004);

    if (!GEL_isMSPM0L111X())
    {
        if (GEL_Dialog("The connected device is not MSPM0L111x.\nContinue?" , "QUESTION" , 0, "OK", "Cancel") != 0)
        {
            GEL_Disconnect();
            return;
        }
    }
}

OnPreFileLoaded()
{
    if (GEL_MatchesConnection(".*XDS.*")) {
        if (GEL_GetBoolDebugProperty("EnableWaitForDebug") == 1) {
            MSPM0_ResetCtl_WaitForDebug();
            GEL_EvalOnTarget("CS_DAP_0", "PWRAP_DPREC0 = 0x00120008", 0);
            GEL_Halt();
        }
    }
}

/*
 * GEL callback function called when the program is restarted.
 */
OnRestart()
{
    if (GEL_MatchesConnection(".*XDS.*")) {
        GEL_Halt();
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_DPREC0 = PWRAP_DPREC0 | 0x00020000", 0);
        GEL_AdvancedReset("System Reset", 1);
    }
}

OnReset()
{
    if (GEL_MatchesConnection(".*XDS.*")) {
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_DPREC0 = PWRAP_DPREC0 | 0x00020000", 0);
    }
}

hotmenu MSPM0_MailboxMassErase_Manual()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remoteMassErase(0)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Mass Erase executed. Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_MailboxMassErase_Auto()
{
    if(GEL_IsConnected() == 1)
    {
        GEL_Disconnect();
    }

    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remoteMassErase(1)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Mass Erase executed. Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_Mailbox_FactoryReset_Manual()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remoteFactoryReset(0)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Factory Reset executed. Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_Mailbox_FactoryReset_Auto()
{
    if(GEL_IsConnected() == 1)
    {
        GEL_Disconnect();
    }
 
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remoteFactoryReset(1)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Factory Reset executed. Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_Mailbox_DebugAccessPasswordAuthentication_Auto()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remotePasswordAuth(1, 0)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut(" Password Authentication executed.\n");
    GEL_Connect();
}

hotmenu MSPM0_Mailbox_MassErasePasswordAuthentication_Auto()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remotePasswordAuth(1, 1)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Mass erase with password authentication executed.\n");
    GEL_TextOut("Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_Mailbox_FactoryResetPasswordAuthentication_Auto()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remotePasswordAuth(1, 2)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Factory reset with password authentication executed.\n");
    GEL_TextOut("Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_Mailbox_MassErasePasswordAuthentication_Manual()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remotePasswordAuth(0, 1)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Mass erase with password authentication executed.\n");
    GEL_TextOut("Please terminate debug session, power-cycle and restart debug session.\n");
}

hotmenu MSPM0_Mailbox_FactoryResetPasswordAuthentication_Manual()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remotePasswordAuth(0, 2)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Factory reset with password authentication executed.\n");
    GEL_TextOut("Please terminate debug session, power-cycle and restart debug session.\n");
}

MSPM0_ResetCtl_WaitForDebug()
{
    int loop = 10; //to ensure it catches

    do
    {
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_SPREC = PWRAP_SPREC | 0x00000001", 0);
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_DPREC0 = PWRAP_DPREC0 | 0x00004000", 0);
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_SPREC = PWRAP_SPREC | 0x00000001", 0);
        loop--;
    }while(loop != 0);

    loop = 10000; //inserting artificial delay to ensure device his able to reinit before connect

    do
    {
        loop--;
    }while(loop != 0);

    return;
}

hotmenu MSPM0_Mailbox_WaitForDebug_Auto()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remoteWaitForDebug(1)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Device is now in reset mode.\n");
}

hotmenu MSPM0_Mailbox_WaitForDebug_Manual()
{
    'GEL'::gGEL_RemoteCmd_Done = 0;
    GEL_EvalOnTarget( "CS_DAP_0", "GEL_DAPInit_remoteWaitForDebug(0)", 0 );
    while(!'GEL'::gGEL_RemoteCmd_Done)
        ;
    GEL_TextOut("Device is now in reset mode.\n");
}

hotmenu MSPM0_ResetCtl_WaitForDebug_NoNRST()
{
    //WFD alternative if user does not have nRST connected
    int loop = 10; //to ensure it catches

    if(GEL_EvalOnTarget("CS_DAP_0", "GEL_IsConnected()", 1) == 0)
    {
        GEL_EvalOnTarget("CS_DAP_0", "GEL_Connect()", 1);
    }

    do
    {
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_SPREC = PWRAP_SPREC | 0x00000001", 0);
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_DPREC0 = PWRAP_DPREC0 | 0x00004000", 0);
        GEL_EvalOnTarget("CS_DAP_0", "PWRAP_SPREC = PWRAP_SPREC | 0x00000001", 0);
        loop--;
    }while(loop != 0);

    loop = 10000; //inserting artificial delay to ensure device his able to reinit before connect

    do
    {
        loop--;
    }while(loop != 0);

    GEL_TextOut("Device is now in the reset handler.\n");
}

hotmenu MSPM0_DeviceDiagnosticRead()
{
    /* General version*/
    GEL_EvalOnTarget("CS_DAP_0", "MSPM0_BootDiag_Read()", 0);
}

MSPM0_BootDiag_DebugRead()
{
    /* Debug version*/
    GEL_EvalOnTarget("CS_DAP_0", "MSPM0_BootDiag_DebugRead()", 1);
}

GEL_CLI_ListCommands()
{
    GEL_TextOut("\n-------------------------------------------------
 COMMAND                            DESCRIPTION
 ManualMassErase                    Manual Mass Erase
 AutomaticMassErase                 Automatic Mass Erase
 ManualMassEraseWithPassword        Manual Mass Erase with Password
 AutomaticMassEraseWithPassword     Automatic Mass Erase with Password
 ManualFactoryReset                 Manual Factory Reset
 AutomaticFactoryReset              Automatic Factory Reset
 ManualFactoryResetWithPassword     Manual Factory Reset with Password
 AutomaticFactoryResetWithPassword  Automatic Factory Reset with Password
-------------------------------------------------\n");
}

GEL_CLI_ManualMassErase()
{
    GEL_TextOut("Executing Manual Mass Erase...\n");
    MSPM0_MailboxMassErase_Manual();
}

GEL_CLI_AutomaticMassErase()
{
    GEL_TextOut("Executing Automatic Mass Erase...\n");
    MSPM0_MailboxMassErase_Auto();
}

GEL_CLI_ManualMassEraseWithPassword()
{
    GEL_TextOut("Executing Manual Mass Erase with Password...\n");
    MSPM0_Mailbox_MassErasePasswordAuthentication_Manual();
}

GEL_CLI_AutomaticMassEraseWithPassword()
{
    GEL_TextOut("Executing Automatic Mass Erase with Password...\n");
    MSPM0_Mailbox_MassErasePasswordAuthentication_Auto();
}

GEL_CLI_ManualFactoryReset()
{
    GEL_TextOut("Executing Manual Factory Reset...\n");
    MSPM0_Mailbox_FactoryReset_Manual();
}

GEL_CLI_AutomaticFactoryReset()
{
    GEL_TextOut("Executing Automatic Factory Reset...\n");
    MSPM0_Mailbox_FactoryReset_Auto();
}

GEL_CLI_ManualFactoryResetWithPassword()
{
    GEL_TextOut("Executing Manual Factory Reset with Password...\n");
    MSPM0_Mailbox_FactoryResetPasswordAuthentication_Manual();
}

GEL_CLI_AutomaticFactoryResetWithPassword()
{
    GEL_TextOut("Executing Automatic Factory Reset with Password...\n");
    MSPM0_Mailbox_FactoryResetPasswordAuthentication_Auto();
}
