This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432E401Y: problems completing ethernet bootloader routine

Part Number: MSP432E401Y
Other Parts Discussed in Thread: UNIFLASH

I'm still struggling with the EMAC bootloader functions on the MSP432E4.

I've now been successful in loading a custom firmware onto the device via emac bootloader.   I can then even trigger another update request through receipt of the magic packet, and have the board initialize a tftp read request.   However this is where things go sideways.

The board will then pull in the file but then bricks itself and can only be recovered by perfoming a mass erase to reprogram.   I'm not really sure what may be causing the issue and am now at a loss.  

Here is the software update task function that monitors for a successful receipt of magicpacket on UDP port 9.  The getFirmwareUpdateSatus() function just returns a boolean value that is set by a monitor thread that checks for the magic packet.   This all works, but I put it here as maybe there is something amiss with the sysClock variable.  

void *_swUpdate(xdc_UArg sysClock)
{
    uint32_t m_sysClock = (uint32_t)sysClock;
    /* If the firmware request is not issued by the Host then blink the LED D1
     * On switch firmware request detect exit the blinking program and jump to
     * the flash boot loader. */
    GPIO_write(Board_GPIO_LED0, 1);
    while (!getFirmwareUpdateSatus())
//    while(1)
    {
        GPIO_toggle(Board_GPIO_LED0);
        Task_sleep(500);
    }

    /* Before passing control make sure that the LED is turned OFF. */
    GPIO_write(Board_GPIO_LED0, 0);
    Display_printf(display, 0, 0, "received MP, sysClock = %u\n",m_sysClock);
//    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0x0);

    /* Pass control to whichever flavour of boot loader the board is configured
     * with. */
    SoftwareUpdateBegin(m_sysClock);

    /* The previous function never returns but we need to stick in a return
     * code here to keep the compiler from generating a warning. */
    return (0);
}

sysClock is passed as a Task argument and derived in the main function routine.   Here is main so you can see where the systemClock is derived.

int main(void)
{
    Task_Params params;
    uint32_t getSystemClock;

    /* Run from the PLL at 120 MHz. */
    getSystemClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    SYSCTL_OSC_MAIN |
    SYSCTL_USE_PLL |
    SYSCTL_CFG_VCO_480),
                                            120000000);

    sem_init(&fwStatusSem, 0, 0);
    sem_post(&fwStatusSem);

    /* Call driver init functions */
    Board_init();

    GPIO_init();

    Display_init();

    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while(1);
    }
//*
    Task_Params_init(&params);
    params.instance->name = "_swUpdate";
    params.priority = 3;
    params.stackSize = 2048;
    params.arg0 = (xdc_UArg)getSystemClock;

    swUpdateThread = Task_create((Task_FuncPtr)_swUpdate, &params, NULL);

    if (!swUpdateThread) {
        // Error: could not create NDK stack thread
        while(1);
    }
//*/
    ti_ndk_config_Global_startupFxn();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

Finally, the SoftwareUpdateBegin begin function disables the interrupts, kills the outstanding tasks, and disables the sysTick interrupts before calling the ROM_updaeEMAC function

void SoftwareUpdateBegin(uint32_t ui32SysClock)
{
    //
    // Disable all processor interrupts.  Instead of disabling them
    // one at a time (and possibly missing an interrupt if new sources
    // are added), a direct write to NVIC is done to disable all
    // peripheral interrupts.
    //
    Display_printf(display, 0, 0, "preparing update, sysClock = %u\n",ui32SysClock);
    Task_delete(&swUpdateThread);
    Task_delete(&ndkThread);


    NVIC->ICER[0] = 0xffffffff;
    NVIC->ICER[1] = 0xffffffff;
    NVIC->ICER[2] = 0xffffffff;
    NVIC->ICER[3] = 0xffffffff;

    //
    // Also disable the SysTick interrupt.
    //
    SysTickIntDisable();
    SysTickDisable();

    //
    // Return control to the boot loader.  This is a call to the SVC
    // handler in the flashed-based boot loader, or to the ROM if configured.
    //
#if ((defined ROM_UpdateEMAC) && !(defined USE_FLASH_BOOT_LOADER))
    ROM_UpdateEMAC(ui32SysClock);
#else
    (*((void (*)(void))(*(uint32_t *)0x2c)))();
#endif
}

