SLAZ709A October   2017  – June 2025 MSP432E401Y , MSP432E411Y

 

  1.   1
  2. 1MSP432E4 SimpleLink™ Microcontrollers
    1. 1.1 Introduction
    2. 1.2 Device Nomenclature
    3. 1.3 Device Markings
    4. 1.4 Errata Overview
    5. 1.5 Errata Descriptions
      1.      ADC#13
      2.      ADC#14
      3.      EPI#01
      4.      GPIO#09
      5.      GPTM#09
      6.      GPTM#15
      7.      HIB#10
      8.      HIB#16
      9.      HIB#18
      10.      HIB#19
      11.      MEM#07
      12.      MEM#15
      13.      MEM#16
      14.      PWM#04
      15.      PWM#05
      16.      PWM#06
      17.      QEI#01
      18.      SSI#03
      19.      SSI#05
      20.      SSI#06
      21.      SSI#07
      22.      SSI#08
      23.      SYSCTL#03
      24.      SYSCTL#18
      25.      SYSCTL#24
      26.      USB#04
      27.      WDT#08
    6. 1.6 Appendix 1
    7. 1.7 Appendix 2
  3. 2Trademarks
  4. 3Revision History

Appendix 1

To address the erratum HIB#16 Application code may miss new tamper event during clear , the HibernateTamperEventsClear() API must be replaced with the following APIs:

HibernateTamperEventsClearNoLock();
HibernateTamperUnLock();
HibernateTamperLock();

The API definitions are as follows:

//*****************************************************************************
//
//! Clears the tamper feature events without Unlock and Lock.
//!
//! This function is used to clear all tamper events without unlock/locking
//! the tamper control registers, so API HibernateTamperUnLock() should be
//! called before this function, and API HibernateTamperLock() should be
//! called after to ensure that tamper control registers are locked.
//! 
//! This function doesn't block until the write is complete. 
//! Therefore, care must be taken to ensure the next immediate write will
//! occure only after the write complete bit is set.
//!
//! This function is used to implement a software workaround in NMI interrupt
//! handler to fix an issue when a new tamper event could be missed during
//! the clear of current tamper event.
//!
//! \note The hibernate tamper feature is not available on all 
//! devices.  Please consult the data sheet for the device that you
//! are using to determine if this feature is available.
//!
//! \return None.
//
//*****************************************************************************
void
HibernateTamperEventsClearNoLock(void)
{
    //
    // Wait for write completion.
    //
    _HibernateWriteComplete();
    // 
    //
    // Set the tamper event clear bit.
    //
    HWREG(HIB_TPCTL) |= HIB_TPCTL_TPCLR;
}
//*****************************************************************************
//
//! Unlock temper registers.
//!
//! This function is used to unlock the temper control registers.  This
//! function should be only used before calling API
//! HibernateTamperEventsClearNoLock().
//!
//! \note The hibernate tamper feature is not available on all
//! devices.  Please consult the data sheet for the device that you
//! are using to determine if this feature is available.
//!
//! \return None.
//
//*****************************************************************************
void
HibernateTamperUnLock(void)
{
    //
    // Unlock the tamper registers.
    //
    HWREG(HIB_LOCK) = HIB_LOCK_HIBLOCK_KEY;
    _HibernateWriteComplete();
}
//*****************************************************************************
//
//! Lock temper registers.
//!
//! This function is used to lock the temper control registers.  This
//! function should be used after calling API
//! HibernateTamperEventsClearNoLock().
//!
//! \note The hibernate tamper feature is not available on all 
//! devices.  Please consult the data sheet for the device that you
//! are using to determine if this feature is available.
//!
//! \return None.
//
//*****************************************************************************
void
HibernateTamperLock(void)
{
    //
    // Wait for write completion.
    //
    _HibernateWriteComplete();
    //
    // Lock the tamper registers.
    //
    HWREG(HIB_LOCK) = 0;
    _HibernateWriteComplete();
}

The software workaround must be added in the NMI Handler. The code mainly polls the tamper log entries during the tamper clear synchronization.

An example of an NMI handler with this workaround is shown below.

