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: Error loading an initial image into erased flash using power on boot loader over SSI0.

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

I am using a tm4c1294ncpdt and attempting to load an initial image through SSI0 using the ROM boot loader after powering the card containing the processor. It fails because the DOWNLOAD command never returns ACK or NAK. Both the PING and GET STATUS commands work correctly. If I program an image into the MCU )using CCS IDE or J-Link) that calls ROM_UpdateSSI0() it works fine. 

I changed the DOWNLOAD command to an ILLEGAL command  and I got an ACK and the GET STATUS returned ILLEGAL COMMAND. I have changed the size and the address in the DOWNLOAD and neither changes the result. I sent a SEND DATA command without a DOWNLOAD command I and get an ACK with the GET STATUS of ILLEGAL ADDRESS.

  • I wired 2 EK-TM4C1294XL boards together using SSI0. The programming of an erased flash works with these two cards using the same software I am using on one of the cards to perform the programming and the host program on a Mac OS X 11.2.3 and Windows 10 connected to the first card with TCP on port 5000.

    The only significant differences between the the schematics for the EK and our custom board is the VBAT and WAKE (active low). We have both signals unconnected.

  • Hi Andrew,

      I'm not sure what is wrong that is not working when one of the boards is connected to the host PC vs. two boards are connected. You are saying when two LaunchPads are connected together then the host card will be able send command to the other card (with its flash erased) and get the ACK back? Is that a correct understanding? If that is the case then the MCU is behaving correctly. You might want to check the host PC that sends the command to the MCU. Is the host PC sending the command with the correct polarity and phase? If you change the baudrate, will it make a difference. Perhaps look at the SSI timing when the two cards are connected together and compare with your PC sending the command. Hopefully, you can find some difference that explains. 

    5.2.2 SSI Transport
    The SSI handling functions are SSISend(), SSIReceive(), and SSIFlush(). The connections
    required to use the SSI port are the following four pins: SSITx, SSIRx, SSIClk, and SSIFss.
    The device communicating with the boot loader is responsible for driving the SSIRx, SSIClk, and
    SSIFss pins, while the Tiva microcontroller drives the SSITx pin. The format used for SSI communications
    is the Motorola format with SPH set to 1 and SPO set to 1 (see Tiva Family data sheet
    for more information on this format). The SSI interface has a hardware requirement that limits the
    maximum rate of the SSI clock to be at most 1/12 the frequency of the microcontroller running the
    boot loader.

  • The Host Computer sends commands and data over a TCP connection to a card that is the master in my configuration. The SPI bus (SSI0) is configured for Motorola mode 3 (SPO=1, SPH=1) operating at 250 Kbps. The master MCU is used to communicate with the slave MCU (erased) to program it using the commands provided in the boot loader source code. If the device is already programmed then the master sends a command to have the slave call ROM_UpdateSSI(). If the device is not programmed the ROM boot loader should be scanning the available ports for a valid command. This is according to the documentation (Boot Loader User's Guide 2.2.0.295). As I stated above, if the slave is already programmed this process works. It is when the slave is not programmed that it does not. I used two EKs to mock up my design using the same software and performed the same functions. Both situations worked in the mock up with the EKs. 

    Why is no ACK or NAK sent back with the DOWNLOAD command (Address is always 0 and size is around 32 Kbytes)? The boot loader code has a definitive path through all of the options to send either an ACK or NAK. The only thing that looks like it could cause an issue is an unexpected interrupt but there is no way of knowing that from the master side. The PING command should cause the boot loader to use that interface even if other interfaces are present since it received a valid command through it.

    Why does calling ROM_UpdateSSI() work and not power on boot loading?

  • Hi,

      Thanks for the clarification.  However, I don't know where the problem is to be honest. So it looks like the two EK boards will work but not two of your custom boards, correct? I suppose what is not working is between the two custom boards. Can you please capture the DOWNLOAD command waveform between the two EK boards and compare with the custom boards? I want to know if the slave is not sending the ACK command or the master is having problem receiving the ACK. 

      Below is the snippet of code that implements the COMMAND_DOWNLOAD. Look for the Updater function that decodes the various commands.  Based on the code, it is supposed to send an ACK whether the command is valid or not. You can find the detail in the bl_main.c file for the flash based bootloader. The ROM bootloader should work the same. Perhaps, I will also suggest if you try the flash bootloader, will you still see the same problem on your custom boards. 

                //
                // This command indicates the start of a download sequence.
                //
                case COMMAND_DOWNLOAD:
                {
                    //
                    // Until determined otherwise, the command status is success.
                    //
                    g_ui8Status = COMMAND_RET_SUCCESS;
    
                    //
                    // A simple do/while(0) control loop to make error exits
                    // easier.
                    //
                    do
                    {
                        //
                        // See if a full packet was received.
                        //
                        if(ui32Size != 9)
                        {
                            //
                            // Indicate that an invalid command was received.
                            //
                            g_ui8Status = COMMAND_RET_INVALID_CMD;
    
                            //
                            // This packet has been handled.
                            //
                            break;
                        }
    
                        //
                        // Get the address and size from the command.
                        //
                        g_ui32TransferAddress = SwapWord(g_pui32DataBuffer[1]);
                        g_ui32TransferSize = SwapWord(g_pui32DataBuffer[2]);
    
                        //
                        // Depending upon the build options set, keep a copy of
                        // the original size and start address because we will need
                        // these later.
                        //
    #if (defined BL_PROGRESS_FN_HOOK) || (defined CHECK_CRC)
                        g_ui32ImageSize = g_ui32TransferSize;
    #endif
    #ifdef CHECK_CRC
                        g_ui32ImageAddress = g_ui32TransferAddress;
    #endif
    
                        //
                        // Check for a valid starting address and image size.
                        //
                        if(!BL_FLASH_AD_CHECK_FN_HOOK(g_ui32TransferAddress,
                                                      g_ui32TransferSize))
                        {
                            //
                            // Set the code to an error to indicate that the last
                            // command failed.  This informs the updater program
                            // that the download command failed.
                            //
                            g_ui8Status = COMMAND_RET_INVALID_ADR;
    
                            //
                            // This packet has been handled.
                            //
                            break;
                        }
    
    
                        //
                        // Only erase the space that we need if we are not
                        // protecting the code, otherwise erase the entire flash.
                        //
    #ifdef FLASH_CODE_PROTECTION
                        ui32FlashSize = BL_FLASH_SIZE_FN_HOOK();
    #ifdef FLASH_RSVD_SPACE
                        if((ui32FlashSize - FLASH_RSVD_SPACE) !=
                           g_ui32TransferAddress)
                        {
                            ui32FlashSize -= FLASH_RSVD_SPACE;
                        }
    #endif
    #else
                        ui32FlashSize = g_ui32TransferAddress + g_ui32TransferSize;
    #endif
    
                        //
                        // Clear the flash access interrupt.
                        //
                        BL_FLASH_CL_ERR_FN_HOOK();
    
                        //
                        // Leave the boot loader present until we start getting an
                        // image.
                        //
                        for(ui32Temp = g_ui32TransferAddress;
                            ui32Temp < ui32FlashSize; ui32Temp += FLASH_PAGE_SIZE)
                        {
                            //
                            // Erase this block.
                            //
                            BL_FLASH_ERASE_FN_HOOK(ui32Temp);
                        }
    
                        //
                        // Return an error if an access violation occurred.
                        //
                        if(BL_FLASH_ERROR_FN_HOOK())
                        {
                            g_ui8Status = COMMAND_RET_FLASH_FAIL;
                        }
                    }
                    while(0);
    
                    //
                    // See if the command was successful.
                    //
                    if(g_ui8Status != COMMAND_RET_SUCCESS)
                    {
                        //
                        // Setting g_ui32TransferSize to zero makes
                        // COMMAND_SEND_DATA fail to accept any data.
                        //
                        g_ui32TransferSize = 0;
                    }
    
                    //
                    // Acknowledge that this command was received correctly.  This
                    // does not indicate success, just that the command was
                    // received.
                    //
                    AckPacket();
    
                    //
                    // If we have a start notification hook function, call it
                    // now if everything is OK.
                    //
    #ifdef BL_START_FN_HOOK
                    if(g_ui32TransferSize)
                    {
                        BL_START_FN_HOOK();
                    }
    #endif
    
                    //
                    // Go back and wait for a new command.
                    //
                    break;
                }

  • Hi Andrew,

    The Host Computer sends commands and data over a TCP connection to a card that is the master in my configuration

    Just to clarify what is card referring to, e.g. your custom PCB? Please use the words EVM or launch pad to describe TI product. Perhaps host computer is swamping the transport on the master side, try reducing the link speed to 10 Megabit?

    Also if master has little to no ring buffer space can cause EMAC to post fault status bits. You can check DMARIS register via CCS debug continuous refresh.