in case it is helpful I've also included my linker cmd file, the resultant .map, and the system_msp432e401y.c and startup_msp432e401y_ccs.c files.  The last two I pulled straight from the boot_emac_flash_app_magicpacket_update_MSP_EXP432E401Y_nortos_ccs example project without changes, so maybe there is something in there that is an issue.

Thanks for any help you can provide.

Patrick

/******************************************************************************
*
* Copyright (C) 2017 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 "Board.h"
#include <ti/devices/msp432e4/inc/msp.h>

/*----------------------------------------------------------------------------
  Define clocks
 *----------------------------------------------------------------------------*/
#define __SYSTEM_CLOCK    (16000000ul)

/* Update frequency to match the crystal frequency on your board */
#define XTAL_FREQ         (25000000ul)

/*----------------------------------------------------------------------------
  Clock Variable definitions
 *----------------------------------------------------------------------------*/
uint32_t SystemCoreClock = __SYSTEM_CLOCK; /*!< System Clock Frequency (Core Clock)*/


/*----------------------------------------------------------------------------
  Clock functions
 *----------------------------------------------------------------------------*/
void SystemCoreClockUpdate (void)            /* Get Core Clock Frequency      */
{
    uint32_t getClockDivider;
    uint32_t getPLLMIntValue;
    uint32_t getPLLNValue;
    uint32_t getPLLQValue;

    /* Update the default System Clock value for MSP432E4x devices */
    SystemCoreClock = __SYSTEM_CLOCK;

    if((SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_USEPLL) == SYSCTL_RSCLKCFG_USEPLL)
    {
        getClockDivider = (SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_PSYSDIV_M) >> SYSCTL_RSCLKCFG_PSYSDIV_S;

        getPLLMIntValue = (SYSCTL->PLLFREQ0 & SYSCTL_PLLFREQ0_MINT_M) >> SYSCTL_PLLFREQ0_MINT_S;
        getPLLNValue = (SYSCTL->PLLFREQ1 & SYSCTL_PLLFREQ1_N_M) >> SYSCTL_PLLFREQ1_N_S;
        getPLLQValue = (SYSCTL->PLLFREQ1 & SYSCTL_PLLFREQ1_Q_M) >> SYSCTL_PLLFREQ1_Q_S;

        if((SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_PLLSRC_M) == SYSCTL_RSCLKCFG_PLLSRC_PIOSC)
        {
            SystemCoreClock = (__SYSTEM_CLOCK * (getPLLMIntValue)) / ((getPLLNValue + 1) * (getPLLQValue + 1));
            SystemCoreClock = SystemCoreClock / (getClockDivider + 1);
        }
        else if((SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_PLLSRC_M) == SYSCTL_RSCLKCFG_PLLSRC_MOSC)
        {
            SystemCoreClock = (XTAL_FREQ * (getPLLMIntValue)) / ((getPLLNValue + 1) * (getPLLQValue + 1));
            SystemCoreClock = SystemCoreClock / (getClockDivider + 1);
        }
    }
    else
    {
        getClockDivider = (SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_OSYSDIV_M) >> SYSCTL_RSCLKCFG_OSYSDIV_S;

        if((SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_OSCSRC_M) == SYSCTL_RSCLKCFG_OSCSRC_PIOSC)
        {
            SystemCoreClock = __SYSTEM_CLOCK / (getClockDivider + 1);
        }
        else if((SYSCTL->RSCLKCFG & SYSCTL_RSCLKCFG_OSCSRC_M) == SYSCTL_RSCLKCFG_OSCSRC_MOSC)
        {
            SystemCoreClock = XTAL_FREQ / (getClockDivider + 1);
        }
    }
}

/**
 * Initialize the system
 *
 * @param  none
 * @return none
 *
 * @brief  Setup the microcontroller system.
 *         Initialize the System.
 */
void SystemInit (void)
{
  #if (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2) |                 /* set CP10 Full Access */
                   (3UL << 11*2)  );               /* set CP11 Full Access */
  #endif

#ifdef UNALIGNED_SUPPORT_DISABLE
  SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
#endif

  SystemCoreClock = __SYSTEM_CLOCK;

}

/******************************************************************************
*
* Copyright (C) 2017 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>


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

/* External declaration for system initialization function                  */
extern void SystemInit(void);