static uint32_t g_ui32RTCLog[4];
static uint32_t g_ui32EventLog[4];
//*****************************************************************************
//
// Handles an NMI interrupt generated by a Tamper event.
//
//*****************************************************************************
void
NMITamperEventHandler(void)
{
    uint32_t ui32NMIStatus, ui32TamperStatus;
    uint32_t pui32Buf[3];
    uint8_t ui8Idx, ui8StartIdx;
    bool     bDetectedEventsDuringClear;
    //
    // Get the cause of the NMI event.
    //
    ui32NMIStatus = SysCtlNMIStatus();
    //
    // We should have got the cause of the NMI event from the above function.
    // But in Snowflake RA0 the NMIC register is not set correctly when an
    // event occurs.  So as a work around check if the NMI event is caused by a
    // tamper event and append this to the return value from SysCtlNMIStatus().
    // This way only this section can be removed once the bug is fixed in next
    // silicon rev.
    //
    ui32TamperStatus = HibernateTamperStatusGet();
    if(ui32TamperStatus & (HIBERNATE_TAMPER_STATUS_EVENT |
                         HIBERNATE_TAMPER_STATUS_EXT_OSC_FAILED))
    {
        ui32NMIStatus |= SYSCTL_NMI_TAMPER;
    }
    //
    // Check if SysCtlNMIStatus() returned a valid value.
    //
    if(ui32NMIStatus)
    {
        //
        // Check if the NMI Interrupt is due to a Tamper event.
        //
        if(ui32NMIStatus & SYSCTL_NMI_TAMPER)
        {
            //
            // If the previous NMI event has not been processed by main
            // thread, we need to OR the new event along with the old ones.
            //
            if(g_ui32NMIEvent == 0)
            {
                //
                // Reset variables that used for tamper event.
                //
                g_ui32TamperEventFlag = 0;
                g_ui32TamperRTCLog = 0;
                //
                // Clean the log data for debugging purpose.
                //
                memset(g_ui32RTCLog, 0, (sizeof(g_ui32RTCLog))<<2);
                memset(g_ui32EventLog, 0, (sizeof(g_ui32EventLog))<<2);
            }
            //
            // Log the tamper event data before clearing tamper events.
            //
            for(ui8Idx = 0; ui8Idx< 4; ui8Idx++)
            {
                if(HibernateTamperEventsGet(ui8Idx,
                                            &g_ui32RTCLog[ui8Idx],
                                            &g_ui32EventLog[ui8Idx]))
                {
                    //
                    // Event in this log entry, store it.
                    // 
                    g_ui32TamperEventFlag |= g_ui32EventLog[ui8Idx];
                    g_ui32TamperRTCLog = g_ui32RTCLog[ui8Idx];
                }
                else
                {
                    //
                    // No event in this log entry. Done checking the logs.
                    //
                    break;
                }
            }
            //
            // Process external oscillator failed event.
            //
            if(ui32TamperStatus & HIBERNATE_TAMPER_STATUS_EXT_OSC_FAILED)
            {
                g_ui32TamperXOSCFailEvent++;
                g_ui32TamperEventFlag |= HIBERNATE_TAMPER_EVENT_EXT_OSC;
                g_ui32TamperRTCLog = HWREG(HIB_TPLOG0);
            }
Note:

This is the beginning of the block of workaround code.


            // The following block of code is to workaround hardware defect
            // which results in missing new tamper events during tamper clear
            // synchronization.
            // 
            // There is a window after the application code writes the tamper
            // clear where a new tamper event can be missed if the application
            // requires more than one tamper event pins detection.
            // 
            // The tamper Clear is synchronized to the hibernate 32kHz clock
            // domain.  The clear takes 3 rising edges of the 32KHz clock.
            // During this window, new tamper events could be missed.
            // A software workaround is to poll the tamper log during the
            // tamper event clear synchronization.
            // 
            //
            // Clear the flag for the case there are events triggered
            // during clear execution.
            //
            bDetectedEventsDuringClear = false;
            //
            // Unlock the Tamper Control register. This is required before
            // calling HibernateTamperEventsClearNoLock().
            // 
            HibernateTamperUnLock();
            do
            {
                //
                // We will start to poll the log registers at index 1 for
                // any new events.
                // 
                ui8StartIdx = 1;
                //
                // Clear the Tamper event.
                // Note this API doesn't wait for synchronization, which
                // allows us to check the tamper log during
                // synchronization.
                //
                HibernateTamperEventsClearNoLock();
                //
                // Check new tamper event during tamper event clear
                // synchronization.
                // This will take about 92us(three clock cycles) at most.
                //
                while(HibernateTamperStatusGet() & HIBERNATE_TAMPER_STATUS_EVENT)
                {
                    //
                    // Clear execution isn't done yet , poll for new events.
                    // If there were any new event, it will be logged in log 1
                    // registers and so on.
                    //
                    for(ui8Idx = ui8StartIdx; ui8Idx< 4; ui8Idx++)
                    {
                        if(HibernateTamperEventsGet(ui8Idx, 
                                                    &g_ui32RTCLog[ui8Idx],
                                                    &g_ui32EventLog[ui8Idx]))
                        {
                            //
                            // detected new event, store it.
                            //
                            g_ui32TamperEventFlag |= g_ui32EventLog[ui8Idx];
                            //
                            // check for more event.
                            //
                            continue;
                        }
                        else
                        {
                            //
                            // no new event in this log, update the log index
                            // to be checked next, and break out of loop.
                            //
                            ui8StartIdx = ui8Idx;
                            break;
                        }
                    }
                    //
                    // all last three logs have info. Check if all 4 logs
                    // have the same info. This is to detect the case that
                    // events happen during clear execution. 
                    // 
                    if(ui8Idx == 4)
                    {
                        //
                        // If events happens during clear
                        // execution, all four log registers will be
                        // logged with the same event, to detect this
                        // condition, we will compare with all four log data.
                        // 
                        if(HibernateTamperEventsGet(0, &g_ui32RTCLog[0], &g_ui32EventLog[0]))
                        {
                            if((g_ui32RTCLog[0] == g_ui32RTCLog[1])     &&
                               (g_ui32EventLog[0] == g_ui32EventLog[1]) &&
                              (g_ui32RTCLog[0] == g_ui32RTCLog[2])     &&
                               (g_ui32EventLog[0] == g_ui32EventLog[2]) &&
                               (g_ui32RTCLog[0] == g_ui32RTCLog[3])     &&
                               (g_ui32EventLog[0] == g_ui32EventLog[3]))
                            {
                                //
                                // Detected events during clear execution.
                                // Event logging takes priority, the clear
                                // will not be done in this case. We will need
                                // to go back to the beginning of the loop and
                                // clear the events.
                                //
                                if(bDetectedEventsDuringClear)
                                {
                                    //
                                    // This condition has already detected,
                                    // we have cleared the event,
                                    // clear the flag.
                                    // 
                                    bDetectedEventsDuringClear = false;
                                }
                                else
                                {
                                    // This is the first time it has been
                                    // detected, set the flag.
                                    //
                                    bDetectedEventsDuringClear = true;
                                }
                                //
                                // Break out of while loop so that we can
                                // clear the events, and start the
                                // workaround all over again.
                                //
                                break;
                            }
                        }
                        else
                        {
                            //
                            // Log 0 didn't detect any events. So this is not
                            // the case of missing events during clear
                            // execution.
                            // Update the log index at which we will poll next.
                            // It should be the last log entry that OR all the
                            // new events.
                            //
                            ui8StartIdx = 3;
                        }
                    }
                }
            }
            while(bDetectedEventsDuringClear);
            //
            // Lock the Tamper Control register.
            // 
            HibernateTamperLock();
Note:

This is the end of the block of workaround code.

            //
            // Save the tamper event and RTC log info in the Hibernate Memory
            //
            HibernateDataGet(pui32Buf, 3);
            pui32Buf[1] = g_ui32TamperEventFlag;
            pui32Buf[2] = g_ui32TamperRTCLog;
            HibernateDataSet(pui32Buf, 3);
            //
            // Signal the main loop that an NMI event occurred.
            //
            g_ui32NMIEvent++;
        }
        //
        // Clear NMI events
        //
        SysCtlNMIClear(ui32NMIStatus);
    }
}