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.

TM4C1294KCPDT: Microcontroller won't restart after a SysCtlReset()

Part Number: TM4C1294KCPDT

Tool/software:

Dear support,

Note: The datasheets I'm referring to below are 

  • TivaWare Peripheral Driver LIbrary User's Guide
  • Microcontroller Datasheet - TM4C1294KCPDT

I have integrated the microcontroller into my own hardware.

My issue is that sometimes (it feels at random) the microcontroller won't reboot after the lib function SysCtlReset() is called. The difficulty with this is that is not easy reproducible.
Since It doesn't happen all the time after the SysCtlReset(), let say it happens 1 out of 100 times
The only way to get out of this state is to completely power cycle it (or use the reset pin) to make the micro start again

Some extra info about my application

  • The application starts at address 0x4000 which is called by a bootloader (at address 0x0000)
  • It already happens when I just have 2 tasks running
  • It always happens at the same exact part of the code namely directly after the SysCtlReset()

To find the the situation where it 'crashes' on, I wrote a test program

  • Where the OS is not running (doesn't not start the bios, or let any tasks run)
  • Only the main() loop is running
  • A count down of 10seconds to force the SysCtlReset()
  • 1 hw GPIO to control a LED
  • 1 hw UART to print out some information

When I loop this program endlessly by starting it somewhere in the evening and the next morning the micro crashed. So it happened somewhere between that time period (in one of those 10second countdowns)

After the 10s countdown runs out and right before the SysCtlReset() I set 2 things in my program

  • SysCtlResetBehaviorSet(SYSCTL_ONRST_WDOG0_POR|SYSCTL_ONRST_WDOG1_POR|SYSCTL_ONRST_BOR_POR|SYSCTL_ONRST_EXT_POR);
  • Print out some debug info with some SysCtl_ information, this is what is looks like on default:
    "
    ClockGet: 0x927C00
    FlashSectorSizeGet: 0x4000
    IntStatus: 0x00
    DeepSleepGet: 0x12
    LDOSleepGet: 0x18
    NMIStatus: 0x0
    PWMClockGet: 0x0
    BehaviorGet: 0xFFFFFFFF
    ResetCauseGet: 0x10
    VoltageEventStatus: 0x0
    "

I'm stuck at this point, so maybe you can help me further by answering these 2 questions.

1) Whatever I set with SysCtlResetBehaviorSet() the SysCtlResetBehaviorGet() will allways return 0xFFFFFFFF, regardless if I do it on startup or right before shutdown , even right before the _Get(). it still returns 0xFFFFFFFF. Do you have any idea why this is? the peripheral library datasheet insinuates that this is something I can configure without any extra conditions. Is this possibly some kind of project settings I'm doing wrong?

2) The output of my 10s countdown debug info is always the same (see above), however after a crash situation occurs and I reset it manually (power cycle) the output is different

"
ClockGet: 0x20C58C0
FlashSectorSizeGet: 0x4000
IntStatus: 0x00
DeepSleepGet: 0x12
LDOSleepGet: 0x18
NMIStatus: 0x0
PWMClockGet: 0x0
BehaviorGet: 0xFFFFFFFF
ResetCauseGet: 0x2
VoltageEventStatus: 0x100

"

My question is, do you know what the VoltageEventStatus() with report value 0x100 means? The datasheet only talks about the following possible values