/* Linker variable that marks the top of the stack. */
extern uint32_t __STACK_TOP;

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

/* Cortex-M4 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 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 handler */
extern void GPIOA_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOB_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOC_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOD_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOE_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART0_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART1_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void SSI0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void PWM0_FAULT_IRQHandler   (void) __attribute__((weak, alias("Default_Handler")));
extern void PWM0_0_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void PWM0_1_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void PWM0_2_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void QEI0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC0SS0_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC0SS1_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC0SS2_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC0SS3_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void WATCHDOG_IRQHandler     (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER0A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER0B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER1A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER1B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER2A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER2B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void COMP0_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void COMP1_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void COMP2_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void SYSCTL_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void FLASH_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOF_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOG_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOH_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART2_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void SSI1_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER3A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER3B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C1_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void CAN0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void CAN1_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void EMAC0_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void HIBERNATE_IRQHandler    (void) __attribute__((weak, alias("Default_Handler")));
extern void USB0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void PWM0_3_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void UDMA_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void UDMAERR_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC1SS0_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC1SS1_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC1SS2_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void ADC1SS3_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void EPI0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOJ_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOK_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOL_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void SSI2_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void SSI3_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void UART3_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART4_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART5_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART6_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void UART7_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C2_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C3_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER4A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER4B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER5A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER5B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void SYSEXC_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C4_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C5_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOM_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void GPION_IRQHandler        (void) __attribute__((weak, alias("Default_Handler")));
extern void TAMPER0_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP0_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP1_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP2_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP3_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP4_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP5_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP6_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOP7_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ0_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ1_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ2_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ3_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ4_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ5_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ6_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void GPIOQ7_IRQHandler       (void) __attribute__((weak, alias("Default_Handler")));
extern void SHA0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void AES0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void DES0_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER6A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER6B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER7A_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void TIMER7B_IRQHandler      (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C6_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C7_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C8_IRQHandler         (void) __attribute__((weak, alias("Default_Handler")));
extern void I2C9_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.                            */
#pragma RETAIN(interruptVectors)
#pragma DATA_SECTION(interruptVectors, ".intvecs")
void (* const interruptVectors[])(void) =
{
    (void (*)(void))((uint32_t)&__STACK_TOP),
                                            /* The initial stack pointer */
    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   */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    SVC_Handler,                            /* SVCall handler            */
    DebugMon_Handler,                       /* Debug monitor handler     */
    0,                                      /* Reserved                  */
    PendSV_Handler,                         /* The PendSV handler        */
    SysTick_Handler,                        /* The SysTick handler       */
    GPIOA_IRQHandler,                       /* GPIO Port A               */
    GPIOB_IRQHandler,                       /* GPIO Port B               */
    GPIOC_IRQHandler,                       /* GPIO Port C               */
    GPIOD_IRQHandler,                       /* GPIO Port D               */
    GPIOE_IRQHandler,                       /* GPIO Port E               */
    UART0_IRQHandler,                       /* UART0 Rx and Tx           */
    UART1_IRQHandler,                       /* UART1 Rx and Tx           */
    SSI0_IRQHandler,                        /* SSI0 Rx and Tx            */
    I2C0_IRQHandler,                        /* I2C0 Master and Slave     */
    PWM0_FAULT_IRQHandler,                  /* PWM Fault                 */
    PWM0_0_IRQHandler,                      /* PWM Generator 0           */
    PWM0_1_IRQHandler,                      /* PWM Generator 1           */
    PWM0_2_IRQHandler,                      /* PWM Generator 2           */
    QEI0_IRQHandler,                        /* Quadrature Encoder 0      */
    ADC0SS0_IRQHandler,                     /* ADC Sequence 0            */
    ADC0SS1_IRQHandler,                     /* ADC Sequence 1            */
    ADC0SS2_IRQHandler,                     /* ADC Sequence 2            */
    ADC0SS3_IRQHandler,                     /* ADC Sequence 3            */
    WATCHDOG_IRQHandler,                    /* Watchdog timer            */
    TIMER0A_IRQHandler,                     /* Timer 0 subtimer A        */
    TIMER0B_IRQHandler,                     /* Timer 0 subtimer B        */
    TIMER1A_IRQHandler,                     /* Timer 1 subtimer A        */
    TIMER1B_IRQHandler,                     /* Timer 1 subtimer B        */
    TIMER2A_IRQHandler,                     /* Timer 2 subtimer A        */
    TIMER2B_IRQHandler,                     /* Timer 2 subtimer B        */
    COMP0_IRQHandler,                       /* Analog Comparator 0       */
    COMP1_IRQHandler,                       /* Analog Comparator 1       */
    COMP2_IRQHandler,                       /* Analog Comparator 2       */
    SYSCTL_IRQHandler,                      /* System Control            */
    FLASH_IRQHandler,                       /* FLASH Control             */
    GPIOF_IRQHandler,                       /* GPIO Port F               */
    GPIOG_IRQHandler,                       /* GPIO Port G               */
    GPIOH_IRQHandler,                       /* GPIO Port H               */
    UART2_IRQHandler,                       /* UART2 Rx and Tx           */
    SSI1_IRQHandler,                        /* SSI1 Rx and Tx            */
    TIMER3A_IRQHandler,                     /* Timer 3 subtimer A        */
    TIMER3B_IRQHandler,                     /* Timer 3 subtimer B        */
    I2C1_IRQHandler,                        /* I2C1 Master and Slave     */
    CAN0_IRQHandler,                        /* CAN0                      */
    CAN1_IRQHandler,                        /* CAN1                      */
    EMAC0_IRQHandler,                       /* Ethernet                  */
    HIBERNATE_IRQHandler,                   /* Hibernate                 */
    USB0_IRQHandler,                        /* USB0                      */
    PWM0_3_IRQHandler,                      /* PWM Generator 3           */
    UDMA_IRQHandler,                        /* uDMA Software Transfer    */
    UDMAERR_IRQHandler,                     /* uDMA Error                */
    ADC1SS0_IRQHandler,                     /* ADC1 Sequence 0           */
    ADC1SS1_IRQHandler,                     /* ADC1 Sequence 1           */
    ADC1SS2_IRQHandler,                     /* ADC1 Sequence 2           */
    ADC1SS3_IRQHandler,                     /* ADC1 Sequence 3           */
    EPI0_IRQHandler,                        /* External Bus Interface 0  */
    GPIOJ_IRQHandler,                       /* GPIO Port J               */
    GPIOK_IRQHandler,                       /* GPIO Port K               */
    GPIOL_IRQHandler,                       /* GPIO Port L               */
    SSI2_IRQHandler,                        /* SSI2 Rx and Tx            */
    SSI3_IRQHandler,                        /* SSI3 Rx and Tx            */
    UART3_IRQHandler,                       /* UART3 Rx and Tx           */
    UART4_IRQHandler,                       /* UART4 Rx and Tx           */
    UART5_IRQHandler,                       /* UART5 Rx and Tx           */
    UART6_IRQHandler,                       /* UART6 Rx and Tx           */
    UART7_IRQHandler,                       /* UART7 Rx and Tx           */
    I2C2_IRQHandler,                        /* I2C2 Master and Slave     */
    I2C3_IRQHandler,                        /* I2C3 Master and Slave     */
    TIMER4A_IRQHandler,                     /* Timer 4 subtimer A        */
    TIMER4B_IRQHandler,                     /* Timer 4 subtimer B        */
    TIMER5A_IRQHandler,                     /* Timer 5 subtimer A        */
    TIMER5B_IRQHandler,                     /* Timer 5 subtimer B        */
    SYSEXC_IRQHandler,                      /* FPU                       */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    I2C4_IRQHandler,                        /* I2C4 Master and Slave     */
    I2C5_IRQHandler,                        /* I2C5 Master and Slave     */
    GPIOM_IRQHandler,                       /* GPIO Port M               */
    GPION_IRQHandler,                       /* GPIO Port N               */
    0,                                      /* Reserved                  */
    TAMPER0_IRQHandler,                     /* Tamper                    */
    GPIOP0_IRQHandler,                      /* GPIO Port P(Summary or P0)*/
    GPIOP1_IRQHandler,                      /* GPIO Port P1              */
    GPIOP2_IRQHandler,                      /* GPIO Port P2              */
    GPIOP3_IRQHandler,                      /* GPIO Port P3              */
    GPIOP4_IRQHandler,                      /* GPIO Port P4              */
    GPIOP5_IRQHandler,                      /* GPIO Port P5              */
    GPIOP6_IRQHandler,                      /* GPIO Port P6              */
    GPIOP7_IRQHandler,                      /* GPIO Port P7              */
    GPIOQ0_IRQHandler,                      /* GPIO Port Q(Summary or Q0)*/
    GPIOQ1_IRQHandler,                      /* GPIO Port Q1              */
    GPIOQ2_IRQHandler,                      /* GPIO Port Q2              */
    GPIOQ3_IRQHandler,                      /* GPIO Port Q3              */
    GPIOQ4_IRQHandler,                      /* GPIO Port Q4              */
    GPIOQ5_IRQHandler,                      /* GPIO Port Q5              */
    GPIOQ6_IRQHandler,                      /* GPIO Port Q6              */
    GPIOQ7_IRQHandler,                      /* GPIO Port Q7              */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    SHA0_IRQHandler,                        /* SHA/MD5 0                 */
    AES0_IRQHandler,                        /* AES 0                     */
    DES0_IRQHandler,                        /* DES3DES 0                 */
    0,                                      /* Reserved                  */
    TIMER6A_IRQHandler,                     /* Timer 6 subtimer A        */
    TIMER6B_IRQHandler,                     /* Timer 6 subtimer B        */
    TIMER7A_IRQHandler,                     /* Timer 7 subtimer A        */
    TIMER7B_IRQHandler,                     /* Timer 7 subtimer B        */
    I2C6_IRQHandler,                        /* I2C6 Master and Slave     */
    I2C7_IRQHandler,                        /* I2C7 Master and Slave     */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    I2C8_IRQHandler,                        /* I2C8 Master and Slave     */
    I2C9_IRQHandler,                        /* I2C9 Master and Slave     */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
    0,                                      /* Reserved                  */
};

/* 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.                                                                */
void Reset_Handler(void)
{
    SystemInit();

    /* Jump to the CCS C Initialization Routine. */
    __asm("    .global _c_int00\n"
          "    b.w     _c_int00");
}

/* 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)
{
    /* Fault trap exempt from ULP advisor */
    #pragma diag_push
    #pragma CHECK_ULP("-2.1")

	/* Enter an infinite loop. */
	while(1)
	{
	}

	#pragma diag_pop
}

udpecho_MSP_EXP432E401Y_tirtos_ccs_bootload.map.txt

I couldn't upload the .cmd file, so here it is:

/*
 *  ======== MSP_EXP432E401Y.cmd ========
 *  Define the memory block start/length for the MSP_EXP432E401Y M4
 */
--stack_size=1024   /* C stack is also used for ISR stack */
--retain=Vectors

#define APP_BASE 	0x00004000
#define FLASH_BASE	0x00005000

HEAPSIZE = 0x20000;  /* Size of heap buffer used by HeapMem */

MEMORY
{
	DEFAULT (RX) : origin = APP_BASE, length = 0x00001000
    FLASH (RX) : origin = FLASH_BASE, length = 0x000FC000
    SRAM (RWX) : origin = 0x20000000, length = 0x00040000
}

/* Section allocation in memory */

SECTIONS
{
	.intvecs:   > APP_BASE
//	.intvecs:   > FLASH
	.resetVecs	> FLASH_BASE
    .text   :   > FLASH
    .const  :   > FLASH
    .cinit  :   > FLASH
    .pinit  :   > FLASH
    .init_array : > FLASH

    .vtable :   > 0x20000000
    .TI.ramfunc : {} load=FLASH, run=SRAM, table(BINIT)
    .data   :   > SRAM
    .bss    :   > SRAM
    .sysmem :   > SRAM

    /* Heap buffer used by HeapMem */
    .priheap   : {
        __primary_heap_start__ = .;
        . += HEAPSIZE;
        __primary_heap_end__ = .;
    } > SRAM align 8

    .stack  :   > SRAM (HIGH)
}

__STACK_TOP = __stack + 512;

  • Looking at this further, it appears that the when I load the same image a second time, the memory map is completely different.   What in the bootloader routine might cause this?   

    The image is first loaded on top of the boot_emac_magicpacket example, and thus loads correctly.   The second time it is obviously done making calls to it's own program as specified above.   This appears to load the file incorrectly for some reason.

    Just for the heck of it, here are snapshots of the memory registers taken from uniflash showing the difference, they should be identical I would think.

    Here's the memory address reads of the good load, everything is working in the program

    And here is the memory read of the subsequent load where the MSP is now bricked.

  • Hey Patrick,

    I will look into this and get back to you shortly. Have you gone through the SimpleLink Academy's MSP432E4 Boot Loader lab?

    BR,

    Seong

  • Seong,

    thanks. I have gone through the SimpleLink Academy's bootloader lab.    My issue, I think, is that there are no examples which use an RTOS or rely on the NDK for UDP port connections which my software will.   I'm thinking that somehow that complicates the matter, though I'm not sure.

    Primarily, something in the manner in which I am performing the tftp transaction seems to be at issue.  My thoughts are that either some interrupt is triggering that I didn't disable properly, the TFTP transaction isn't being completely read, or it isn't being copied over properly, or there is an issue with memory allocation I'm not seeing.  

    It would be incredibly helpful if someone were to just prepare an example of a program that uses an RTOS and properly allows for bootloader functionality, whether via EMAC or some other peripheral.   

    Patrick

  • Hi Patrick,

    Quick update: This is still open an open issue that has been reported internally and our team is continuing to work on finding a solution. Please bare with us. 

    BR,

    Seong

  • Seong,

    thanks for the update.   I've discovered a work around, one that is less elegant but will work in the meantime.

    First, I reset the application memory space to start of the Flash space, 0x00000000, and removed any custom bootloader application that would normally be in that space.

    //#define APP_BASE 	0x00004000
    #define APP_BASE 	0x00000000
    
    HEAPSIZE = 0x20000;
    
    MEMORY
    {
    //    FLASH (RX) : origin = APP_BASE, length = 0x000FC000 FLASH (RX) : origin = APP_BASE, length = 0x00100000 SRAM (RWX) : origin = 0x20000000, length = 0x00040000 } /* Section allocation in memory */ SECTIONS { .intvecs: > APP_BASE .text : > FLASH .const : > FLASH .cinit : > FLASH .pinit : > FLASH .init_array : > FLASH .vtable : > 0x20000000 // .TI.ramfunc : {} load=FLASH, run=SRAM, table(BINIT) .data : > SRAM .bss : > SRAM .sysmem : > SRAM /* Heap buffer used by HeapMem */ .priheap : { __primary_heap_start__ = .; . += HEAPSIZE; __primary_heap_end__ = .; } > SRAM align 8 .stack : > SRAM (HIGH) }

    Then I use a routine to detect the magicpacket on UDP port 9.   Once detected and verified I launch a custom software update function that basically just clears memory block 0x00000004 from Flash and then resets the microcontroller

    void SoftwareUpdateBegin()
    {
        Display_printf(display, 0, 0, "closing network interfaces on NDK stack\n");
        NC_NetStop(-1);
        Task_sleep(500);
    
        // Disable all processor interrupts
        NVIC->ICER[0] = 0xffffffff;
        NVIC->ICER[1] = 0xffffffff;
        NVIC->ICER[2] = 0xffffffff;
        NVIC->ICER[3] = 0xffffffff;
    
        // disable the SysTick interrupt.
        SysTickIntDisable();
        SysTickDisable();
    
        // Attempt to ERASE BLOCK 0x00000004
        FLASH_CTRL->FMA = (0x00000004);
        FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
    
        // Wait until the flash has been erased.
        while(FLASH_CTRL->FMC & FLASH_FMC_ERASE) { }
    
        // reset the system
        SCB->AIRCR = NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ;
    
    }

    From here I need to send a new magicpacket request to kick off the native update routine and then the rest of the process kicks off as in the EMAC examples with receipt of the BOOTP request from the client and then servicing of the TFTP update packets.

    It isn't ideal since I'm forced to erase part of the flash, making the process non-recoverable if an error results, and I'm not able to customize the process in ways I'd like so I'll probably be interested in knowing if there is a solution to my earlier problem.  But for now I'm at least able to service the firmware without use of JTAG which is vital for our application and should still allow me to update the devices remotely if we do find a better solution.

    Patrick

**Attention** This is a public forum