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.

TM4C1294NCPDT: Hardware solution to prevent accidental programming?

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: CC1350, UNIFLASH

As someone who has accidentally misprogrammed a TM4C1294NCPDT myself I can see it being an issue for some of our customers.

Is there some sort of hardware pin solution that can prevent flash programming but still allow USB/JTAG operation? I've begun to look through the datasheet but haven't found anything so far.

I suppose a software solution could also be useful as well if anyone is aware of one. 

  • How did they accidentally program the flash w/o using JTAG? That would appear to take some effort.

    Robert
  • Perhaps I explained the situation poorly but that's not the case here. Using various programming tools I had accidentally programmed the TM4C1294NCPDT with an image that was built for a connected CC1350. Neither JTAG or USB signals were ever disconnected. I was able to recover the bricked TM4C1294NCPDT but was hoping to find a mechanism to help prevent situations like this for customers.

    The problem is that tools like xdsdfu and uniflash don't appear to have any sanity checks on binaries they program to the flash. For instance, if there was a pin you could connect a jumper to that prevents flash writes we could save ourselves from some potential user error.
  • Robert Jones8 said:
    ...as one who has accidentally misprogrammed a TM4C1294NCPDT ... can see it being an issue for ... some customers.

    We must ask - are there "valid" (and keenly thought/considered) reasons - for giving (some) clients - the (potential) "keys (i.e. JTAG/SWD access) to your kingdom?"     Such is key/critical - is it not?

    Whenever one "attaches to JTAG/SWD" there exists the possibility (either deliberate or via accident) for, "Disturbance to existing code to occur."    

    Thus - is not "Step ONE" the limiting of such access?

    There exists a (past) small program (jtag-gpio.c) or similar - which enabled/disabled JTAG/SWD functionality - via the "toggle or level" impressed upon a single (non-JTAG) GPIO.    (additional safeguards may be added)    If this code is placed (among) the first to be executed - and "defaults" to, "Switch JTAG/SWD pins to GPIO" you have "reasonable" protection against such undesired/inadvertent, "Unwanted MCU Program Alteration."

  • Our product using this device does not include any proprietary software. In this case we are mainly selling to developers who we expect will need to replace/modify the existing code. The only concern we have is support issues/RMA's involved with said customers bricking their TM4C1294NCPDT's on accident. It is a problem we are willing to deal with but wanted to explore any options available to us.

    This jtag-gpio sounds like a potential software solution. Where can I find the source?
  • Your guess - as good as mine. I have "forever" squawked re: "Vendors LACK of "clear-cut" links to key/critical tech data!" Ideally - such would be placed w/in the Forum's Top of the page - Red Striped area - devoted (mistakenly) to "Blogs, Videos, Groups" - but ZERO to "VITAL TECH DATA!"

    If you make (some) effort (use the Forum Search Box - up top) - I'll dig the program up from the past (when under LMI) all code (granted it was smaller then) was centrally located - and SO MUCH EASIER to DIRECTLY FIND!

    IMPEDING USER-CLIENT'S FINDING - EVEN NOTING - KEY/CRITICAL TECH DATA IS "IMPOSSIBLE TO UNDERSTAND" (almost as bad as vendor's banning of 'LIKE" (for valuable posts) and "KISS" (for every design requirement)...
  • Here now - the promised code file:

    Note that this is a very simple program - iirc "switch bounce" was not managed - and you (surely) do not have to employ the OLED display referenced w/in this code.

    The code DOES succeed in providing you (and others) the means to selectively "gate" the "IMPACT" of signals arriving upon the JTAG/SWD Pins - such that "JTAG/SWD Mode" must be (deliberately) selected.    (this may or may not be the "default" of this program - yet is easily changed/reversed.    My firm uses a modernized version of this - defaulting into SWD Mode (while we are developing) - and switched to "Non-SWD Mode" when development completes...

    //*****************************************************************************
    //
    // gpio_jtag.c - Example to demonstrate recovering the JTAG interface.
    //
    // Copyright (c) 2006-2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 9453 of the EK-LM3S1968 Firmware Package.
    //
    //*****************************************************************************
    
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "drivers/rit128x96x4.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>GPIO JTAG Recovery (gpio_jtag)</h1>
    //!
    //! This example demonstrates changing the JTAG pins into GPIOs, along with a
    //! mechanism to revert them to JTAG pins.  When first run, the pins remain in
    //! JTAG mode.  Pressing the select push button will toggle the pins between
    //! JTAG mode and GPIO mode.  Because there is no debouncing of the push button
    //! (either in hardware or software), a button press will occasionally result
    //! in more than one mode change.
    //!
    //! In this example, all five pins (PB7, PC0, PC1, PC2, and PC3) are switched,
    //! though the more typical use would be to change PB7 into a GPIO.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The current mode of pins PB7, PC0, PC1, PC2, and PC3.  When zero, the pins
    // are in JTAG mode; when non-zero, the pins are in GPIO mode.
    //
    //*****************************************************************************
    volatile unsigned long g_ulMode;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // The interrupt handler for the PG7 pin interrupt.  When triggered, this will
    // toggle the JTAG pins between JTAG and GPIO mode.
    //
    //*****************************************************************************
    void
    GPIOGIntHandler(void)
    {
        //
        // Clear the GPIO interrupt.
        //
        GPIOPinIntClear(GPIO_PORTG_BASE, GPIO_PIN_7);
    
        //
        // Toggle the pin mode.
        //
        g_ulMode ^= 1;
    
        //
        // See if the pins should be in JTAG or GPIO mode.
        //
        if(g_ulMode == 0)
        {
            //
            // Change PB7 and PC0-3 into hardware (i.e. JTAG) pins.
            //
            HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0x80;
            HWREG(GPIO_PORTB_BASE + GPIO_O_AFSEL) |= 0x80;
            HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0x00;
            HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = 0;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x01;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) |= 0x01;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x02;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) |= 0x02;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x04;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) |= 0x04;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x08;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) |= 0x08;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x00;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = 0;
            HWREG(GPIO_PORTB_BASE + GPIO_O_DEN) |= 0x80;
            HWREG(GPIO_PORTC_BASE + GPIO_O_DEN) |= 0x0f;
        }
        else
        {
            //
            // Change PB7 and PC0-3 into GPIO inputs.
            //
            HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0x80;
            HWREG(GPIO_PORTB_BASE + GPIO_O_AFSEL) &= ~0x7f;
            HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTB_BASE + GPIO_O_CR) = 0x00;
            HWREG(GPIO_PORTB_BASE + GPIO_O_LOCK) = 0;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x01;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) &= ~0xfe;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x02;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) &= 0xfd;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x04;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) &= 0xfb;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x08;
            HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) &= 0xf7;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x00;
            HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = 0;
            HWREG(GPIO_PORTB_BASE + GPIO_O_DEN) &= ~0x80;
            HWREG(GPIO_PORTC_BASE + GPIO_O_DEN) &= ~0x0f;
            GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_7);
            GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, (GPIO_PIN_0 | GPIO_PIN_1 |
                                                   GPIO_PIN_2 | GPIO_PIN_3));
        }
    }
    
    //*****************************************************************************
    //
    // Toggle the JTAG pins between JTAG and GPIO mode with a push button selecting
    // between the two.
    //
    //*****************************************************************************
    int
    main(void)
    {
        unsigned long ulMode;
    
        //
        // Set the clocking to run directly from the crystal.
        //
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_8MHZ);
    
        //
        // Enable the peripherals used by this application.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    
        //
        // Configure the push button as an input and enable the pin to interrupt on
        // the falling edge (i.e. when the push button is pressed).
        //
        GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_7);
        GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA,
                         GPIO_PIN_TYPE_STD_WPU);
        GPIOIntTypeSet(GPIO_PORTG_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);
        GPIOPinIntEnable(GPIO_PORTG_BASE, GPIO_PIN_7);
        IntEnable(INT_GPIOG);
    
        //
        // Set the global and local indicator of pin mode to zero, meaning JTAG.
        //
        g_ulMode = 0;
        ulMode = 0;
    
        //
        // Initialize the OLED display.
        //
        RIT128x96x4Init(1000000);
        RIT128x96x4StringDraw("PB7/PC0-3 are", 30, 16, 15);
        RIT128x96x4StringDraw("JTAG", 48, 32, 15);
    
        //
        // Loop forever.  This loop simply exists to display on the OLED display
        // the current state of PB7/PC0-3; the handling of changing the JTAG pins
        // to and from GPIO mode is done in GPIO Interrupt Handler.
        //
        while(1)
        {
            //
            // Wait until the pin mode changes.
            //
            while(g_ulMode == ulMode)
            {
            }
    
            //
            // Save the new mode locally so that a subsequent pin mode change can
            // be detected.
            //
            ulMode = g_ulMode;
    
            //
            // See what the new pin mode was changed to.
            //
            if(ulMode == 0)
            {
                //
                // Indicate that PB7 and PC0-3 are currently JTAG pins.
                //
                RIT128x96x4StringDraw("JTAG", 48, 32, 15);
            }
            else
            {
                //
                // Indicate that PB7 and PC0-3 are currently GPIO pins.
                //
                RIT128x96x4StringDraw("GPIO", 48, 32, 15);
            }
        }
    }
    

  • Hi Robert,
    You can find the example in <Tiva_Installation>\examples\boards\ek-tmsc1294xl\gpio_jtag.
  • Robert Jones8 said:
    The problem is that tools like xdsdfu and uniflash don't appear to have any sanity checks on binaries they program to the flash.

    Such a sanity check may be impossible. It's certainly not easy since you are downloading a binary containing arbitrary sequences.

    Robert Jones8 said:
    For instance, if there was a pin you could connect a jumper to that prevents flash writes we could save ourselves from some potential user error.

    Route the JTAG clock through a jumper? You could potentially route it through a double pole switch and if it was in the JTAG enabled position refuse to run code so they couldn't accidentally leave it in the program position.

    Robert

  • This doesn't prevent the user from downloading an arbitrary binary though which seems to have been the original problem. To do that you are going to need a bootloader

    Robert
  • Or - more directly - the example appears @ cb1 post 14:22 CST. (4 minutes prior to your posting).    

    Added (by cb1) were "instructions" too (such as "No debounce") should a simple switch be employed to "access/switch JTAG in/out..."

    Note too - NOT ALL HERE - have interest in - nor employ "4C1294" - thus the (actual) example code proves advantaged...    (i.e. "KISS" once more arrives - to: "Speed, Ease, Simplify")