//*****************************************************************************
//
// Values used with the SysCtlVoltageEventStatus() and
// SysCtlVoltageEventClear() APIs.
//
//*****************************************************************************
#define SYSCTL_VESTAT_VDDBOR    0x00000040
#define SYSCTL_VESTAT_VDDABOR   0x00000010

  • Hi Jordi,

    1) Whatever I set with SysCtlResetBehaviorSet() the SysCtlResetBehaviorGet() will allways return 0xFFFFFFFF, regardless if I do it on startup or right before shutdown , even right before the _Get(). it still returns 0xFFFFFFFF. Do you have any idea why this is? the peripheral library datasheet insinuates that this is something I can configure without any extra conditions. Is this possibly some kind of project settings I'm doing wrong?

      SysCtlResetBehaviorGet can only be used for the Flurry class MCU. This function is not applicable to TM4C129. I will suggest you read out the register directly using HWREG()

    2) The output of my 10s countdown debug info is always the same (see above), however after a crash situation occurs and I reset it manually (power cycle) the output is different

    "
    ClockGet: 0x20C58C0
    FlashSectorSizeGet: 0x4000
    IntStatus: 0x00
    DeepSleepGet: 0x12
    LDOSleepGet: 0x18
    NMIStatus: 0x0
    PWMClockGet: 0x0
    BehaviorGet: 0xFFFFFFFF
    ResetCauseGet: 0x2
    VoltageEventStatus: 0x100

     I think the problem has something to do with SYSCTL#23 errata. See below. There is a fix for this errata in the latest TivaWare SDK. However, TI-RTOS does not use the latest version and therefore missed the complete errata fix while having only a partial fix that is not sufficient to address the errata. 

      The fix requires rebuilding TI-RTOS BIOS package with the latest TivaWare that implements the workaround for SYSCTL#23. The existing TI-RTOS has only partial workaround that isn’t complete and I think this is the reason why it can still fail. The problem is a hardware issue that is temperature and material dependent, not a TI-RTOS issue per se.

    First refer to section A.3 and A.4 in SYS/BIOS user’s guide on how to rebuild the library. The user’s guide version I follow is https://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/sysbios/6_53_00_11/exports/bios_6_53_00_11/docs/Bios_User_Guide.pdf.

    Once you are familiar with the SYS/BIOS rebuild flow then follow the below steps to rebuild TI-RTOS for the errata fix. 

    1. Make a duplicate copy of bios_6_45_01_29 as  copy-bios_6_45_01_29. See below. 

    2. Modify the bios.mak file under copy-bios_6_45_01_29. The only things to change are line 16 and 39. Depending on the version of the compiler is used, the path will be slightly different. See below.

    3. Replace C:\ti\tirtos_tivac_2_16_00_08_old2\products\copy-bios_6_45_01_29\packages\ti\catalog\arm\cortexm4\tiva\ce\Boot_sysctl.c file with the attached Boot_sysctl.c file that has the complete workaround for SYSCTL#23. 

    /*
     * Copyright (c) 2013, 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.
     * */
    
    /*
     *  ======== Boot_sysctl.c ========
     */
    
    #include <xdc/std.h>
    
    #ifndef bool
    #define bool Bool
    #endif
    #ifndef uint32_t
    #define uint32_t UInt32
    #endif
    #ifndef int32_t
    #define int32_t Int32
    #endif
    #ifndef uint_fast8_t
    #define uint_fast8_t UChar
    #endif
    #ifndef uint_fast16_t
    #define uint_fast16_t UInt16
    #endif
    #ifndef true
    #define true 1
    #endif
    #ifndef false
    #define false 0
    #endif
    
    #include "hw_sysctl.h"
    #include "hw_types.h"
    #include "sysctl.h"
    
    #include "package/internal/Boot.xdc.h"
    
    #define ASSERT(expr)
    
    
    //*****************************************************************************
    //
    // A macro used to determine whether the target part uses the new SysCtl
    // register layout.
    //
    //*****************************************************************************
    #define NEW_SYSCTL_CONFIGURATION (CLASS_IS_FLURRY || CLASS_IS_SNOWFLAKE)
    
    //*****************************************************************************
    //
    //
    //
    //*****************************************************************************
    #ifndef FLASH_PP_MAINSS_S
    #define FLASH_PP_MAINSS_S       16
    #endif
    
    //*****************************************************************************
    //
    // This macro extracts the array index out of the peripheral number.
    //
    //*****************************************************************************
    #define SYSCTL_PERIPH_INDEX(a)  (((a) >> 28) & 0xf)
    
    //*****************************************************************************
    //
    // This macro constructs the peripheral bit mask from the peripheral number.
    //
    //*****************************************************************************
    #define SYSCTL_PERIPH_MASK(a)   (((a) & 0xffff) << (((a) & 0x001f0000) >> 16))
    
    //*****************************************************************************
    //
    // This macro converts the XTAL value provided in the ui32Config parameter to
    // an index to the g_pui32Xtals array.
    //
    //*****************************************************************************
    #define SysCtlXtalCfgToIndex(a) ((a & 0x7c0) >> 6)
    
    //*****************************************************************************
    //
    // An array that maps the crystal number in RCC to a frequency.
    //
    //*****************************************************************************
    static const uint32_t g_pui32Xtals[] =
    {
        1000000,
        1843200,
        2000000,
        2457600,
        3579545,
        3686400,
        4000000,
        4096000,
        4915200,
        5000000,
        5120000,
        6000000,
        6144000,
        7372800,
        8000000,
        8192000,
        10000000,
        12000000,
        12288000,
        13560000,
        14318180,
        16000000,
        16384000,
        18000000,
        20000000,
        24000000,
        25000000
    };
    
    //*****************************************************************************
    //
    // Maximum number of VCO entries in the g_pui32XTALtoVCO and
    // g_pui32VCOFrequencies structures for a device.
    //
    //*****************************************************************************
    #define MAX_VCO_ENTRIES         2
    #define MAX_XTAL_ENTRIES        18
    
    //*****************************************************************************
    //
    // These macros are used in the g_pui32XTALtoVCO table to make it more
    // readable.
    //
    //*****************************************************************************
    #define PLL_M_TO_REG(mi, mf)                                                  \
            ((uint32_t)mi | (uint32_t)(mf << SYSCTL_PLLFREQ0_MFRAC_S))
    #define PLL_N_TO_REG(n)                                                       \
            ((uint32_t)(n - 1) << SYSCTL_PLLFREQ1_N_S)
    #define PLL_Q_TO_REG(q)                                                       \
            ((uint32_t)(q - 1) << SYSCTL_PLLFREQ1_Q_S)
    
    //*****************************************************************************
    //
    // Look up of the values that go into the PLLFREQ0 and PLLFREQ1 registers.
    //
    //*****************************************************************************
    static const uint32_t g_pppui32XTALtoVCO[MAX_VCO_ENTRIES][MAX_XTAL_ENTRIES][2] =
    {
        {
            //
            // VCO 320 MHz
            //
            { PLL_M_TO_REG(64, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 5 MHz
            { PLL_M_TO_REG(62, 512), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 5.12 MHz
            { PLL_M_TO_REG(160, 0),  PLL_N_TO_REG(3), PLL_Q_TO_REG(2) },     // 6 MHz
            { PLL_M_TO_REG(52, 85),  PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 6.144 MHz
            { PLL_M_TO_REG(43, 412), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 7.3728 MHz
            { PLL_M_TO_REG(40, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 8 MHz
            { PLL_M_TO_REG(39, 64),  PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 8.192 MHz
            { PLL_M_TO_REG(32, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 10 MHz
            { PLL_M_TO_REG(80, 0),   PLL_N_TO_REG(3), PLL_Q_TO_REG(2) },     // 12 MHz
            { PLL_M_TO_REG(26, 43),  PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 12.288 MHz
            { PLL_M_TO_REG(23, 613), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 13.56 MHz
            { PLL_M_TO_REG(22, 358), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 14.318180 MHz
            { PLL_M_TO_REG(20, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 16 MHz
            { PLL_M_TO_REG(19, 544), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 16.384 MHz
            { PLL_M_TO_REG(160, 0),  PLL_N_TO_REG(9), PLL_Q_TO_REG(2) },     // 18 MHz
            { PLL_M_TO_REG(16, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 20 MHz
            { PLL_M_TO_REG(40, 0),   PLL_N_TO_REG(3), PLL_Q_TO_REG(2) },     // 24 MHz
            { PLL_M_TO_REG(64, 0),   PLL_N_TO_REG(5), PLL_Q_TO_REG(2) },     // 25 MHz
        },
        {
            //
            // VCO 480 MHz
            //
            { PLL_M_TO_REG(96, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 5 MHz
            { PLL_M_TO_REG(93, 768), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 5.12 MHz
            { PLL_M_TO_REG(80, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 6 MHz
            { PLL_M_TO_REG(78, 128), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 6.144 MHz
            { PLL_M_TO_REG(65, 107), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 7.3728 MHz
            { PLL_M_TO_REG(60, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 8 MHz
            { PLL_M_TO_REG(58, 608), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 8.192 MHz
            { PLL_M_TO_REG(48, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 10 MHz
            { PLL_M_TO_REG(40, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 12 MHz
            { PLL_M_TO_REG(39, 64),  PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 12.288 MHz
            { PLL_M_TO_REG(35, 408), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 13.56 MHz
            { PLL_M_TO_REG(33, 536), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 14.318180 MHz
            { PLL_M_TO_REG(30, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 16 MHz
            { PLL_M_TO_REG(29, 304), PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 16.384 MHz
            { PLL_M_TO_REG(80, 0),   PLL_N_TO_REG(3), PLL_Q_TO_REG(2) },     // 18 MHz
            { PLL_M_TO_REG(24, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 20 MHz
            { PLL_M_TO_REG(20, 0),   PLL_N_TO_REG(1), PLL_Q_TO_REG(2) },     // 24 MHz
            { PLL_M_TO_REG(96, 0),   PLL_N_TO_REG(5), PLL_Q_TO_REG(2) },     // 25 MHz
        },
    };
    
    //*****************************************************************************
    //
    // The mapping of system clock frequency to flash memory timing parameters.
    //
    //*****************************************************************************
    static const struct
    {
        uint32_t ui32Frequency;
        uint32_t ui32MemTiming;
    }
    g_sXTALtoMEMTIM[] =
    {
        { 16000000, (SYSCTL_MEMTIM0_FBCHT_0_5 | SYSCTL_MEMTIM0_FBCE |
                     (0 << SYSCTL_MEMTIM0_FWS_S) |
                     SYSCTL_MEMTIM0_EBCHT_0_5 | SYSCTL_MEMTIM0_EBCE |
                     (0 << SYSCTL_MEMTIM0_EWS_S) |
                     SYSCTL_MEMTIM0_MB1) },
        { 40000000, (SYSCTL_MEMTIM0_FBCHT_1_5 | (1 << SYSCTL_MEMTIM0_FWS_S) |
                     SYSCTL_MEMTIM0_FBCHT_1_5 | (1 << SYSCTL_MEMTIM0_EWS_S) |
                     SYSCTL_MEMTIM0_MB1) },
        { 60000000, (SYSCTL_MEMTIM0_FBCHT_2 | (2 << SYSCTL_MEMTIM0_FWS_S) |
                     SYSCTL_MEMTIM0_EBCHT_2 | (2 << SYSCTL_MEMTIM0_EWS_S) |
                     SYSCTL_MEMTIM0_MB1) },
        { 80000000, (SYSCTL_MEMTIM0_FBCHT_2_5 | (3 << SYSCTL_MEMTIM0_FWS_S) |
                     SYSCTL_MEMTIM0_EBCHT_2_5 | (3 << SYSCTL_MEMTIM0_EWS_S) |
                     SYSCTL_MEMTIM0_MB1) },
        { 100000000, (SYSCTL_MEMTIM0_FBCHT_3 | (4 << SYSCTL_MEMTIM0_FWS_S) |
                      SYSCTL_MEMTIM0_EBCHT_3 | (4 << SYSCTL_MEMTIM0_EWS_S) |
                      SYSCTL_MEMTIM0_MB1) },
        { 120000000, (SYSCTL_MEMTIM0_FBCHT_3_5 | (5 << SYSCTL_MEMTIM0_FWS_S) |
                      SYSCTL_MEMTIM0_EBCHT_3_5 | (5 << SYSCTL_MEMTIM0_EWS_S) |
                      SYSCTL_MEMTIM0_MB1) },
    };
    
    //*****************************************************************************
    //
    // Get the correct memory timings for a given system clock value.
    //
    //*****************************************************************************
    static uint32_t
    _SysCtlMemTimingGet(uint32_t ui32SysClock)
    {
        uint_fast8_t ui8Idx;
    
        //
        // Loop through the flash memory timings.
        //
        for(ui8Idx = 0;
            ui8Idx < (sizeof(g_sXTALtoMEMTIM) / sizeof(g_sXTALtoMEMTIM[0]));
            ui8Idx++)
        {
            //
            // See if the system clock frequency is less than the maximum frequency
            // for this flash memory timing.
            //
            if(ui32SysClock <= g_sXTALtoMEMTIM[ui8Idx].ui32Frequency)
            {
                //
                // This flash memory timing is the best choice for the system clock
                // frequency, so return it now.
                //
                return(g_sXTALtoMEMTIM[ui8Idx].ui32MemTiming);
            }
        }
    
        //
        // An appropriate flash memory timing could not be found, so the device is
        // being clocked too fast.  Return the default flash memory timing.
        //
        return(0);
    }
    
    //*****************************************************************************
    //
    // Calculate the system frequency from the register settings base on the
    // oscillator input.
    //
    //*****************************************************************************
    static uint32_t
    _SysCtlFrequencyGet(uint32_t ui32Xtal)
    {
        uint32_t ui32Result;
        uint_fast16_t ui16F1, ui16F2;
        uint_fast16_t ui16PInt, ui16PFract;
        uint_fast8_t ui8Q, ui8N;
    
        //
        // Extract all of the values from the hardware registers.
        //
        ui16PFract = ((HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_MFRAC_M) >>
                      SYSCTL_PLLFREQ0_MFRAC_S);
        ui16PInt = HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_MINT_M;
        ui8Q = (((HWREG(SYSCTL_PLLFREQ1) & SYSCTL_PLLFREQ1_Q_M) >>
                 SYSCTL_PLLFREQ1_Q_S) + 1);
        ui8N = (((HWREG(SYSCTL_PLLFREQ1) & SYSCTL_PLLFREQ1_N_M) >>
                 SYSCTL_PLLFREQ1_N_S) + 1);
    
        //
        // Divide the crystal value by N.
        //
        ui32Xtal /= (uint32_t)ui8N;
    
        //
        // Calculate the multiplier for bits 9:5.
        //
        ui16F1 = ui16PFract / 32;
    
        //
        // Calculate the multiplier for bits 4:0.
        //
        ui16F2 = ui16PFract - (ui16F1 * 32);
    
        //
        // Get the integer portion.
        //
        ui32Result = ui32Xtal * (uint32_t)ui16PInt;
    
        //
        // Add first fractional bits portion(9:0).
        //
        ui32Result += (ui32Xtal * (uint32_t)ui16F1) / 32;
    
        //
        // Add the second fractional bits portion(4:0).
        //
        ui32Result += (ui32Xtal * (uint32_t)ui16F2) / 1024;
    
        //
        // Divide the result by Q.
        //
        ui32Result = ui32Result / (uint32_t)ui8Q;
    
        //
        // Return the resulting PLL frequency.
        //
        return(ui32Result);
    }
    
    //*****************************************************************************
    //
    // Look up of the possible VCO frequencies.
    //
    //*****************************************************************************
    static const uint32_t g_pui32VCOFrequencies[MAX_VCO_ENTRIES] =
    {
        160000000,                              // VCO 320
        240000000,                              // VCO 480
    };
    
    //*****************************************************************************
    //
    // The base addresses of the various peripheral control registers.
    //
    //*****************************************************************************
    #define SYSCTL_PPBASE           0x400fe300
    #define SYSCTL_SRBASE           0x400fe500
    #define SYSCTL_RCGCBASE         0x400fe600
    #define SYSCTL_SCGCBASE         0x400fe700
    #define SYSCTL_DCGCBASE         0x400fe800
    #define SYSCTL_PCBASE           0x400fe900
    #define SYSCTL_PRBASE           0x400fea00
    
    //*****************************************************************************
    //
    //! Configures the system clock.
    //!
    //! \param ui32Config is the required configuration of the device clocking.
    //! \param ui32SysClock is the requested processor frequency.
    //!
    //! This function configures the main system clocking for the device.  The
    //! input frequency, oscillator source, whether or not to enable the PLL, and
    //! the system clock divider are all configured with this function.  This
    //! function configures the system frequency to the closest available divisor
    //! of one of the fixed PLL VCO settings provided in the \e ui32Config
    //! parameter.  The caller sets the \e ui32SysClock parameter to request the
    //! system clock frequency, and this function then attempts to match this using
    //! the values provided in the \e ui32Config parameter.  If this function
    //! cannot exactly match the requested frequency, it picks the closest
    //! frequency that is lower than the requested frequency.  The \e ui32Config
    //! parameter provides the remaining configuration options using a set of
    //! defines that are a logical OR of several different values, many of which
    //! are grouped into sets where only one of the set can be chosen.  This
    //! function returns the current system frequency which may not match the
    //! requested frequency.
    //!
    //! The oscillator source is chosen with one of the following values:
    //!
    //! - \b SYSCTL_OSC_MAIN to use an external crystal or oscillator.
    //! - \b SYSCTL_OSC_INT to use the 16-MHz precision internal oscillator.
    //! - \b SYSCTL_OSC_INT30 to use the internal low frequency oscillator.
    //! - \b SYSCTL_OSC_EXT32 to use the hibernate modules 32.786-kHz oscillator.
    //! This option is only available on devices that include the hibernation
    //! module.
    //!
    //! The system clock source is chosen with one of the following values:
    //!
    //! - \b SYSCTL_USE_PLL is used to select the PLL output as the system clock.
    //! - \b SYSCTL_USE_OSC is used to choose one of the oscillators as the
    //! system clock.
    //!
    //! The PLL VCO frequency is chosen with one of the the following values:
    //!
    //! - \b SYSCTL_CFG_VCO_480 to set the PLL VCO output to 480-MHz
    //! - \b SYSCTL_CFG_VCO_320 to set the PLL VCO output to 320-MHz
    //!
    //! Example: Configure the system clocking to be 40 MHz with a 320-MHz PLL
    //! setting using the 16-MHz internal oscillator.
    //!
    //! \verbatim
    //! SysCtlClockFreqSet(SYSCTL_OSC_INT | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320,
    //!                    40000000);
    //! \endverbatim
    //!
    //! \note This function cannot be used with TM4C123 devices.  For TM4C123
    //! devices use the SysCtlClockSet() function.
    //!
    //! \return The actual configured system clock frequency in Hz or zero if the
    //! value could not be changed due to a parameter error or PLL lock failure.
    //
    //*****************************************************************************
    ULong
    Boot_sysCtlClockFreqSetI(ULong ui32Config, ULong ui32SysClock)
    {
        int32_t i32Timeout, i32VCOIdx, i32XtalIdx;
        uint32_t ui32MOSCCTL;
        uint32_t ui32Delay;
        uint32_t ui32SysDiv, ui32Osc, ui32OscSelect, ui32RSClkConfig;
    
        //
        // TM4C123 devices should not use this function.
        //
        if(CLASS_IS_TM4C123)
        {
            return(0);
        }
    
        //
        // Get the index of the crystal from the ui32Config parameter.
        //
        i32XtalIdx = SysCtlXtalCfgToIndex(ui32Config);
    
        //
        // Determine which non-PLL source was selected.
        //
        if((ui32Config & 0x38) == SYSCTL_OSC_INT)
        {
            //
            // Use the nominal frequency for the PIOSC oscillator and set the
            // crystal select.
            //
            ui32Osc = 16000000;
            ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC;
            ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_PIOSC;
    
            //
            // Force the crystal index to the value for 16-MHz.
            //
            i32XtalIdx = SysCtlXtalCfgToIndex(SYSCTL_XTAL_16MHZ);
        }
        else if((ui32Config & 0x38) == SYSCTL_OSC_INT30)
        {
            //
            // Use the nominal frequency for the low frequency oscillator.
            //
            ui32Osc = 30000;
            ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_LFIOSC;
        }
        else if((ui32Config & 0x38) == (SYSCTL_OSC_EXT32 & 0x38))
        {
            //
            // Use the RTC frequency.
            //
            ui32Osc = 32768;
            ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_RTC;
        }
        else if((ui32Config & 0x38) == SYSCTL_OSC_MAIN)
        {
            //
            // Bounds check the source frequency for the main oscillator.  The is
            // because the PLL tables in the g_pppui32XTALtoVCO structure range
            // from 5MHz to 25MHz.
            //
            if((i32XtalIdx > (SysCtlXtalCfgToIndex(SYSCTL_XTAL_25MHZ))) ||
               (i32XtalIdx < (SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ))))
            {
                return(0);
            }
    
            ui32Osc = g_pui32Xtals[i32XtalIdx];
    
            //
            // Set the PLL source select to MOSC.
            //
            ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_MOSC;
            ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_MOSC;
    
            //
            // Clear MOSC power down, high oscillator range setting, and no crystal
            // present setting.
            //
            ui32MOSCCTL = HWREG(SYSCTL_MOSCCTL) &
                          ~(SYSCTL_MOSCCTL_OSCRNG | SYSCTL_MOSCCTL_PWRDN |
                            SYSCTL_MOSCCTL_NOXTAL);
    
            //
            // Increase the drive strength for MOSC of 10 MHz and above.
            //
            if(i32XtalIdx >= (SysCtlXtalCfgToIndex(SYSCTL_XTAL_10MHZ) -
                              (SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ))))
            {
                ui32MOSCCTL |= SYSCTL_MOSCCTL_OSCRNG;
            }
    
            HWREG(SYSCTL_MOSCCTL) = ui32MOSCCTL;
            
            //
            // Timeout using the legacy delay value.
            //
            ui32Delay = 524288;
    
            while((HWREG(SYSCTL_RIS) & SYSCTL_RIS_MOSCPUPRIS) == 0)
            {
                ui32Delay--;
    
                if(ui32Delay == 0)
                {
                    break;
                }
            }
    
            //
            // If the main oscillator failed to start up then do not switch to
            // it and return.
            //
            if(ui32Delay == 0)
            {
                return(0);
            }
    
            
        }
        else
        {
            //
            // This was an invalid request because no oscillator source was
            // indicated.
            //
            ui32Osc = 0;
            ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC;
        }
    
        //
        // Check if the running with the PLL enabled was requested.
        //
        if((ui32Config & SYSCTL_USE_OSC) == SYSCTL_USE_PLL)
        {
            //
            // ui32Config must be SYSCTL_OSC_MAIN or SYSCTL_OSC_INT.
            //
            if(((ui32Config & 0x38) != SYSCTL_OSC_MAIN) &&
               ((ui32Config & 0x38) != SYSCTL_OSC_INT))
            {
                return(0);
            }
    
            //
            // Get the VCO index out of the ui32Config parameter.
            //
            i32VCOIdx = (ui32Config >> 24) & 7;
    
            //
            // Check that the VCO index is not out of bounds.
            //
            ASSERT(i32VCOIdx < MAX_VCO_ENTRIES);
    
            //
            // Set the memory timings for the maximum external frequency since
            // this could be a switch to PIOSC or possibly to MOSC which can be
            // up to 25MHz.
            //
            HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(25000000);
    
            //
            // Clear the old PLL divider and source in case it was set.
            //
            ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG) &
                              ~(SYSCTL_RSCLKCFG_PSYSDIV_M |
                                SYSCTL_RSCLKCFG_OSCSRC_M |
                                SYSCTL_RSCLKCFG_PLLSRC_M | SYSCTL_RSCLKCFG_USEPLL);
    
            //
            // Update the memory timings to match running from PIOSC.
            //
            ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
    
            //
            // Update clock configuration to switch back to PIOSC.
            //
            HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
    
            //
            // The table starts at 5 MHz so modify the index to match this.
            //
            i32XtalIdx -= SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ);
    
            //
            // Calculate the System divider such that we get a frequency that is
            // the closest to the requested frequency without going over.
            //
            ui32SysDiv = (g_pui32VCOFrequencies[i32VCOIdx] + ui32SysClock - 1) /
                         ui32SysClock;
    
            //
            // Set the oscillator source.
            //
            HWREG(SYSCTL_RSCLKCFG) |= ui32OscSelect;
    
            //
            // Set the M, N and Q values provided from the table and preserve
            // the power state of the main PLL.
            //
            HWREG(SYSCTL_PLLFREQ1) =
                g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][1];
            HWREG(SYSCTL_PLLFREQ1) |= PLL_Q_TO_REG(ui32SysDiv);
            HWREG(SYSCTL_PLLFREQ0) =
                (g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][0] |
                 (HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_PLLPWR));
    
            //
            // Calculate the actual system clock as PSYSDIV is always div-by 2.
            //
            ui32SysClock = _SysCtlFrequencyGet(ui32Osc) / 2;
    
            //
            // Set the Flash and EEPROM timing values.
            //
            HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(ui32SysClock);
    
            //
            // Check if the PLL is already powered up.
            //
            if(HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_PLLPWR)
            {
                //
                // Trigger the PLL to lock to the new frequency.
                //
                HWREG(SYSCTL_RSCLKCFG) |= SYSCTL_RSCLKCFG_NEWFREQ;
            }
            else
            {
                //
                // Power up the PLL.
                //
                HWREG(SYSCTL_PLLFREQ0) |= SYSCTL_PLLFREQ0_PLLPWR;
            }
    
            //
            // Wait until the PLL has locked.
            //
            for(i32Timeout = 32768; i32Timeout > 0; i32Timeout--)
            {
                if((HWREG(SYSCTL_PLLSTAT) & SYSCTL_PLLSTAT_LOCK))
                {
                    break;
                }
            }
    
            //
            // If the loop above did not timeout then switch over to the PLL
            //
            if(i32Timeout)
            {
                ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
                ui32RSClkConfig |= (1 << SYSCTL_RSCLKCFG_PSYSDIV_S) |
                                    ui32OscSelect | SYSCTL_RSCLKCFG_USEPLL;
                ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
    
                //
                // Set the new clock configuration.
                //
                HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
            }
            else
            {
                ui32SysClock = 0;
            }
        }
        else
        {
            //
            // Set the Flash and EEPROM timing values for PIOSC.
            //
            HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(16000000);
    
            //
            // Make sure that the PLL is powered down since it is not being used.
            //
            HWREG(SYSCTL_PLLFREQ0) &= ~SYSCTL_PLLFREQ0_PLLPWR;
    
            //
            // Clear the old PLL divider and source in case it was set.
            //
            ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
            ui32RSClkConfig &= ~(SYSCTL_RSCLKCFG_OSYSDIV_M |
                                 SYSCTL_RSCLKCFG_OSCSRC_M |
                                 SYSCTL_RSCLKCFG_USEPLL);
    
            //
            // Update the memory timings.
            //
            ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
    
            //
            // Set the new clock configuration.
            //
            HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
    
            //
            // If zero given as the system clock then default to divide by 1.
            //
            if(ui32SysClock == 0)
            {
                ui32SysDiv = 0;
            }
            else
            {
                //
                // Calculate the System divider based on the requested
                // frequency.
                //
                ui32SysDiv = ui32Osc / ui32SysClock;
    
                //
                // If the system divisor is not already zero, subtract one to
                // set the value in the register which requires the value to
                // be n-1.
                //
                if(ui32SysDiv != 0)
                {
                    ui32SysDiv -= 1;
                }
    
                //
                // Calculate the system clock.
                //
                ui32SysClock = ui32Osc / (ui32SysDiv + 1);
            }
    
            //
            // Set the memory timing values for the new system clock.
            //
            HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(ui32SysClock);
    
            //
            // Set the new system clock values.
            //
            ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
            ui32RSClkConfig |= (ui32SysDiv << SYSCTL_RSCLKCFG_OSYSDIV_S) |
                               ui32OscSelect;
    
            //
            // Update the memory timings.
            //
            ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
    
            //
            // Set the new clock configuration.
            //
            HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
        }
    
        //
        // Finally change the OSCSRC back to PIOSC
        //
        HWREG(SYSCTL_RSCLKCFG) &= ~(SYSCTL_RSCLKCFG_OSCSRC_M);
    
        return(ui32SysClock);
    }
    
    //*****************************************************************************
    //
    //! Sets the clocking of the device.
    //!
    //! \param ui32Config is the required configuration of the device clocking.
    //!
    //! This function configures the clocking of the device.  The input crystal
    //! frequency, oscillator to be used, use of the PLL, and the system clock
    //! divider are all configured with this function.
    //!
    //! The \e ui32Config parameter is the logical OR of several different values,
    //! many of which are grouped into sets where only one can be chosen.
    //!
    //! The system clock divider is chosen with one of the following values:
    //! \b SYSCTL_SYSDIV_1, \b SYSCTL_SYSDIV_2, \b SYSCTL_SYSDIV_3, ...
    //! \b SYSCTL_SYSDIV_64.
    //!
    //! The use of the PLL is chosen with either \b SYSCTL_USE_PLL or
    //! \b SYSCTL_USE_OSC.
    //!
    //! The external crystal frequency is chosen with one of the following values:
    //! \b SYSCTL_XTAL_4MHZ, \b SYSCTL_XTAL_4_09MHZ, \b SYSCTL_XTAL_4_91MHZ,
    //! \b SYSCTL_XTAL_5MHZ, \b SYSCTL_XTAL_5_12MHZ, \b SYSCTL_XTAL_6MHZ,
    //! \b SYSCTL_XTAL_6_14MHZ, \b SYSCTL_XTAL_7_37MHZ, \b SYSCTL_XTAL_8MHZ,
    //! \b SYSCTL_XTAL_8_19MHZ, \b SYSCTL_XTAL_10MHZ, \b SYSCTL_XTAL_12MHZ,
    //! \b SYSCTL_XTAL_12_2MHZ, \b SYSCTL_XTAL_13_5MHZ, \b SYSCTL_XTAL_14_3MHZ,
    //! \b SYSCTL_XTAL_16MHZ, \b SYSCTL_XTAL_16_3MHZ, \b SYSCTL_XTAL_18MHZ,
    //! \b SYSCTL_XTAL_20MHZ, \b SYSCTL_XTAL_24MHZ, or \b SYSCTL_XTAL_25MHz.
    //! Values below \b SYSCTL_XTAL_5MHZ are not valid when the PLL is in
    //! operation.
    //!
    //! The oscillator source is chosen with one of the following values:
    //! \b SYSCTL_OSC_MAIN, \b SYSCTL_OSC_INT, \b SYSCTL_OSC_INT4,
    //! \b SYSCTL_OSC_INT30, or \b SYSCTL_OSC_EXT32.  \b SYSCTL_OSC_EXT32 is only
    //! available on devices with the hibernate module, and then only when the
    //! hibernate module has been enabled.
    //!
    //! The internal and main oscillators are disabled with the
    //! \b SYSCTL_INT_OSC_DIS and \b SYSCTL_MAIN_OSC_DIS flags, respectively.
    //! The external oscillator must be enabled in order to use an external clock
    //! source.  Note that attempts to disable the oscillator used to clock the
    //! device is prevented by the hardware.
    //!
    //! To clock the system from an external source (such as an external crystal
    //! oscillator), use \b SYSCTL_USE_OSC \b | \b SYSCTL_OSC_MAIN.  To clock the
    //! system from the main oscillator, use \b SYSCTL_USE_OSC \b |
    //! \b SYSCTL_OSC_MAIN.  To clock the system from the PLL, use
    //! \b SYSCTL_USE_PLL \b | \b SYSCTL_OSC_MAIN, and select the appropriate
    //! crystal with one of the \b SYSCTL_XTAL_xxx values.
    //!
    //! \note This function should only be called on Blizzard-class devices.  For
    //! all other devices use the SysCtlClockFreqSet() function.
    //!
    //!
    //! \note If selecting the PLL as the system clock source (that is, via
    //! \b SYSCTL_USE_PLL), this function polls the PLL lock interrupt to
    //! determine when the PLL has locked.  If an interrupt handler for the
    //! system control interrupt is in place, and it responds to and clears the
    //! PLL lock interrupt, this function delays until its timeout has occurred
    //! instead of completing as soon as PLL lock is achieved.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    Boot_sysCtlClockSetI(ULong ui32Config)
    {
        uint32_t ui32Delay, ui32RCC, ui32RCC2;
    
        //
        // Get the current value of the RCC and RCC2 registers.
        //
        ui32RCC = HWREG(SYSCTL_RCC);
        ui32RCC2 = HWREG(SYSCTL_RCC2);
    
        //
        // Bypass the PLL and system clock dividers for now.
        //
        ui32RCC |= SYSCTL_RCC_BYPASS;
        ui32RCC &= ~(SYSCTL_RCC_USESYSDIV);
        ui32RCC2 |= SYSCTL_RCC2_BYPASS2;
    
        //
        // Write the new RCC value.
        //
        HWREG(SYSCTL_RCC) = ui32RCC;
        HWREG(SYSCTL_RCC2) = ui32RCC2;
    
        //
        // See if the oscillator needs to be enabled.
        //
        if((ui32RCC & SYSCTL_RCC_MOSCDIS) && !(ui32Config & SYSCTL_RCC_MOSCDIS))
        {
            //
            // Make sure that the required oscillators are enabled.  For now, the
            // previously enabled oscillators must be enabled along with the newly
            // requested oscillators.
            //
            ui32RCC &= (~SYSCTL_RCC_MOSCDIS | (ui32Config & SYSCTL_RCC_MOSCDIS));
    
            //
            // Write the new RCC value.
            //
            HWREG(SYSCTL_RCC) = ui32RCC;
    
            //
            // Wait for a bit, giving the oscillator time to stabilize.  The number
            // of iterations is adjusted based on the current clock source; a
            // smaller number of iterations is required for slower clock rates.
            //
            if(((ui32RCC2 & SYSCTL_RCC2_USERCC2) &&
                (((ui32RCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_30) ||
                 ((ui32RCC2 & SYSCTL_RCC2_OSCSRC2_M) ==
                  SYSCTL_RCC2_OSCSRC2_32))) ||
               (!(ui32RCC2 & SYSCTL_RCC2_USERCC2) &&
                ((ui32RCC & SYSCTL_RCC_OSCSRC_M) == SYSCTL_RCC_OSCSRC_30)))
            {
                //
                // Delay for 4096 iterations.
                //
                Boot_sysCtlDelayI(4096);
            }
            else
            {
                //
                // Delay for 524,288 iterations.
                //
                Boot_sysCtlDelayI(524288);
            }
        }
    
        //
        // Set the new crystal value and oscillator source.  Because the OSCSRC2
        // field in RCC2 overlaps the XTAL field in RCC, the OSCSRC field has a
        // special encoding within ui32Config to avoid the overlap.
        //
        ui32RCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
        ui32RCC |= ui32Config & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
        ui32RCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M);
        ui32RCC2 |= ui32Config & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M);
        ui32RCC2 |= (ui32Config & 0x00000008) << 3;
    
        //
        // Write the new RCC value.
        //
        HWREG(SYSCTL_RCC) = ui32RCC;
        HWREG(SYSCTL_RCC2) = ui32RCC2;
    
        //
        // Wait for a bit so that new crystal value and oscillator source can take
        // effect.
        //
        Boot_sysCtlDelayI(16);
    
        //
        // Set the PLL configuration.
        //
        ui32RCC &= ~SYSCTL_RCC_PWRDN;
        ui32RCC |= ui32Config & SYSCTL_RCC_PWRDN;
        ui32RCC2 &= ~SYSCTL_RCC2_PWRDN2;
        ui32RCC2 |= ui32Config & SYSCTL_RCC2_PWRDN2;
    
        //
        // Clear the PLL lock interrupt.
        //
        HWREG(SYSCTL_MISC) = SYSCTL_INT_PLL_LOCK;
    
        //
        // Write the new RCC value.
        //
        if(ui32RCC2 & SYSCTL_RCC2_USERCC2)
        {
            HWREG(SYSCTL_RCC2) = ui32RCC2;
            HWREG(SYSCTL_RCC) = ui32RCC;
        }
        else
        {
            HWREG(SYSCTL_RCC) = ui32RCC;
            HWREG(SYSCTL_RCC2) = ui32RCC2;
        }
    
        //
        // Set the requested system divider and disable the appropriate
        // oscillators.  This value is not written immediately.
        //
        ui32RCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
                     SYSCTL_RCC_MOSCDIS);
        ui32RCC |= ui32Config & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
                                 SYSCTL_RCC_MOSCDIS);
        ui32RCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M);
        ui32RCC2 |= ui32Config & SYSCTL_RCC2_SYSDIV2_M;
        if(ui32Config & SYSCTL_RCC2_DIV400)
        {
            ui32RCC |= SYSCTL_RCC_USESYSDIV;
            ui32RCC2 &= ~(SYSCTL_RCC_USESYSDIV);
            ui32RCC2 |= ui32Config & (SYSCTL_RCC2_DIV400 | SYSCTL_RCC2_SYSDIV2LSB);
        }
        else
        {
            ui32RCC2 &= ~(SYSCTL_RCC2_DIV400);
        }
    
        //
        // See if the PLL output is being used to clock the system.
        //
        if(!(ui32Config & SYSCTL_RCC_BYPASS))
        {
            //
            // Wait until the PLL has locked.
            //
            for(ui32Delay = 32768; ui32Delay > 0; ui32Delay--)
            {
                if(HWREG(SYSCTL_RIS) & SYSCTL_INT_PLL_LOCK)
                {
                    break;
                }
            }
    
            //
            // Enable use of the PLL.
            //
            ui32RCC &= ~(SYSCTL_RCC_BYPASS);
            ui32RCC2 &= ~(SYSCTL_RCC2_BYPASS2);
        }
    
        //
        // Write the final RCC value.
        //
        HWREG(SYSCTL_RCC) = ui32RCC;
        HWREG(SYSCTL_RCC2) = ui32RCC2;
    
        //
        // Delay for a little bit so that the system divider takes effect.
        //
        Boot_sysCtlDelayI(16);
    }
    
    //*****************************************************************************
    //
    //! Provides a small delay.
    //!
    //! \param ulCount is the number of delay loop iterations to perform.
    //!
    //! This function provides a means of generating a constant length delay.  It
    //! is written in assembly to keep the delay consistent across tool chains,
    //! avoiding the need to tune the delay based on the tool chain in use.
    //!
    //! The loop takes 3 cycles/loop.
    //!
    //! \return None.
    //
    //*****************************************************************************
    
    //
    // For CCS implement this function in pure assembly.  This prevents the TI
    // compiler from doing funny things with the optimizer.
    //
    #if defined(__ti__)
        __asm("    .sect \".text:ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I\"\n"
              "    .clink\n"
              "    .thumbfunc ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I\n"
              "    .thumb\n"
              "    .global ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I\n"
              "ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I:\n"
              "    subs r0, #1\n"
              "    bne.n ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I\n"
              "    bx lr\n");
    #endif
    
    #if defined(__GNUC__) && !defined(__ti__)
    void __attribute__((naked))
    ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I(unsigned long ulCount)
    {
        __asm("    subs    r0, #1\n"
              "    bne     ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I\n"
              "    bx      lr");
    }
    #endif
    
    #if defined(__IAR_SYSTEMS_ICC__)
    void
    ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I(unsigned long ulCount)
    {
        __asm("    subs    r0, #1\n"
              "    bne.n   ti_catalog_arm_cortexm4_tiva_ce_Boot_sysCtlDelayI__I\n"
              "    bx      lr");
    }
    #endif
    
    4. Type ‘gmake -f .\bios.mak clean

    5. Type ‘gmake -f .\bios.mak’

    6. After the bios is rebuild, in CCS, update the library path as follows.

  • Hi Charles,

    Thank you very much for your detailed reply. I have it running for a full week now and it didn't crashed once. So this solves the issue for me!

    Maybe you can point to a right direction with another thing, to test it I used the same directory name as the original bios folder.

    If I use a copy of my bios folder (like you suggested) and then rebuild it I get a output error of which I can't get to find the cause for. 

    "C:/ti/xdctools_3_32_01_22_core/xs" --xdcpath="C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31_custom_sysctlfix;C:/ti/tirtos_tivac_2_16_01_14/packages;C:/ti/tirtos_tivac_2_16_01_14/products/tidrivers_tivac_2_16_01_13/packages;C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31_custom_sysctlfix;C:/ti/tirtos_tivac_2_16_01_14/products/ndk_2_25_00_09/packages;C:/ti/tirtos_tivac_2_16_01_14/products/uia_2_00_05_50/packages;C:/ti/tirtos_tivac_2_16_01_14/products/ns_1_11_00_10/packages;C:/ti/ccs1040/ccs/ccs_base;" xdc.tools.configuro -o configPkg -t ti.targets.arm.elf.M4F -p ti.platforms.tiva:TM4C1294NCPDT -r release -c "C:/ti/ccs1040/ccs/tools/compiler/ti-cgt-arm_20.2.5.LTS" --compileOptions "-mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -Ooff --opt_for_speed=0 --include_path=\"C:/Data/Joep\" --include_path=\"C:/Data/Joep/src\" --include_path=\"C:/Data/Joep/3d-party/zwave/include\" --include_path=\"C:/ti/tirtos_tivac_2_16_01_14/products/TivaWare_C_Series-2.1.1.71b\" --include_path=\"C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31_custom_sysctlfix/packages/ti/sysbios/posix\" --include_path=\"C:/ti/tirtos_tivac_2_16_01_14/products/ndk_2_25_00_09/packages/ti/ndk/inc/bsd\" --include_path=\"C:/ti/ccs1040/ccs/tools/compiler/ti-cgt-arm_20.2.5.LTS/include\" --define=CONFIG_DEBUG --define=ccs=\"ccs\" --define=PART_TM4C1294NCPDT --define=ccs --define=TIVAWARE -g --gcc --diag_warning=225 --diag_warning=255 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi  " "../gateway2.cfg"
    subdir_rules.mk:19: recipe for target 'build-2085381327-inproc' failed
    js: "C:/ti/xdctools_3_32_01_22_core/packages/xdc/tools/Cmdr.xs", line 52: Error: xdc.tools.configuro: Error: Can't find the platform package 'ti.platforms.tiva'.  TI platforms are no longer shipped as part of XDCtools (C:\ti\xdctools_3_32_01_22_core).  Please ensure you are either using a pre-3.30 version of XDCtools or you have added a product that includes your platform support along the path 'C:/ti/tirtos_tivac_2_16_01_14/products/bios_6_45_02_31_custom_sysctlfix;C:/ti/tirtos_tivac_2_16_01_14/packages;C:/ti/tirtos_tivac_2_16_01_14/products/tidrivers_tivac_2_16_01_13/packages;C:/ti/tirtos_tivac_2_16_01_14/products/ndk_2_25_00_09/packages;C:/ti/tirtos_tivac_2_16_01_14/products/uia_2_00_05_50/packages;C:/ti/tirtos_tivac_2_16_01_14/products/ns_1_11_00_10/packages;C:/ti/ccs1040/ccs/ccs_base;C:\ti\xdctools_3_32_01_22_core/packages'.  Check that this path names a directory containing the necessary platform support and that the platform name is properly spelled.
    gmake[2]: *** [build-2085381327-inproc] Error 1
    gmake[1]: *** [build-2085381327] Error 2
    gmake[1]: Target 'main-build' not remade because of errors.
    gmake: *** [all] Error 2
    subdir_rules.mk:16: recipe for target 'build-2085381327' failed
    makefile:410: recipe for target 'all' failed

    • In addition to adding the directory to
    • I also change the directory in COM_TI_RTSC_TIRTOSTIVAC_REPOS

    Do you have an idea what causes this? 

  • If I use a copy of my bios folder (like you suggested) and then rebuild it I get a output error of which I can't get to find the cause for. 

    Hi Jordi,

      I'm a bit confused. It seems you were able to follow the steps I listed and rebuilt the library. How is this copy of your bios folder different than what you were successfully rebuilding?

    • In addition to adding the directory to

    The XDCtools show 3.32.1.22 version. Not sure it this is an issue. I will suggest you use only 3.32.0.6.

  • Hi Charles,

    Thanks for your quick reply. What works is if I don't make a copy of the current bios folder but keep the current one and only replace the Boot_sysctl.c file with the fix and rebuild that. If I then rebuild my project I can run my test program without any issues (and no crashes, that's how I know it solved my problem).

    But for distibution reasons I want to create a copy of the bios folder (in my example named it bios_6_45_02_31_custom_sysctlfix) and then rebuild it. but when I do that. I get the error mentioned in my previous post.
    And to clarify, I get an output error building my project (not building the bios itself, that still works)

    So somewhere in the settings or maybe even a hardcoded link there is reference to the original bios directory
    For example in C:\ti\tirtos_tivac_2_16_01_14\tirtos.mak

    line 66: BIOS_INSTALL_DIR          ?= $(TIRTOS_INSTALL_DIR)/products/bios_6_45_02_31

  • Hi Jordi,

      I'm not sure about the build error. I followed the instructions in the SYS/BIOS user's guide to rebuild the BIOS in the folder named  copy-bios_6_45_01_29. I know I'm using an slightly older version of TI-RTOS as well as XDCtools which is 3.32.0.06. Your error says 'Error: Can't find the platform package 'ti.platforms.tiva'.  TI platforms are no longer shipped as part of XDCtools (C:\ti\xdctools_3_32_01_22_core)'. I don't know if your XDCtools version is the reason for the build error. But I suppose you use the same XDCtools version when building the original bios directory, correct? 

  • Thanks again for your reply.
    It should be something specific to my project. I will continue investigating it.

    The important thing is that I know that it fixes my crash situation.

  • Hi Charles,

    I managed to build my project now

    I'm still not sure what caused the project build issue but what I did to make it work was downgraded to XDC tools version to 3.32.0.06  and changed the order (first update project settings then rebuild BIOS)

    1) Made a copy of the bios folder

    2) Open my project with code composer and in the settings

    C/C++ Build > Build Variables > (select 'Show system variables') > edit
    COM_TI_RTSC_TIRTOSTIVAC_REPOS > select the current bios/packages directory and changed it to the copy_bios/packages directory

    Note: I use the 'File System' option to change the dir but I had to manually alter it after since it was greyed out in my project tree under includes. I might think this caused the build issue but not 100% sure since I didn't build my project in between to verify

    3) Continue with the rebuild of the SYS/BIOS as described in your original post

    The only difference compared to your description was in the bios.mak I reversed the directories links (from C:\..) to C:/../.  I tried it with "C:\.." around the directories but that gave an build error (something like could not find the path)

    Thanks again much for the quick reply and clear instructions!

  • Hi Charles,

    Sorry to come back to this one more time. I noticed the following. The Boot_sysctl.c you shared with the patch does the job for my project. However it differs a bit from the errata code: found in here (https://www.ti.com/lit/er/spmz850g/spmz850g.pdf)

    For example the errata code has a bNewPLL boolean

    And also it gives a warning on the struct initializer (array exceeds)



    I understand this is specific for the bios part that uses the sys controller and like I said the version you provided works. But could this potentially be something that could cause error?

  • Hi Jordi,

     I reference the latest TivaWare 2.2.0.295 sysctl.c file for the SysCtlClockFreqSet function. 

    2804.sysctl.c