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: Bootloader trouble on custom PCB with TM4C1294NCPDT

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

Hello everybody! I have a custom PBC with TM4C1294NCPDT. My client decided that we need an EMAC bootloader on this PCB. So, first I tried to do this on my EK-TM4C1294XL. Everything was fine, everything worked fine, but then I tried to download the same firmware to my PCB... And I ran into a problem. The LM Flash Programmer cannot find the TM4C1294NCPDT. Maybe because we didn't initially consider the bootloader and then decided to add it, we missed some jumpers or something like that? Could you help me figure this out? Thank you in advance

  • You have a new PCB with a blank TM4C1294CPDT part. You need to program your Ethernet bootloader. How are you trying to program the bootloader (which interface, JTAG, UART)? 

  • Via JTAG. If anything, JTAG works because I already downloaded other firmware through it and everything worked. Now the problem is that LM Flash Programmer does not see the bootloader loaded in the PCB

  • Can you run some of the Ethernet examples on your hardware to verify that the Ethernet interface hardware is correct?

  • Done Already. Everything works fine

  • There is nothing special in the hardware that is different for the Ethernet bootloader. I will check with my colleagues.

  • Charles had two comments. First, how did you choose the IP address in the LM flash programmer? You can first run other Ethernet examples and obtain a leased DHCP IP address. Use that IP address in LM for boot-loading.

    Second, there is a bug in LM flash programmer that it will send the magic packet to an incorrect NIC (Network Interface Card) if there are multiple of them on the PC. Please disable all network adapters in the Windows control panel except for the NIC interface you are using.

  • Greetings! I did as you said! It worked, it was possible to download the firmware via bootloader! But, after the first flashing, bootloader stops working. Most likely, bootloader and firmware overlap in some areas of memory (But I do not know how this is possible if I set the bootloader and firmware start address to 0x4000). What do you think might be the problem?

  • Using UniFlash, I collected memory dumps. One, while only bootloader is loaded, and the second, when the firmware is loaded via bootloader. There are no intersections in the memory. So the problem is something else. The question is, what? Let me remind you that this problem was not observed on the EK-TM4C1294XL. Can we definitely rule out a hardware problem?

  • Once you have used the bootloader to load the application code (first time) can you connect the debugger by JTAG and set a hardware breakpoint back in the bootloader. Then verify that the application is properly transferring control back to the bootloader.

    I don't think it is likely a hardware problem, but it is best to understand this issue so we can be sure.

  • I don't understand where I should put a breakpoint to see if the firmware passes control to bootloader. Can you tell me?

  • I made a big mistake. I was flashing the EK-TM4C1294XL over USB, not Ethernet. It doesn't work over Ethernet. Can you tell me how to flash EK-TM4C1294XL via Ethernet step by step?

  • Hi,

    Below are the steps you need to take.

    1. Program the TivaWare example such as enet_lwip into the MCU flash via the JTAG interface using CCS or LM flash programmer. 

    2. Run the enet_lwip and you should see the IP addressed printed out on the terminal window. You need to record this IP address. This IP address is dynamically generated by the DHCP server. This IP address needs to be used later when you run the emac_boot_flash example. The reason is that the PC running the LM flash programmer is also a BootP server as well as the TFTP server. The BootP server is static in nature. You need to manually associate a client's IP address with the client's MAC address in a fixed table in the BootP server.  Note the only purpose to run the enet_lwip is to obtain an IP address. Once the dynamic address is acquired it is leased to you on your network for some hours. You might be able to configure your router to lease an IP address indefinitely. Check with your IT department. 

    3. Program the emac_boot_flash into the MCU's flash via the JTAG interface. You can use the CCS or LM flash programmer to load the code. Note the emac_boot_flash starts at 0x0.

    4. Run the emac_boot_flash bootloader. The emac_boot_flash is supposed to send the BootP request now. However, since you have not yet launched the BootP server the client will just keep sending the request. If you have a wireshark you should see the BootP requests at 1s, 2s, 4s, 8s and so on. Therefore, you may need to wait a while before the server receives the request and responds to the request. Don't just wait a short second and think it is not working or broken. Bring up the wireshark to observe the trace. This is extremely useful. 

    5. Open the LM flash programmer. See below. Enter the IP address that you just acquired from running the enet_lwip into the Client IP address field. Next enter the MAC address of your client. If you are using the LaunchPad you should see the MAC address on the sticker at the back of the board. What you are doing here is more like manually updating the BootP server's table of IP address and MAC address association. Note the below capture shows my IP address and MAC address. Yours will be entirely different than mine. 

    6. Go to the Program tab and specify the boot_demo_emac_flash.bin as your application program image and hit the Program button. See below. 

    7. Give some time and you should see the download happening via the Ethernet. 

    8. Make sure your PC and the LaunchPad are in the same subnet if you wait a long time and nothing happens. If this is the case, show your wireshark capture.

  • Thank you very much! I did everything step by step and 1 time I will be able to download a new firmware! But the problem remained the same, after 1 boot, bootloader can't get control. What should I write in the code to pass control to bootloader?

  • The boot_demo_emac_flash (the application firmware example) is designed to jump back to the bootloader when the SW1 is pressed on the LaunchPad? Did you press the SW1? Please refer to the source code (boot_demo_emac_flash.c file).

  • Yes, boot_demo_emac is flashed as many times as I want, even if I don't press SW1. I would venture to assume that the code on line 324 in the boot_demo_emac_flash file is responsible for passing control to bootloader. c:

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

    Am I right?

  • Glad that it is working for you now. Please confirm. When you press the "Program" button on the LM flash programmrer, it sends a magic packet to the client. The client will then set the g_bFirmwareUpdate flag in the SoftwareUpdateRequestCallback(). Once g_bFirmwareUpdate  is set, the application will call SoftwareUpdateBegin. The SoftwareUpdateBegin will eventually return the control to the bootloader by making a SVC call. 

  • Yep. Everything is exactly as you say

  • An attempt to integrate the SoftwareUpdateBegin function call into my firmware was unsuccessful. I added a call to the SoftwareUpdateInit function after initializing the Ip stack, and in the Callback function I made a call to SoftwareUpdateBegin. Compile failed because the compiler does not want to compile the swupdate file, although the path to the folder where the utils folder is located is specified to the linker. Error - "Unresolved Symbol SoftwareUpdatreBegin, first referenced in...", although if you click on the SoftwareUpdateInit function LMB+Ctrl, the swupdate file will open. What could be wrong?

  • in the Callback function I made a call to SoftwareUpdateBegin

    SoftwareUpdateBegin() cannot be called from within an interrupt routine. (The callback function is still in the interrupt routine.) Follow the example in boot_demo_emac_flash. Set a global flag in SoftwareUpdateRequestCallback() and then check the flag in your main loop. Call SoftwareUpdateBegin() when the flag is set. There is an important note on lines 177-180 of boot_demo_emac_flash.c:

    //*****************************************************************************
    //
    // This function is called by the software update module whenever a remote
    // host requests to update the firmware on this board.  We set a flag that
    // will cause the main loop to exit and transfer control to the bootloader.
    //
    // IMPORTANT:
    // Note that this callback is made in interrupt context and, since it is not
    // permitted to transfer control to the boot loader from within an interrupt,
    // we can't just call SoftwareUpdateBegin() here.
    //
    //*****************************************************************************
    void SoftwareUpdateRequestCallback(void)
    {
        g_bFirmwareUpdate = true;
    }
    

    Compile failed because the compiler does not want to compile the swupdate file, although the path to the folder where the utils folder is located is specified to the linker.

    I suggest that you again follow the example of boot_cemo_emac_flash and copy links to lwiplib.c, swupdate.c and ustlib.c into your project. This will cause the compiler to compile those files and put a copy of the object in the "Debug" directory where the linker will find it.

  • I was able to compile and try to run my firmware. I called SoftwareUpdateInit (I used my void(void) function as an argument), I set a flag in this function, and checked its status by a timer. When the flag was cocked, I called the SoftwareUpdateBegin function. As a result, my firmware does not want to work, and due to the fact that I downloaded it via bootloader, I can not even debug everything properly and see why control is not transferred to bootloader

  • You can debug a program that was loaded by a bootloader. Connect the JTAG connector to the board and launch the target configuration. 

    "View" -> "Target Configurations"

    Then expand the projects and find the target configuration for your project. Right click and then select "Launch Selected Configuration" 

    Then select "Run" -> "Connect Target", this will stop the code from executing.

    Then select "Run" -> "Load" -> "Load Symbols", and select the .out file that was used to make your .bin file. This will load the debug information without erasing or programming the flash. 

    Now you can debug as you normally would.

  • Thanks! My firmware crashes on line 291 of the swupdate.c (udp_recv) file. As I understood from the description of the SoftwareUpdateInit function, I have to initialize the lwip stack. How do I do this if I use RTOS? And if this is not possible, then how do I transfer control to bootloader? Catch the magic package by myself and call SoftwareUpdateBegin?

  • I was able to get my firmware to pass control to bootloader. Everything works perfectly! Now there is one small question: can I somehow set a static ip address for bootloader? Because having to work with DHCP is not something I can afford when doing field work

  • Hi,

      You have been using static IP address. Please go back to step 2 in my prior answer. I was asking you to first run enet_lwip example so you can find out which IP address is available on your network so you can use that IP address for your client on the LM flash programmer. If you check with your IT admin or if you could login to your router and find out what IP address is available, then you could have just entered the static IP address into LM flash programmer without first to run the enet_lwip at all. 

      As part of the BootP protocol, the client which is the MCU will find out its IP address from the BootP server. See below code in bl_emac.c file. 

    //*****************************************************************************
    //
    //! Parses a packet checking for a BOOTP reply message.
    //!
    //! This function parses a packet to determine if it is a BOOTP reply to our
    //! currently outstanding BOOTP request. If a valid reply is found, the
    //! appropriate information from the packet is extracted and saved.
    //!
    //! \return Returns 1 if a valid BOOTP reply message was found and 0 otherwise.
    //
    //*****************************************************************************
    static uint32_t
    ParseBOOTPReply(void)
    {
    tBOOTPPacket *psBOOTP = (tBOOTPPacket *)uip_appdata;
    uint32_t ui32Idx;

    //
    // See if this is a reply for our current BOOTP request.
    //
    if((psBOOTP->ui8Op != BOOTP_REPLY) ||
    (psBOOTP->ui32XID != g_ui32XID) ||
    (*(uint32_t *)psBOOTP->pui8CHAddr != *(uint32_t *)g_sMACAddr.addr) ||
    (*(uint16_t *)(psBOOTP->pui8CHAddr + 4) !=
    *(uint16_t *)(g_sMACAddr.addr + 4)))
    {
    return(0);
    }

    //
    // Extract our IP address from the response.
    //
    *((uint32_t *)(void *)(&uip_hostaddr)) = psBOOTP->ui32YIAddr;

    //
    // Extract the server address from the response.
    //
    *((uint32_t *)(void *)(&g_sServerAddr)) = psBOOTP->ui32SIAddr;

    //
    // Save the boot file name.
    //
    for(ui32Idx = 0;
    ((g_pcFilename[ui32Idx] = psBOOTP->pcFile[ui32Idx]) != 0) &&
    (ui32Idx < (sizeof(g_pcFilename) - 1));
    ui32Idx++)
    {
    }
    g_pcFilename[ui32Idx] = 0;

  • Thanks! So it all depends on what MAC address I enter in the LM Flash Programmer? Changing the values of ENET_MAC_ADDR0 - ENET_MAC_ADDR5 in the bl_config file.h did not give the desired result, because the bootloader did not respond to magic packets from the Lm Flash Programmer at any of the MAC addresses (neither to the one written on the board, nor to the one I specified in bl_config. h). How can I change the MAC address?

  • the bootloader did not respond to magic packets from the Lm Flash Programmer at any of the MAC addresses (neither to the one written on the board, nor to the one I specified in bl_config. h). How can I change the MAC address?

    I'm confused. I thought you just got everything working. The EK-TM4C1294XL LaunchPad is pre-programmed with a MAC address. Look at bl_emac.c file below. If there is already a MAC address stored in the flash memory then it will just use that one. If you want to reprogram with a new MAC address to the flash you need to do a mass-erase of the MCU first. See below image. First do a "Unlock" and that will completely wipe out the NVM memory in the chip. After the chip is mass-erased to factory setting, you can program a new MAC address at the upper right. There is no need to to erase the MAC address in the LaunchPad. If you want to experiment it, it is your choice. For your custom board, you must have a valid MAC address if it is not there. 

    //
    // Get the MAC address from the flash user registers. If it has not been
    // programmed, then use the boot loader default MAC address.
    //
    ROM_FlashUserGet(&ui32User0, &ui32User1);
    if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
    {
    //
    // MAC address has not been programmed, use default.
    //
    g_sMACAddr.addr[0] = 0x00;
    g_sMACAddr.addr[1] = 0x1a;
    g_sMACAddr.addr[2] = 0xb6;
    g_sMACAddr.addr[3] = 0x00;
    g_sMACAddr.addr[4] = 0x64;
    g_sMACAddr.addr[5] = 0x00;
    }
    else
    {
    g_sMACAddr.addr[0] = ui32User0 & 0xff;
    g_sMACAddr.addr[1] = (ui32User0 >> 8) & 0xff;
    g_sMACAddr.addr[2] = (ui32User0 >> 16) & 0xff;
    g_sMACAddr.addr[3] = ui32User1 & 0xff;
    g_sMACAddr.addr[4] = (ui32User1 >> 8) & 0xff;
    g_sMACAddr.addr[5] = (ui32User1 >> 16) & 0xff;
    }

  • Thank you so much, Bob and Chrales! Everything worked out! In case someone in the future will have similar problems with me-here is a quick guide:
    1) Import the boot_emac_flash project via Resource Explorer Classic
    2) In the bl_config file.h find lines 884-889 and uncomment them
    3) Set the required MAC address in them (then you will need to write this MAC address in the LM Flash Programmer)
    4) In the bl_emac.c file, comment out the lines from 1512 to 1533 and write under them

    g_sMACAddr.addr[0] = ENET_MAC_ADDR0;
    g_sMACAddr.addr[1] = ENET_MAC_ADDR1;
    g_sMACAddr.addr[2] = ENET_MAC_ADDR2;
    g_sMACAddr.addr[3] = ENET_MAC_ADDR3;
    g_sMACAddr.addr[4] = ENET_MAC_ADDR4;
    g_sMACAddr.addr[5] = ENET_MAC_ADDR5;

    5) Download boot_emac_flash to your device via CCS
    6) In your main project, add some condition (for example, receiving a special UDP packet), by which you will call the 
    SoftwareUpdateBegin(g_ui32SysClockFreq)
     function. 
    g_ui32SysClockFreq
     must be declared in the code as follows: 
    volatile uint32_t g_ui32SysClockFreq

    7) Of course, do not forget to connect .h file with the SoftwareUpdateBegin function. #include "utils/swupdate.h"
    8) Import the boot_demo_emac_flash project via Resource Explorer Classic
    9) From this project, copy the swupdate.c file to your main project
    10) Configure the creation .bin from your main project: Link to e2e forum
    11) In the .cmd file of your main project on the 13th line, replace the values with 0x00004000 and 0x000FC000
    12) Open the. cfg file of your main project via HGCONF
    13) In the upper left corner, click the arrow XDCtools->System->Programm - >View - >sectMap ->. resetVecs->loadAddress and write the value 0x00004000 there
    14) Compile your main project. If there are problems with the linker, then connect the necessary directories to your main project
    15) Run LM Flash Programmer
    16) In the Configuration->Quick Set column, set Manual Configuration
    17) In the Interface column, set Ethernet
    18) Enter the MAC address you entered in step 3
    19) Enter the ip address that LM Flash Programmer will assign to the device
    20) Make sure that you have disabled all network adapters except the one that is connected to your device
    21) In the Programm column, select .bin file of your main project
    21) Click Programm
    22) After a few seconds, you will see the process of downloading the firmware to the device
    23) To re-download the firmware, you need to fulfill the condition of calling the SoftwareUpdateBegin function
    Thanks again to Bob and Chrales!

  • The joy was premature. Everything works on EK-TM4C1294XL, but on my PCB bootloader does not want to work. Moreover, the problem is curious: I started bootloader through the debugger, clicked the "Programm" button in LM Flash Programmer and UDP sniffer. LM Flash Programmer sends packets 72 bytes long, and bootloader catches packets 76 bytes long (Although the contents of the packet are correct. Checked in the uip_buf variable). As a result, the bootloader is constantly spinning in a loop that starts on line 1783 (if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus & DES0_RX_CTRL_OWN))). What could be the problem?

  • Hi,

      Really don't know what went wrong when you said it is fully working on the LaunchPad. Are you sure it is exactly the same bootloader and application firmware that are running on the custom board?

      I will suggest you check a few things.

      - Do you have the 25Mhz OSCIN on the custom board?

      - Do you have the MAC address programmed on your custom board? For experiment, why don't you program the same MAC address for the LaunchPad on your custom board? Does it make a difference?

      - If you start your custom board MCU with only the bootloader and no application, will it bootload at least once? I just wanted to know if it will bootload once. Or Is it only that the subsequent "Program" from the LM flash Programmer fails?

      - On the wireshark, where is the difference between the LaunchPad and your custom board?

  • Yes, I downloaded the same bootloader from the same computer on LaunchPad and PCB. I did not change the bootloader itself between downloads to the devices.

    - Yes, the PCB is 25MHz OSCIN.

    -In my answer above, I described how I set the MAC address and in sniffer I see that LaunchPad actually uses this MAC address.

    - While the LaunchPad is flashed as many times as you want, the PCB (after pressing Programm) does not show any signs of life, and the LM Flash Programmer hangs indefinitely in the state of Attempting to connect.

    - In sniffer, the difference between LaunchPad and PCB is visible - the latter does not give an answer to port 67.

  • Hi,

      Did you resolve the problem? Did you make sure there is only one NIC on your PC? How long did you wait to claim that it is not working. The reason I asked is because the client does not send BootP request periodically but rather in increasing duration to avoid jamming the network. If you look at the below capture the client sends BootP request the first time and if it didn't receive a response from the server, it will wait for 1 second before sending the next request. If it still doesn't receive response then it will wait 2 seconds before sending the next request. As you can see, it will wait 1s, 2s, 4s, 8s, 16s, 32s and 64s before sending the BootP request. If you happen to press the "Program" button when the client just send its request, the server may need to wait up to 64 seconds before the client sends its next request. You may think that it is not working but if you wait long enough (longer than 64 seconds) it should come through. 

  • Hi, nope i didn't. Yep, i have the one and only NIC (i checked output packets in Wireshark). I waited for 30 mins, so i don't think this is why bootloader didn't work on my PCB. I guess, problem is hardware. This is the one and only difference between my PCB and Launchpad (which bootloader works properly)

  • Does the custom board still work for other Ethernet examples? 

    Can you share your schematic at least for the Ethernet portion?

    Can you share the wireshark captures for running on the LaunchPad and custom  boards?

  • 1) Yes, still work
    2)
    3) I'll share it later

  • Looking at the schematic, we don't see the isolation transformer or the protection diodes. Are they integrated in the RJ45 connector? Still does not explain why other applications work and but the bootloader does not. Let us know when you have the wireshark captures.