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: TFTP communication failed

Part Number: TM4C1294NCPDT

I tried to implement a TFTP protocol in the EK-TM4C1294NCPDT board, using the files tftp.c and tftp.h contained in the utils folder on TivaWare 2.1.3.156. I want to read the value of specific memory position in the flash via TFTP.

As there are not examples of this protocol for my board, I use the enet_io example and I modifying for add a TFTP protocol implementation. I initialize the TFTP using TFTPInit function, as it is in the code below:

int
main(void)
{
    uint32_t ui32User0, ui32User1;
    uint8_t pui8MACArray[8];

    //
    // Make sure the main oscillator is enabled because this is required by
    // the PHY.  The system must have a 25MHz crystal attached to the OSC
    // pins.  The SYSCTL_MOSC_HIGHFREQ parameter is used when the crystal
    // frequency is 10MHz or higher.
    //
    SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ);

    //
    // Run from the PLL at 120 MHz.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_480), 120000000);

    //
    // Configure the device pins.
    //
    PinoutSet(true, false);

    //
    // Configure debug port for internal use.
    //
    UARTStdioConfig(0, 115200, g_ui32SysClock);

    //
    // Clear the terminal and print a banner.
    //
    UARTprintf("\033[2J\033[H");
    UARTprintf("Ethernet IO Example\n\n");

    //
    // Configure SysTick for a periodic interrupt.
    //
    MAP_SysTickPeriodSet(g_ui32SysClock / SYSTICKHZ);
    MAP_SysTickEnable();
    MAP_SysTickIntEnable();

    //
    // Configure the hardware MAC address for Ethernet Controller filtering of
    // incoming packets.  The MAC address will be stored in the non-volatile
    // USER0 and USER1 registers.
    //
    MAP_FlashUserGet(&ui32User0, &ui32User1);
    if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
    {
        //
        // Let the user know there is no MAC address
        //
        UARTprintf("No MAC programmed!\n");

        while(1)
        {
        }
    }

    //
    // Tell the user what we are doing just now.
    //
    UARTprintf("Waiting for IP.\n");

    //
    // Convert the 24/24 split MAC address from NV ram into a 32/16 split
    // MAC address needed to program the hardware registers, then program
    // the MAC address into the Ethernet Controller registers.
    //
    pui8MACArray[0] = ((ui32User0 >>  0) & 0xff);
    pui8MACArray[1] = ((ui32User0 >>  8) & 0xff);
    pui8MACArray[2] = ((ui32User0 >> 16) & 0xff);
    pui8MACArray[3] = ((ui32User1 >>  0) & 0xff);
    pui8MACArray[4] = ((ui32User1 >>  8) & 0xff);
    pui8MACArray[5] = ((ui32User1 >> 16) & 0xff);

    //
    // Initialze the lwIP library, using DHCP.
    //
    lwIPInit(g_ui32SysClock, pui8MACArray, 0, 0, 0, IPADDR_USE_DHCP);
//    lwIPInit(g_ui32SysClock, pui8MACArray, 2887557220, 4294934528, 2887526654, IPADDR_USE_STATIC);

    //
    // Setup the device locator service.
    //
    LocatorInit();
    LocatorMACAddrSet(pui8MACArray);
    LocatorAppTitleSet("EK-TM4C1294XL enet_io");

    uint32_t i;
    for(i = 0; i < 99; i++) {
        buffer[i] = 'a';
    }
    buffer[99] = '\0';

    //
    // Initialize a sample httpd server.
    //
    httpd_init();
    TFTPInit(okToContinue);

    //
    // Set the interrupt priorities.  We set the SysTick interrupt to a higher
    // priority than the Ethernet interrupt to ensure that the file system
    // tick is processed if SysTick occurs while the Ethernet handler is being
    // processed.  This is very likely since all the TCP/IP and HTTP work is
    // done in the context of the Ethernet interrupt.
    //
    MAP_IntPrioritySet(INT_EMAC0, ETHERNET_INT_PRIORITY);
    MAP_IntPrioritySet(FAULT_SYSTICK, SYSTICK_INT_PRIORITY);

    //
    // Pass our tag information to the HTTP server.
    //
    http_set_ssi_handler((tSSIHandler)SSIHandler, g_pcConfigSSITags,
            NUM_CONFIG_SSI_TAGS);

    //
    // Pass our CGI handlers to the HTTP server.
    //
    http_set_cgi_handlers(g_psConfigCGIURIs, NUM_CONFIG_CGI_URIS);

    //
    // Initialize IO controls
    //
    io_init();

    //
    // Loop forever, processing the on-screen animation.  All other work is
    // done in the interrupt handlers.
    //
    while(1)
    {
        //
        // Wait for a new tick to occur.
        //
        while(!g_ulFlags)
        {
            //
            // Do nothing.
            //
        }

        //
        // Clear the flag now that we have seen it.
        //
        HWREGBITW(&g_ulFlags, FLAG_TICK) = 0;

        //
        // Toggle the GPIO
        //
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1,
                (MAP_GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1) ^
                 GPIO_PIN_1));
    }
}

I created the callback functions, but now I implemented only the TFTPInit and pfnGetData Callback.

tTFTPError getDataFromTFTP(struct _tTFTPConnection *psTFTP){

    unsigned long ulOffset;

    UARTprintf("Get block %d, %d\n", psTFTP->ui32BlockNum, psTFTP->ui32DataLength);

    //
    // Where does this block of data get read from?  This is calculated from
    // the requested TFTP block number.
    //
    ulOffset = ((psTFTP->ui32BlockNum - 1) * TFTP_BLOCK_SIZE);

    //
    // Copy the data into the supplied buffer.
    //
    memcpy(psTFTP->pui8Data, (unsigned char *)(buffer + ulOffset),
           psTFTP->ui32DataLength);

    //
    // Tell the caller everything went fine.
    //
    return(TFTP_OK);
}

tTFTPError putDataFromTFTP(struct _tTFTPConnection *psTFTP){

    return TFTP_OK;
}

void closeTFTP(struct _tTFTPConnection *psTFTP){
}

tTFTPError okToContinue(struct _tTFTPConnection *psTFTP, bool bGet,
                        int8_t *pui8FileName, tTFTPMode eMode){

    psTFTP->pfnClose = closeTFTP;

    //
    // Is this a GET or PUT request?
    //
    if(bGet)
    {
        //
        // GET request - fill in the image size and the data transfer
        // function pointer.
        //
        psTFTP->pfnGetData = getDataFromTFTP;
        psTFTP->ui32DataRemaining = 100;
    }
    else
    {
        //
        // PUT request - fill in the data transfer function pointer.
        //
        psTFTP->pfnPutData = putDataFromTFTP;
    }

    return TFTP_OK;
}

The board got the IP adress and the http server worked perfectly. But when I use a native TFTP client in the windows, the TFTPRecv function and the pfnGetData callback function is called. But the TFTPRecv function is called , when the TFTPDataRecv function should be called, and occurs the Fault_ISR when udp_recv in the line 618 is called again.

Why the function TFTPDataRecv is never called?