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.

essage enet_lwip project on ek-tm4c1294xl board

Other Parts Discussed in Thread: EK-TM4C1294XL

Hi fellows, good afeternoon, today I'm writting because I found a message at the websites I'm working at, based on the enet_lwip example in the ek-tm4c1294xl board.
 This issue sometimes apppears sometimes not, in fact if I refresh the website several times sooner or later it goes away. It is very problematic because it beaks the website down, and the JavaScript function linked stop working, the CSS styles also changes.

 The error is the one blue circuled. I will be grateful if someone can tell me what's going on with this issue. 

I also have several warning whan I compile the project, and one of these:

When I search for updates in the help menu, it notifyis me there anot updates availables, I was thinking perhaps it could be related with the error message found.

Thanks in advanced, Regards

Martin c!

  • Hello Martin,

    The error is not related to the compiler version. The compiler version used to create the project was an older version that your current compiler version being used and it cannot be updated "backwards".

    1. Anyhow did you change the browser?
    2. If you run the original project does it give the same error?

    Regards
    Amit
  • Hello Amit! no, I don't change the browser and I don't have this mistake with any original example included the enet_lwip.
    Could it be possible that this error is produced by a failed C code? I mean, obviously there are not errors, but perhaps in some aspect the code of my program (the C-JavaScpit interaction) is failing. I really don't have any clue, I would by grateful for any piece of advice.

    Thanks a lot for your time. Regards.

    Martin C!
  • Hello Martin,

    It could be a part of the code which is causing this. Can you share your code perhaps?

    Regards
    Amit
  • Of course Amit, I'll be very grateful if you give support of any kind, related or no related with our currently issue, after all I'm a begineer :)

    I've been working lot with this error and I noticed that If I restart the PC, CSS, and compile the proyect again, sometimes goes away, it's pretty strange.

    I've attached in a .rar folder: .c, .js and .html code.

    ti_cuestion.rar

    Again, thanks in advanced.

    MARTIN C!

  • Hi Fellows I have to admitt that this issue made me lot of problems and I am very lost. I do not get it what is happenning with this error message, in fact if I refresh several times the main webpage, the error sooner or later goes away, so we could say is almost alleatory.

    I have been thinking perhaps there is a suggested configuration of the CCS that can improve the performance. 

    I have been trying harware solutions too: I changed ethernet and usb connector, and the problems still stays on.

     

    Annyway, I was wondering if someone could search in deep this topic. Thanks in advanced!

     

    MARTIN C! 

  • Hello Martin

    I checked the rar file and it contained reference to some folder called Archivos. I think i would need the entire project to build the same.

    Regards
    Amit
  • Yes Ammit here's the latest project! 

    Sensados.rar

    As i said before any knind of help is welcome! :)

    Thanks in advanced

    Martin C!

  • Hi fellows I googled the error message and I found that a collegue of yours found the problem and the answer to this topic in the following post:
    e2e.ti.com/.../1205705
    But unfortunately I didn't understand what they were talking about. Please someone can clarify this issue?

    Thanks!
    Martin C!
  • Hello Martin,

    The changes that are being suggested are

    1. In the makefsfile.c (~line 1686 onwards) which is in D:\ti\TivaWare_C_Series-2.1.1.71\tools\makefsfile and rebuilding the exe associated with it
    2. The next change is in enet_fs.c (~Line 198) in the CCS project
    3. The last change is in enet_fs.c (~Line 144) in the CCS project for addition of the line

    psFile->http_header_included = 0;

    Regards
    Amit
  • Thanks again Amit, but I'm afraid I didn't understand what you mean.

    Let me explain myself:

    1. Here's the line 1686 of the makefsfile.c  file: The line you mentioned is red-circled so, firstly: I was wondering what are the changes suggested at this code. Secondly: I don't find a .exe file associated with with it in this path. 

    2. Here's the 198 line of the enet_fs.c code:


    What are the suggested changes in this case?

    3. Here's the 144 line of the same enet_fs.c code:

    Do you mean that i have to add psFile->http_header_included = 0; nex to the red-circled line?


    I really preciatte your concern with this issue, and I wolud be very grateful if you could give me the detailed information asked above, in order to finally solved this issue, which is bringing me headaches at the compiling time.

  • Hello Martin,

    The exe for the makefsfile is kept in bin location. In this case you need to recompile the source code with the update to make the new exe. I will open a bug to do so for the next TivaWare release (but in the meantime you would need to recompile it)

    For the other 2 points can you point me to the original project that you used?

    Regards
    Amit
  • Hi Amit, I found the .exe makefsfile, but i don't get what I have to modify in the mentioned file.

    I sent you screenshots of the enet_fs.c file that I have upload in the previous post (you can find it in the Sensados.rar folder)

    I sent you the two files:

    //*****************************************************************************
    //
    // enet_fs.c - File System Processing for lwIP Web Server Apps.
    //
    // Copyright (c) 2013-2015 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 2.1.1.71 of the EK-TM4C1294XL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdio.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/rom.h"
    #include "driverlib/ssi.h"
    #include "utils/lwiplib.h"
    #include "utils/ustdlib.h"
    #include "httpserver_raw/httpd.h"
    #include "httpserver_raw/fs.h"
    #include "httpserver_raw/fsdata.h"
    #include "fatfs/src/ff.h"
    #include "fatfs/src/diskio.h"
    #include "Varios/tension.h"
    #include "Varios/date.h"
    #include "Varios/datos.h"
    //*****************************************************************************
    //
    // Include the file system data for this application.  This file is generated
    // by the makefsfile utility, using the following command:
    //
    //     ../../../../tools/bin/makefsfile -i fs -o enet_fsdata.h -r -h -q
    //
    // If any changes are made to the static content of the web pages served by the
    // application, this command must be used to regenerate enet_fsdata.h in order
    // for those changes to be picked up by the web server.
    //
    //*****************************************************************************
    #include "enet_fsdata.h"
    
    //*****************************************************************************
    //
    // The following are data structures used by FatFs.
    //
    //*****************************************************************************
    static FATFS g_sFatFs;
    extern float tension;
    extern uint32_t tension_int;
    extern uint32_t h;
    extern uint32_t valoru;
    extern uint32_t veces;
    extern float decena;
    extern float vlinea;
    
    extern float temperatura;
    extern float corriente;
    
    int i_h=0, u_h=0, d_h=0;
    
    //*****************************************************************************
    //
    // The number of milliseconds that has passed since the last disk_timerproc()
    // call.
    //
    //*****************************************************************************
    static uint32_t ui32TickCounter = 0;
    
    //*****************************************************************************
    //
    // Initialize the file system.
    //
    //*****************************************************************************
    void
    fs_init(void)
    {
        //
        // Initialize and mount the Fat File System.
        //
        f_mount(0, &g_sFatFs);
    }
    
    //*****************************************************************************
    //
    // File System tick handler.
    //
    //*****************************************************************************
    void
    fs_tick(uint32_t ui32TickMS)
    {
        //
        // Increment the tick counter.
        //
        ui32TickCounter += ui32TickMS;
    
        //
        // Check to see if the FAT FS tick needs to run.
        //
        if(ui32TickCounter >= 10)
        {
            ui32TickCounter = 0;
            disk_timerproc();
        }
    }
    
    
    void enviar_tension(char * pcBuf, int iBufLen)
    {
    
    			sprintf(pcBuf, "%-4.2f%", vlinea);
    
    }
    
    void enviar_date(char * pcBuf, int iBufLen){
    	sprintf(pcBuf, "%s", DateTimeBuf);	
    }
    
    void enviar_temperatura(char * pcBuf, int iBufLen){
    		sprintf(pcBuf, "%-4.2f%", temperatura);
    
    }
    
    void enviar_corriente(char * pcBuf, int iBufLen){
    		sprintf(pcBuf, "%-4.2f%", corriente);
    
    }
    
    
    void seteo_anio_web(char *pcBuf) {
       unsigned long ulSpeed;
    
       // Parse the passed parameter as a decimal number.
    
       ulSpeed = 0;
       while((*pcBuf>='0')&&(*pcBuf <= '9')){
            ulSpeed *= 10;
            ulSpeed += (*pcBuf-'0');
            pcBuf++;
        }
    
        // If the number is valid, set the new speed.
    
        if(ulSpeed <= 100)
       {
        	actual_anio = ulSpeed;
        	//g_ulAnimSpeed = ulSpeed;
           // io_set_timer(g_ulAnimSpeed);
        }
    }
    
    void seteo_mes_web(char *pcBuf) {
       unsigned long ulSpeed;
    
       // Parse the passed parameter as a decimal number.
    
       ulSpeed = 0;
       while((*pcBuf>='0')&&(*pcBuf <= '9')){
            ulSpeed *= 10;
            ulSpeed += (*pcBuf-'0');
            pcBuf++;
        }
    
        // If the number is valid, set the new speed.
    
        if(ulSpeed <= 100)
       {
           actual_mes = ulSpeed;
    
        }
    }
    
    void seteo_dia_web(char *pcBuf){
       unsigned long ulSpeed;
    
       // Parse the passed parameter as a decimal number.
    
       ulSpeed = 0;
       while((*pcBuf>='0')&&(*pcBuf <= '9')){
            ulSpeed *= 10;
            ulSpeed += (*pcBuf-'0');
            pcBuf++;
        }
    
        // If the number is valid, set the new speed.
    
        if(ulSpeed <= 100)
       {
           actual_dia = ulSpeed;
    
        }
    }
    
    void seteo_hora_web(char *pcBuf){
       unsigned long ulSpeed;
    
       // Parse the passed parameter as a decimal number.
    
       ulSpeed = 0;
       while((*pcBuf>='0')&&(*pcBuf <= '9')){
            ulSpeed *= 10;
            ulSpeed += (*pcBuf-'0');
            pcBuf++;
        }
    
        // If the number is valid, set the new speed.
    
        if(ulSpeed <= 100)
       {
           actual_hora = ulSpeed;
    
        }
    }
    
    void seteo_min_web(char *pcBuf){
       unsigned long ulSpeed;
    
       // Parse the passed parameter as a decimal number.
    
       ulSpeed = 0;
       while((*pcBuf>='0')&&(*pcBuf <= '9')){
            ulSpeed *= 10;
            ulSpeed += (*pcBuf-'0');
            pcBuf++;
        }
    
        // If the number is valid, set the new speed.
    
        if(ulSpeed <= 100)
       {
           actual_min = ulSpeed;
    
        }
    }
    
    void seteo_seg_web(char *pcBuf){
       unsigned long ulSpeed;
    
       // Parse the passed parameter as a decimal number.
    
       ulSpeed = 0;
       while((*pcBuf>='0')&&(*pcBuf <= '9')){
            ulSpeed *= 10;
            ulSpeed += (*pcBuf-'0');
            pcBuf++;
        }
    
        // If the number is valid, set the new speed.
    
        if(ulSpeed <= 100)
       {
           actual_seg = ulSpeed;
    
        }
    }
    
    void enviar_frecuencia(char * pcBuf, int iBufLen){
    		sprintf(pcBuf, "%-4.2f%", decena);
    	
    }
    //*****************************************************************************
    //
    // Open a file and return a handle to the file, if found.  Otherwise,
    // return NULL.
    //
    //*****************************************************************************
    struct fs_file *
    fs_open(const char *pcName)
    {
        const struct fsdata_file *psTree;
        struct fs_file *psFile = NULL;
        FIL *psFatFile = NULL;
        FRESULT fresult = FR_OK;
    
        //
        // Allocate memory for the file system structure.
        //
        psFile = mem_malloc(sizeof(struct fs_file));
        if(psFile == NULL)
        {
            return(NULL);
        }
    
    
    
        if(ustrncmp(pcName, "/cgi-bin/get_voltage", 19) == 0)
                            {
                                static char pcBuf[8];
    
                               enviar_tension(pcBuf, 8);
    
                                //usnprintf(pcBuf, 5, "%4d%", tension_int);
    
                                psFile->data = pcBuf;
                                psFile->len = strlen(pcBuf);
                                psFile->index = psFile->len;
                                psFile->pextension = NULL;
    
                                //
                                // Return the psFile system pointer.
                                //
                                return(psFile);
                            }
    	
    	if(ustrncmp(pcName, "/cgi-bin/get_date", 16) == 0)
                               {
    
                                   static char pcBuf[22];
                                   enviar_date(pcBuf,22);
    							  // sprintf(pcBuf, "%s", g_pcDateTimeBuf);
    
                                   psFile->data = pcBuf;
                                   psFile->len = strlen(pcBuf);
                                   psFile->index = psFile->len;
                                   psFile->pextension = NULL;
    
                                   //
                                   // Return the psFile system pointer.
                                   //
    
                                   return(psFile);
                               }
    	
    	if(ustrncmp(pcName, "/cgi-bin/get_temperatura", 23) == 0)
    	                        {
    	                            static char pcBuf[8];
    
    	                           enviar_temperatura(pcBuf, 8);
    
    	                            psFile->data = pcBuf;
    	                            psFile->len = strlen(pcBuf);
    	                            psFile->index = psFile->len;
    	                            psFile->pextension = NULL;
    
    	                            //
    	                            // Return the psFile system pointer.
    	                            //
    	                            return(psFile);
    	                        }
    	
    	if(ustrncmp(pcName, "/cgi-bin/anio_enviar", 12) == 0){
    
                                fecha_actual ++;
                                static char pcBuf[6];
                                   //
                                   // Extract the parameter and set the actual speed requested.
                                   //
                                   seteo_anio_web((char*)pcName + 20);
    
    
                                   psFile->data = pcBuf;
                                   psFile->len = strlen(pcBuf);
                                   psFile->index = psFile->len;
                                   psFile->pextension = NULL;
                                   return(psFile);
    
                              }
    						  
    	if(ustrncmp(pcName, "/cgi-bin/mes_enviar", 11) == 0){
                                       static char pcBuf[6];
    
                                       fecha_actual ++;
                                       //
                                       // Extract the parameter and set the actual speed requested.
                                       //
                                       seteo_mes_web((char*)pcName + 19);
    
                                       psFile->data = pcBuf;
                                       psFile->len = strlen(pcBuf);
                                       psFile->index = psFile->len;
                                       psFile->pextension = NULL;
                                       return(psFile);
                                   //
                                   // If I can't find it there, look in the rest of the main psFile system*/
    
                                   }
    
    	if(ustrncmp(pcName, "/cgi-bin/dia_enviar", 11) == 0){
                                       static char pcBuf[6];
    
                                       fecha_actual ++;
                                       //
    
                                       //
                                       seteo_dia_web((char*)pcName + 19);
    
                                       psFile->data = pcBuf;
                                       psFile->len = strlen(pcBuf);
                                       psFile->index = psFile->len;
                                       psFile->pextension = NULL;
                                       return(psFile);
                                   //
                                   // If I can't find it there, look in the rest of the main psFile system*/
    
                                   }
    
    	if(ustrncmp(pcName, "/cgi-bin/hora_enviar", 12) == 0){
                                       static char pcBuf[6];
    
                                       fecha_actual ++;
                                       //
                                       // Extract the parameter and set the actual speed requested.
                                       //
                                       seteo_hora_web((char*)pcName + 20);
    
    
                                       psFile->data = pcBuf;
                                       psFile->len = strlen(pcBuf);
                                       psFile->index = psFile->len;
                                       psFile->pextension = NULL;
                                       return(psFile);
                                   //
                                   // If I can't find it there, look in the rest of the main psFile system*/
    
                                   }
    							   
    	if(ustrncmp(pcName, "/cgi-bin/min_enviar", 11) == 0){
                                       static char pcBuf[6];
    
                                       fecha_actual ++;
                                       //
                                       // Extract the parameter and set the actual speed requested.
                                       //
                                       seteo_min_web((char*)pcName + 19);
                                       //
                                       // Get the current speed setting as a string to send back.
    
    
                                       psFile->data = pcBuf;
                                       psFile->len = strlen(pcBuf);
                                       psFile->index = psFile->len;
                                       psFile->pextension = NULL;
                                       return(psFile);
                                   //
                                   // If I can't find it there, look in the rest of the main psFile system*/
    								}
    	
    	if(ustrncmp(pcName, "/cgi-bin/seg_enviar", 12) == 0){
                                      static char pcBuf[6];
    
                                      fecha_actual ++;
                                       //
                                       // Extract the parameter and set the actual speed requested.
                                       //
                                       seteo_seg_web((char*)pcName + 19);
                                       //
                                       // Get the current speed setting as a string to send back.
    
    
                                       psFile->data = pcBuf;
                                       psFile->len = strlen(pcBuf);
                                       psFile->index = psFile->len;
                                       psFile->pextension = NULL;
                                       return(psFile);
                                   //
                                   // If I can't find it there, look in the rest of the main psFile system
    
                                   }
    
    	if(ustrncmp(pcName, "/cgi-bin/get_corriente", 21) == 0) {
    		                            static char pcBuf[8];
    
    		                           enviar_corriente(pcBuf, 8);
    
    		                            //usnprintf(pcBuf, 5, "%4d%", tension_int);
    
    		                            psFile->data = pcBuf;
    		                            psFile->len = strlen(pcBuf);
    		                            psFile->index = psFile->len;
    		                            psFile->pextension = NULL;
    
    		                            //
    		                            // Return the psFile system pointer.
    		                            //
    		                            return(psFile);
    		                        }
    
    	if(ustrncmp(pcName, "/cgi-bin/get_frecuencia", 22) == 0) {
                                static char pcBuf[8];
    
                               enviar_frecuencia(pcBuf, 8);
    
                                //usnprintf(pcBuf, 5, "%4d%", tension_int);
    
                                psFile->data = pcBuf;
                                psFile->len = strlen(pcBuf);
                                psFile->index = psFile->len;
                                psFile->pextension = NULL;
    
                                //
                                // Return the psFile system pointer.
                                //
                                return(psFile);
                            }
    	
    	if(ustrncmp(pcName, "/cgi-bin/d_hist", 13) == 0){
    
    								
    	           					static char pcBuf[22];
    	
    								show_datos_h();
    								sprintf(pcBuf, "%s", show_fecha);	
    								
    	                             psFile->data = pcBuf;
    	                             psFile->len = strlen(pcBuf);
    	                             psFile->index = psFile->len;
    	                             psFile->pextension = NULL;
    
    	                             d_h++;
    	                                   return(psFile);
    
    	   	   	   	   	   	   	   }
    
    
    	if(ustrncmp(pcName, "/cgi-bin/u_hist", 13) == 0){
    
               					char pcBuf[7];
               					
    							show_datos_u();	
    							sprintf(pcBuf, "%s", show_tension);
    
    
                                 psFile->data = pcBuf;
                                 psFile->len = strlen(pcBuf);
                                 psFile->index = psFile->len;
                                 psFile->pextension = NULL;
    
                                 u_h++;
    
                                 return(psFile);
    
       	   	   	   	   	   	   }
    						   
    		if(ustrncmp(pcName, "/cgi-bin/i_hist", 13) == 0){
    
               					static char pcBuf[7];
               					
    							show_datos_i();	
    							sprintf(pcBuf, "%s", show_corriente);
    
    
                                 psFile->data = pcBuf;
                                 psFile->len = strlen(pcBuf);
                                 psFile->index = psFile->len;
                                 psFile->pextension = NULL;
    
                                 i_h++;
    
                                return(psFile);
    
       	   	   	   	   	   	   }
        //
        // Initialize the file system tree pointer to the root of the linked list.
        //
        psTree = FS_ROOT;
    
        //
        // Begin processing the linked list, looking for the requested file name.
        //
        while(NULL != psTree)
        {
            //
            // Compare the requested file "name" to the file name in the
            // current node.
            //
            if(ustrncmp(pcName, (char *)psTree->name, psTree->len) == 0)
            {
                //
                // Fill in the data pointer and length values from the
                // linked list node.
                //
                psFile->data = (char *)psTree->data;
                psFile->len = psTree->len;
    
                //
                // For now, we setup the read index to the end of the file,
                // indicating that all data has been read.
                //
                psFile->index = psTree->len;
    
                //
                // We are not using any file system extensions in this
                // application, so set the pointer to NULL.
                //
                psFile->pextension = NULL;
    
                //
                // Exit the loop and return the file system pointer.
                //
                break;
            }
    
            //
            // If we get here, we did not find the file at this node of the linked
            // list.  Get the next element in the list.
            //
            psTree = psTree->next;
        }
    
        //
        // If we didn't find the file, ptTee will be NULL.  Make sure we
        // return a NULL pointer if this happens.
        //
        if(psTree == NULL)
        {
            mem_free(psFile);
            psFile = NULL;
        }
    
        //
        // Return the file system pointer.
        //
        return(psFile);
    }
    //*****************************************************************************
    //
    // Close an opened file designated by the handle.
    //
    //*****************************************************************************
    void
    fs_close(struct fs_file *psFile)
    {
        //
        // If a Fat file was opened, free its object.
        //
        if(psFile->pextension)
        {
            mem_free(psFile->pextension);
        }
    
        //
        // Free the main file system object.
        //
        mem_free(psFile);
    }
    
    //*****************************************************************************
    //
    // Read the next chunck of data from the file.  Return the count of data
    // that was read.  Return 0 if no data is currently available.  Return
    // a -1 if at the end of file.
    //
    //*****************************************************************************
    int
    fs_read(struct fs_file *psFile, char *pcBuffer, int iCount)
    {
        int iAvailable;
        UINT uiBytesRead;
        FRESULT fresult;
    
        //
        // Check to see if a Fat File was opened and process it.
        //
        if(psFile->pextension)
        {
            //
            // Read the data.
            //
            fresult = f_read(psFile->pextension, pcBuffer, iCount, &uiBytesRead);
            if((fresult != FR_OK) || (uiBytesRead == 0))
            {
                return(-1);
            }
            return((int)uiBytesRead);
        }
    
        //
        // Check to see if more data is available.
        //
        if(psFile->index == psFile->len)
        {
            //
            // There is no remaining data.  Return a -1 for EOF indication.
            //
            return(-1);
        }
    
        //
        // Determine how much data we can copy.  The minimum of the 'iCount'
        // parameter or the available data in the file system buffer.
        //
        iAvailable = psFile->len - psFile->index;
        if(iAvailable > iCount)
        {
            iAvailable = iCount;
        }
    
        //
        // Copy the data.
        //
        memcpy(pcBuffer, psFile->data + iAvailable, iAvailable);
        psFile->index += iAvailable;
    
        //
        // Return the count of data that we copied.
        //
        return(iAvailable);
    }
    
    //*****************************************************************************
    //
    // Determine the number of bytes left to read from the file.
    //
    //*****************************************************************************
    int
    fs_bytes_left(struct fs_file *psFile)
    {
        //
        // Check to see if a Fat File was opened and process it.
        //
        if(psFile->pextension)
        {
            //
            // Return the number of bytes left to be read from the Fat File.
            //
            return(f_size((FIL *)psFile->pextension) -
                   f_tell((FIL *)psFile->pextension));
        }
    
        //
        // Return the number of bytes left to be read from this file.
        //
        return(psFile->len - psFile->index);
    }
    
    //*****************************************************************************
    //
    // makefsfile.c - A simple command line application to generate a file system
    //                image file from the contents of a directory.
    //
    // This application is based on the Perl script "makefsdata" shipped with
    // the Light Weight Internet Protocol (lwIP) TCP/IP stack which can be found
    // at http://www.sics.se/~adam/lwip/.
    //
    // Copyright (c) 2008-2015 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 2.1.1.71 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <errno.h>
    #include <sys/stat.h>
    
    typedef struct _tFileInfo_
    {
        struct _tFileInfo_ *psNext;
        char *pszFileName;
        char *pszStructName;
        long lFileSize;
    }
    tFileInfo;
    
    //*****************************************************************************
    //
    // Globals used to hold command line parameter information.
    //
    //*****************************************************************************
    bool g_bExcludeHeaders = false;
    bool g_bVerbose = false;
    bool g_bQuiet = false;
    bool g_bOverwrite = false;
    bool g_bBinaryOutput = false;
    bool g_bSingleFile = false;
    char *g_pszExclude = NULL;
    char *g_pszInputDir = NULL;
    char *g_pszOutput = "fsdata.c";
    
    //*****************************************************************************
    //
    // Globals tracking the list of files being processed.
    //
    //*****************************************************************************
    unsigned long g_ulNumFiles = 0;
    unsigned long g_ulTotalSize = 0;
    long g_lLastFileHeaderOffset = 0;
    long g_lFileSizeOffset = 0;
    FILE *g_fhOutput = NULL;
    tFileInfo g_sFileHead = { NULL, NULL, NULL, 0 };
    
    char *g_pszDefaultExcludeList[] =
    {
       ".svn",
       "CVS",
       "thumbs.db",
       "filelist.txt",
       "dirlist.txt"
    };
    
    #define NUM_EXCLUDE_STRINGS (sizeof(g_pszDefaultExcludeList) / sizeof(char *))
    
    //*****************************************************************************
    //
    // Storage for strings read from the user's exclude file and the number of
    // filenames it contains.
    //
    //*****************************************************************************
    char *g_pszUserExcludeStrings = NULL;
    unsigned long g_ulNumUserExcludeFiles = 0;
    
    //*****************************************************************************
    //
    // Count of the number of directories processed.
    //
    //*****************************************************************************
    int g_iDirCount = 0;
    
    //*****************************************************************************
    //
    // HTTP header strings for various filename extensions.
    //
    //*****************************************************************************
    typedef struct
    {
        char *pszExtension;
        char *pszHTTPHeader;
    }
    tHTTPHeader;
    
    tHTTPHeader g_sHTTPHeaders[] =
    {
        { "html",  "Content-type: text/html\r\n" },
        { "htm",   "Content-type: text/html\r\n" },
        { "shtml", "Content-type: text/html\r\n"
                   "Expires: Fri, 10 Apr 2008 14:00:00 GMT\r\n"
                   "Pragma: no-cache\r\n"},
        { "shtm",  "Content-type: text/html\r\n"
                   "Expires: Fri, 10 Apr 2008 14:00:00 GMT\r\n"
                   "Pragma: no-cache\r\n"},
        { "ssi",   "Content-type: text/html\r\n"
                   "Expires: Fri, 10 Apr 2008 14:00:00 GMT\r\n"
                   "Pragma: no-cache\r\n"},
        { "gif",   "Content-type: image/gif\r\n" },
        { "png",   "Content-type: image/png\r\n" },
        { "jpg",   "Content-type: image/jpeg\r\n" },
        { "bmp",   "Content-type: image/bmp\r\n" },
        { "ico",   "Content-type: image/x-icon\r\n" },
        { "class", "Content-type: application/octet-stream\r\n" },
        { "js",    "Content-type: application/x-javascript\r\n" },
        { "swf",   "Content-type: application/x-shockwave-flash\r\n" },
        { "ram",   "Content-type: audio/x-pn-realaudio\r\n" },
        { "css",   "Content-type: text/css\r\n" },
        { "xml",   "Content-type: text/xml\r\n"
                   "Expires: Fri, 10 Apr 2008 14:00:00 GMT\r\n"
                   "Pragma: no-cache\r\n"},
        { "txt",   "Content-type: text/plain\r\n" }
    };
    
    #define NUM_HTTP_HEADERS        (sizeof(g_sHTTPHeaders) / sizeof(tHTTPHeader))
    
    #define DEFAULT_HTTP_HEADER     "Content-type: text/plain\r\n"
    
    #define MAX_HTTP_HEADER_LEN     512
    
    //*****************************************************************************
    //
    // Characters in a path/filename that will be replaced by underscores when
    // constructing structure names in the output file.
    //
    //*****************************************************************************
    #define FILENAME_TOKENS         " .\\/~`!@#$%^&*()-+=[]{}|;:""'<>,/?"
    
    //*****************************************************************************
    //
    // Show the startup banner.
    //
    //*****************************************************************************
    void
    PrintWelcome(void)
    {
        printf("\nmakefsfile - Generate a file containing a file system image.\n");
        printf("Copyright (c) 2008-2015 Texas Instruments Incorporated.  All rights reserved.\n\n");
    }
    
    //*****************************************************************************
    //
    // Show help on the application command line parameters.
    //
    //*****************************************************************************
    void
    ShowHelp(void)
    {
        //
        // Only print help if we are not in quiet mode.
        //
        if(g_bQuiet)
        {
            return;
        }
    
        printf("This application may be used to create file system images to\n");
        printf("embed in applications offering web server interfaces.\n");
        printf("Two output formats are supported.  By default, an ASCII, C file\n");
        printf("containing initialized data structures is generated.  This may be\n");
        printf("built alongside the other application source to link the image\n");
        printf("into the application binary itself.  The second option, enabled\n");
        printf("using the -b command line parameter, outputs a position-independent\n");
        printf("binary file that may be flashed at a suitable address independently\n");
        printf("of the application binary.  Assuming the application knows the\n");
        printf("address at which the image has been placed, it can parse the file\n");
        printf("system image as normal.\n");
        printf("One additional mode is provided to allow easy creation of a C\n");
        printf("character array from a binary file.  If -f is specified, the file\n");
        printf("provided with -i will be dumped to the output as an array of hex\n");
        printf("bytes suitable for inclusion in a program.\n\n");
        printf("Supported parameters are:\n");
        printf("-i <dir>  - The name of the directory containing the files\n");
        printf("            to be included in the image.\n");
        printf("-o <file> - The name of the output file (default fsdata.c)\n");
        printf("-x <file> - A file containing a list of filenames and directory\n");
        printf("            names to be excluded from the generated image.\n");
        printf("-h        - Exclude HTTP headers from files.  By default, HTTP\n");
        printf("            headers are added to each file in the output.\n");
        printf("-b        - Generate a position-independent binary image.\n");
        printf("-r        - Rewrite existing output file without prompting.\n");
        printf("-f        - Dump a single file as a hex character array.\n");
        printf("            In this case, -i is a file rather than a directory\n");
        printf("            name\n");
        printf("-?        - Show this help.\n");
        printf("-q        - Quiet mode.  Disable output to stdio.\n");
        printf("-v        - Enable verbose output\n\n");
        printf("Example:\n\n");
        printf("   makefsfile -i html -o lmfsdata.c\n\n");
        printf("generates an image of all files and directories in and below\n");
        printf("\"html\", writing the result into file lmfsdata.c.\n");
    }
    
    //*****************************************************************************
    //
    // Read the contents of file pszFile and use it to populate the exclude list
    // stored in global variables g_pszUserExcludeList and g_ulNumUserExcludeFiles.
    //
    //*****************************************************************************
    bool
    PopulateExcludeList(char *pszFile)
    {
        FILE *fhExclude;
        long lSize, lRead, lLoop;
        char *pszDest;
        bool bLastWasZero;
    
        //
        // Open the file for reading.
        //
        fhExclude = fopen(pszFile, "rb");
    
        if(!fhExclude)
        {
            return(false);
        }
    
        //
        // Determine the size of the file.
        //
        fseek(fhExclude, 0, SEEK_END);
        lSize = ftell(fhExclude);
        fseek(fhExclude, 0, SEEK_SET);
    
    
        //
        // Allocate a block of memory to hold the strings.
        //
        g_pszUserExcludeStrings = malloc(lSize);
        if(!g_pszUserExcludeStrings)
        {
            return(false);
        }
    
        //
        // Read the whole file into our buffer.
        //
        lRead = (long)fread(g_pszUserExcludeStrings, 1, lSize, fhExclude);
    
        //
        // Close the file.
        //
        fclose(fhExclude);
    
        //
        // Did we read everything we expected?
        //
        if(lRead != lSize)
        {
            //
            // No - we didn't read the expected number of bytes.
            //
            free(g_pszUserExcludeStrings);
            return(false);
        }
    
        //
        // Remove all end-of-line characters, replacing them with zeros.  At the
        // end of this operation, the buffer contains a collection of strings
        // terminated by single NULLs.
        //
        pszDest = g_pszUserExcludeStrings;
        bLastWasZero = true;
        g_ulNumUserExcludeFiles = 0;
    
        for(lLoop = 0; lLoop < lSize; lLoop++)
        {
            switch(g_pszUserExcludeStrings[lLoop])
            {
                case '\r':
                    //
                    // Do nothing - we throw away all '\r' characters.
                    //
                    break;
    
                case '\n':
                    //
                    // Substitute a '\n' with '\0' unless we just inserted a 0
                    // in which case we skip the character.
                    //
                    if(!bLastWasZero)
                    {
                        g_ulNumUserExcludeFiles++;
                        *pszDest++ = '\0';
                        bLastWasZero = true;
                    }
                    break;
    
                case '\0':
                    if(!bLastWasZero)
                    {
                        g_ulNumUserExcludeFiles++;
                        *pszDest++ = g_pszUserExcludeStrings[lLoop];
                        bLastWasZero = true;
                    }
                    break;
    
                default:
                    *pszDest++ = g_pszUserExcludeStrings[lLoop];
                    bLastWasZero = false;
                    break;
            }
        }
    
        return(true);
    }
    
    //*****************************************************************************
    //
    // Dump the list of file and directory names that are being excluded from
    // the output.
    //
    //*****************************************************************************
    void
    DumpExcludeList(void)
    {
        char *pszDest;
        long lLoop;
    
        printf("Excluding the following files and directory names:\n");
    
        //
        // Dump the exclude list contents.
        //
        if(g_pszExclude)
        {
            //
            // We are using a user-supplied exclude list.  Dump this.
            //
            pszDest = g_pszUserExcludeStrings;
    
            for(lLoop = 0; lLoop < g_ulNumUserExcludeFiles; lLoop++)
            {
                printf("  %s\n", pszDest);
                pszDest += (strlen(pszDest) + 1);
            }
        }
        else
        {
            //
            // We are using the default internal exclude list. Dump this.
            //
            for(lLoop = 0; lLoop < NUM_EXCLUDE_STRINGS; lLoop++)
            {
                printf("  %s\n", g_pszDefaultExcludeList[lLoop]);
            }
        }
    
        printf("\n");
    }
    
    //*****************************************************************************
    //
    // Parse the command line, extracting all parameters.
    //
    // Returns 0 on failure, 1 on success.
    //
    //*****************************************************************************
    int
    ParseCommandLine(int argc, char *argv[])
    {
        int iRetcode;
        bool bRetcode;
        bool bShowHelp;
        bool bExcludeOK;
    
        //
        // By default, don't show the help screen and assume the exclude file
        // was fine.
        //
        bShowHelp = false;
        bExcludeOK = true;
    
        while(1)
        {
            //
            // Get the next command line parameter.
            //
            iRetcode = getopt(argc, argv, "i:o:x:hv?qrbf");
    
            if(iRetcode == -1)
            {
                break;
            }
    
            switch(iRetcode)
            {
                case 'i':
                {
                    g_pszInputDir = optarg;
                    break;
                }
    
                case 'o':
                {
                    g_pszOutput = optarg;
                    break;
                }
    
                case 'x':
                {
                    g_pszExclude = optarg;
    
                    //
                    // Populate the exclude list with the contents of the given
                    // file.
                    //
                    bExcludeOK = PopulateExcludeList(g_pszExclude);
                    if(!bExcludeOK)
                    {
                        bShowHelp = true;
                    }
                    break;
                }
    
                case 'f':
                {
                    g_bSingleFile = true;
                    break;
                }
    
                case 'h':
                {
                    g_bExcludeHeaders = true;
                    break;
                }
    
                case 'b':
                {
                    g_bBinaryOutput = true;
                    break;
                }
    
                case 'v':
                {
                    g_bVerbose = true;
                    break;
                }
    
                case 'q':
                {
                    g_bQuiet = true;
                    break;
                }
    
                case 'r':
                {
                    g_bOverwrite = true;
                    break;
                }
    
                case '?':
                {
                    bShowHelp = true;
                    break;
                }
            }
        }
    
        //
        // Show the welcome banner unless we have been told to be quiet.
        //
        if(!g_bQuiet)
        {
            PrintWelcome();
        }
    
        if(bShowHelp || (g_pszInputDir == NULL))
        {
            ShowHelp();
    
            //
            // Was there a problem with the exclude file?
            //
            if(bExcludeOK == false)
            {
                printf("\nThere was a problem reading exclude file %s.\n",
                       g_pszExclude);
            }
    
            //
            // Make sure we were given an input file.
            //
            if(g_pszInputDir == NULL)
            {
                printf("\nAn input directory must be specified using the -i "
                       "parameter.\n");
            }
    
            //
            // If we get here, we exit immediately.
            //
            exit(1);
        }
    
        //
        // Tell the caller that everything is OK.
        //
        return(1);
    }
    
    //*****************************************************************************
    //
    // Dump the command line parameters to stdout if we are in verbose mode.
    //
    //*****************************************************************************
    void
    DumpCommandLineParameters(void)
    {
        if(!g_bQuiet && g_bVerbose)
        {
            printf("Input %s   %s\n", g_bSingleFile ? "file:     " : "directory:",
                   g_pszInputDir);
            printf("Output file:       %s\n", g_pszOutput);
            printf("Output format:     %s\n",
                   ((g_bBinaryOutput && !g_bSingleFile)? "Binary" : "ASCII C"));
            printf("Overwrite output?: %s\n", g_bOverwrite ? "Yes" : "No");
    
            if(!g_bSingleFile)
            {
                printf("Exclude headers?:  %s\n", g_bExcludeHeaders ? "Yes" : "No");
                printf("Exclude file:      %s\n\n", (g_pszExclude == NULL) ? "None" :
                                                  g_pszExclude);
                DumpExcludeList();
            }
            else
            {
                printf("\n");
            }
        }
    }
    
    //*****************************************************************************
    //
    // Open the user's chosen output file, taking into account whether or not
    // we have been asked to overwrite it automatically.
    //
    //*****************************************************************************
    FILE *
    OpenOutputFile(char *szFile)
    {
        FILE *fhOut;
        int iResponse;
        unsigned long ulSize;
    
        //
        // First check to see if the file already exists unless we are to overwrite
        // it automatically.
        //
        if(!g_bOverwrite)
        {
            fhOut = fopen(szFile, "r");
    
            if(fhOut)
            {
                //
                // Close the file.
                //
                fclose(fhOut);
    
                //
                // If we are not running quietly, prompt the user as to what they
                // want to do.
                //
                if(!g_bQuiet)
                {
                    printf("File %s exists. Overwrite? ", szFile);
                    iResponse = getc(stdin);
                    if((iResponse != 'y') && (iResponse != 'Y'))
                    {
                        //
                        // The user didn't respond with 'y' or 'Y' so return an
                        // error and don't overwrite the file.
                        //
                        return(NULL);
                    }
                }
                else
                {
                    //
                    // In quiet mode but -r has not been specified so don't
                    // overwrite.
                    //
                    return(NULL);
                }
            }
        }
    
        //
        // If we get here, it is safe to open and, possibly, overwrite the output
        // file.
        //
        if(g_bVerbose)
        {
            printf("Opening output file %s\n", szFile);
        }
    
        //
        // Open the file in either binary or ASCII mode depending upon the
        // output type we are to use.
        //
        fhOut = fopen(szFile, g_bBinaryOutput ? "wb" : "w");
    
        if(fhOut)
        {
            if(g_bBinaryOutput)
            {
                //
                // Write the marker word "FIMG" at the beginning of the output
                // file so that the parser knows this is a position-independent
                // binary file system image.
                //
                fwrite("FIMG", 4, 1, fhOut);
    
                //
                // Remember where we are so that we can patch the file system
                // image size once we are done.
                //
                g_lFileSizeOffset = ftell(fhOut);
    
                //
                // Now write 4 bytes of 0 just to reserve space for the file
                // system image size.
                //
                ulSize = 0;
                fwrite(&ulSize, 4, 1, fhOut);
    
                //
                // Initialize the size of the image with the number of bytes
                // we have already written.
                //
                g_ulTotalSize = 8;
            }
            else
            {
                //
                // We are writing an ASCII C output file so add a header to
                // describe what the file contains.
                //
                fprintf(fhOut, "//***************************************************************************\n");
                fprintf(fhOut, "//\n");
                fprintf(fhOut, "// File System Image.\n");
                fprintf(fhOut, "//\n");
                fprintf(fhOut, "// This file was automatically generated using the makefsfile utility.\n");
                fprintf(fhOut, "//\n");
                fprintf(fhOut, "//***************************************************************************\n\n");
    
                //
                // This variable tracks the number of bytes in the file system
                // image not the number of bytes in the ASCII output file so
                // initialize it to 0 here (since we have not written anything that
                // will contribute to the binary size yet).
                //
                g_ulTotalSize = 0;
            }
        }
        return(fhOut);
    }
    
    //*****************************************************************************
    //
    // This function checks the supplied file or directory name against all those
    // in the current exclude list and returns true to indicate that this file is
    // to be included in the output or false to indicate that it is to be excluded.
    //
    //*****************************************************************************
    bool
    IncludeThisFile(char *pszFile)
    {
        int iLoop;
        char *pszString;
    
        //
        // If the file exclude list has not been overridden, check the filename
        // against our default list.
        //
        if(g_pszExclude == NULL)
        {
            //
            // Look at each of the default exclude strings in turn.
            //
            for(iLoop = 0; iLoop < NUM_EXCLUDE_STRINGS; iLoop++)
            {
                //
                // Does this file name match the exclude list entry?
                //
                if(!strcmp(pszFile, g_pszDefaultExcludeList[iLoop]))
                {
                    //
                    // Yes - this file is to be excluded.
                    //
                    return(false);
                }
            }
        }
        else
        {
            //
            // Search the user exclude list rather than the default internal one.
            //
            pszString = g_pszUserExcludeStrings;
    
            for(iLoop = 0; iLoop < g_ulNumUserExcludeFiles; iLoop++)
            {
                //
                // Does this file name match the exclude list entry?
                //
                if(!strcmp(pszFile, pszString))
                {
                    //
                    // Yes - this file is to be excluded.
                    //
                    return(false);
                }
    
                //
                // Move on to the next string.
                //
                pszString += strlen(pszString) + 1;
            }
        }
    
        return(true);
    }
    
    //*****************************************************************************
    //
    // Generate the relevant HTTP headers for the given filename and write
    // them into the supplied buffer.
    //
    //*****************************************************************************
    bool
    GetHTTPHeaders(char *pszDest, int iDestLen, char *pszFile)
    {
        int iLen, iLoop;
        char *pszStart;
        char *pszExt;
        char *pszWork;
    
        //
        // Set up for writing the output.
        //
        iLen = iDestLen;
        pszStart = pszDest;
    
        //
        // Is this a normal file or our special-case 404 file?
        //
        if(strstr(pszFile, "404"))
        {
            snprintf(pszDest, iLen, "HTTP/1.0 404 File not found\r\n");
        }
        else
        {
            snprintf(pszDest, iLen, "HTTP/1.0 200 OK\r\n");
        }
    
        //
        // Move to the end of the added string.
        //
        iLen -= strlen(pszDest);
        pszStart += strlen(pszDest);
    
        //
        // Was the buffer too small?
        //
        if(iLen <= 0)
        {
            //
            // Yes - fail the call.
            //
            if(!g_bQuiet)
            {
                printf("%d byte HTTP header buffer exhausted after line 1!\n",
                       iDestLen);
                printf("Current header is\n%s\n", pszDest);
            }
    
            return(false);
        }
    
        //
        // Add the server ID string.
        //
        snprintf(pszStart, iLen,
                 "Server: lwIP/1.3.2 (http://www.sics.se/~adam/lwip/)\r\n");
    
        //
        // Move to the end of the added string.
        //
        iLen = iDestLen - strlen(pszDest);
        pszStart = pszDest + strlen(pszDest);
    
        //
        // Was the buffer too small?
        //
        if(iLen <= 0)
        {
            //
            // Yes - fail the call.
            //
            if(!g_bQuiet)
            {
                printf("HTTP header buffer exhausted after server ID!\n");
            }
    
            return(false);
        }
    
        //
        // Get a pointer to the file extension.  We find this by looking for the
        // last occurrence of "." in the filename passed.
        //
        pszExt = NULL;
        pszWork = strchr(pszFile, '.');
        while(pszWork)
        {
            pszExt = pszWork + 1;
            pszWork = strchr(pszExt, '.');
        }
    
        if(g_bVerbose)
        {
            printf("File extension is %s.\n", pszExt);
        }
    
        //
        // Clear pszWork since we are about to use it for something different.
        //
        pszWork = NULL;
    
        //
        // Now determine the content type and any content-specific headers
        //
        for(iLoop = 0; (iLoop < NUM_HTTP_HEADERS) && pszExt; iLoop++)
        {
            //
            // Have we found a matching extension?
            //
            if(!strcmp(g_sHTTPHeaders[iLoop].pszExtension, pszExt))
            {
                pszWork = g_sHTTPHeaders[iLoop].pszHTTPHeader;
                if(g_bVerbose)
                {
                    printf("File extension found. Header is:\n%s\n", pszWork);
                }
                break;
            }
        }
    
        //
        // Did we find a matching extension?
        //
        if(!pszWork)
        {
            //
            // No - use the default, plain text file type.
            //
            pszWork = DEFAULT_HTTP_HEADER;
    
            if(g_bVerbose)
            {
                printf("Using default HTTP header for extension %s\n", pszExt);
            }
    
        }
    
        //
        // Output the file extension-specific headers.
        //
        snprintf(pszStart, iLen, "%s\r\n", pszWork);
    
        //
        // Move to the end of the added string.
        //
        iLen = iDestLen - strlen(pszDest);
        pszStart = pszDest + strlen(pszDest);
    
        //
        // Was the buffer too small?
        //
        if(iLen <= 0)
        {
            //
            // Yes - fail the call.
            //
            return(false);
        }
    
        //
        // If we get here, all the required headers were correctly written into
        // the supplied buffer.
        //
        return(true);
    }
    
    //*****************************************************************************
    //
    // Dump a block of bytes to the output file in the correct format for ASCII or
    // binary output.
    //
    //*****************************************************************************
    bool
    DumpHexToOutput(FILE *fhOutput, char *pcData, long lSize)
    {
        long lLoop;
        int iRetcode;
    
        //
        // Are we outputing in ASCII format?
        //
        if(!g_bBinaryOutput)
        {
            //
            // Yes - ASCII output so indent the start of the first line.
            //
            iRetcode = fprintf(fhOutput, "   ");
    
            //
            // Dump the bytes one at a time.
            //
            for(lLoop = 0; lLoop < lSize; lLoop++)
            {
                //
                // Dump a character in 0xZZ format.
                //
                iRetcode = fprintf(fhOutput, " 0x%02x,",
                                   (unsigned char)pcData[lLoop]);
    
                //
                // Exit the loop if we failed to write to the output.
                //
                if(!iRetcode)
                {
                    break;
                }
    
                //
                // Take a new line after every 8 characters.
                //
                if((lLoop % 8) == 7)
                {
                    fprintf(fhOutput, "\n   ");
                }
            }
    
            //
            // End the final line.
            //
            fprintf(fhOutput, "\n");
        }
        else
        {
            //
            // We are outputing binary so merely write the input data directly
            // to the output file.
            //
            iRetcode = fwrite(pcData, lSize, 1, fhOutput);
        }
    
        //
        // Update the binary size.
        //
        g_ulTotalSize += lSize;
    
        //
        // Was everything OK?
        //
        return(iRetcode ? true : false);
    }
    
    //*****************************************************************************
    //
    // Write a 32 bit value to the output file such that it appears in little
    // endian byte order.
    //
    //*****************************************************************************
    bool
    WriteLittleEndianDWORD(FILE *fhOutput, unsigned long ulValue)
    {
        unsigned char ucBuffer[4];
        int iRetcode;
    
        //
        // Be absolutely sure of the byte order we are going to write out.
        //
        ucBuffer[0] = (unsigned char)(ulValue & 0xFF);
        ucBuffer[1] = (unsigned char)((ulValue >> 8) & 0xFF);
        ucBuffer[2] = (unsigned char)((ulValue >> 16) & 0xFF);
        ucBuffer[3] = (unsigned char)((ulValue >> 24) & 0xFF);
    
        //
        // Write the 4 bytes comprising the little-endian value.
        //
        iRetcode = fwrite(ucBuffer, 1, 4, fhOutput);
    
        //
        // Update the binary size.
        //
        g_ulTotalSize += 4;
    
        //
        // Let the caller know whether or not we wrote the value successfully.
        //
        return((iRetcode == 4) ? true : false);
    }
    
    //*****************************************************************************
    //
    // Dump the contents of the supplied file as a file system data structure,
    // including HTTP headers if required.
    //
    //*****************************************************************************
    bool
    DumpFileContents(FILE *fhOutput, char *pszFile, tFileInfo *pFileInfo,
                     bool bNoHeaders)
    {
        bool bRetcode;
        char pcHTTPHeaders[MAX_HTTP_HEADER_LEN];
        char *pcFileBuffer;
        long lRead;
        FILE *fhFile;
    
        //
        // Get the HTTP headers if necessary.
        //
        if(!bNoHeaders)
        {
            //
            // Get the HTTP headers appropriate for this file type.
            //
            bRetcode = GetHTTPHeaders(pcHTTPHeaders, MAX_HTTP_HEADER_LEN,
                                      pFileInfo->pszFileName);
    
            //
            // Did we get the headers successfully?
            //
            if(!bRetcode)
            {
                if(g_bVerbose)
                {
                    printf("Failure determining HTTP headers!\n");
                }
                return(false);
            }
        }
        else
        {
            //
            // No HTTP headers.
            //
            pcHTTPHeaders[0] = '\0';
        }
    
        //
        // Open the file for binary read operations.
        fhFile = fopen(pszFile, "rb");
        if(!fhFile)
        {
            if(g_bVerbose)
            {
                printf("Can't open file %s!\n", pszFile);
            }
            return(false);
        }
    
        //
        // Determine the file's size.
        //
        fseek(fhFile, 0, SEEK_END);
        pFileInfo->lFileSize = ftell(fhFile);
        fseek(fhFile, 0, SEEK_SET);
    
        //
        // Zero length files are a problem.
        //
        if(pFileInfo->lFileSize == 0)
        {
            if(g_bVerbose)
            {
                printf("Zero length file!\n");
            }
    
            return(false);
        }
    
        //
        // Allocate a buffer for the file data.
        //
        pcFileBuffer = malloc(pFileInfo->lFileSize);
        if(!pcFileBuffer)
        {
            if(g_bVerbose)
            {
                printf("Can't allocate file read buffer!\n");
            }
            return(false);
        }
    
        //
        // Read the file contents into the buffer.
        //
        lRead = (long)fread(pcFileBuffer, 1, pFileInfo->lFileSize, fhFile);
    
        //
        // Close the file.
        //
        fclose(fhFile);
    
        //
        // Did we read everything we expected?
        //
        if(lRead != pFileInfo->lFileSize)
        {
            //
            // There was a problem reading the file.
            //
            if(g_bVerbose)
            {
                printf("Read %ld bytes but expected %ld!\n", lRead,
                       pFileInfo->lFileSize);
            }
    
            free(pcFileBuffer);
            return(false);
        }
    
        //
        // Output the structure definition and header comment if we are
        // generating ASCII output.
        //
        if(!g_bBinaryOutput || g_bSingleFile)
        {
            fprintf(fhOutput, "static const uint8_t data%s[] =\n{\n",
                    pFileInfo->pszStructName);
            fprintf(fhOutput, "    /* %s */\n", pFileInfo->pszFileName);
        }
        else
        {
            //
            // We remember the current file pointer so that we can go back
            // and fix up the last offset once we have finished processing all
            // the files.
            //
            g_lLastFileHeaderOffset = ftell(fhOutput);
    
            //
            // Output the offset to the next file in the output.  We fill this in
            // even before we know whether or not there is another file in the
            // output.  This will be fixed up once we finish parsing the whole
            // directory tree.
            //
            WriteLittleEndianDWORD(fhOutput, (17 +
                                   strlen(pFileInfo->pszFileName) +
                                   strlen(pcHTTPHeaders) +
                                   pFileInfo->lFileSize));
    
            //
            // Write the offset to the filename string.  The filename starts
            // immediately following this 16 byte header so the offset, from the
            // start of the header, is always 16 bytes.
            //
            WriteLittleEndianDWORD(fhOutput, 16);
    
            //
            // Write the offset of the data.  Again, this is relative to the start
            // of the header so it is 16 + the length of the filename including
            // its terminating 0.
            //
            WriteLittleEndianDWORD(fhOutput, (17 +
                                   strlen(pFileInfo->pszFileName)));
    
            //
            // Write the size of the data.  This does not include the filename,
            // merely the HTTP headers + the file data itself.
            //
            WriteLittleEndianDWORD(fhOutput, (pFileInfo->lFileSize +
                                              strlen(pcHTTPHeaders)));
        }
    
        //
        // Dump the filename to the output.  Note that the "+ 1" here ensures
        // that we also dump the terminating zero character.
        //
        if(!g_bSingleFile)
        {
            bRetcode = DumpHexToOutput(fhOutput, pFileInfo->pszFileName,
                                       strlen(pFileInfo->pszFileName) + 1);
    
            if(!bRetcode)
            {
                if(g_bVerbose)
                {
                    printf("Failed to write filename to output!\n");
                }
                free(pcFileBuffer);
                return(false);
            }
    
            //
            // If required, dump the HTTP headers to the output.  In this case, we don't
            // want the terminating zero character.
            //
            if(!bNoHeaders)
            {
                bRetcode = DumpHexToOutput(fhOutput, pcHTTPHeaders,
                                           strlen(pcHTTPHeaders));
    
                if(!bRetcode)
                {
                    if(g_bVerbose)
                    {
                        printf("Failed to write HTTP headers to output!\n");
                    }
                    free(pcFileBuffer);
                    return(false);
                }
            }
        }
    
        //
        // Dump the contents of the file to the output.
        //
        bRetcode = DumpHexToOutput(fhOutput, pcFileBuffer, pFileInfo->lFileSize);
    
        //
        // Update the file size to include the headers that we may have appended
        // at the beginning.
        //
        if(!bNoHeaders)
        {
            pFileInfo->lFileSize += strlen(pcHTTPHeaders);
        }
    
        //
        // Free the file buffer.
        //
        free(pcFileBuffer);
    
        //
        // Close the file data structure if outputing ASCII.
        //
        if(!g_bBinaryOutput || g_bSingleFile)
        {
            fprintf(fhOutput, "};\n\n");
        }
    
        return(bRetcode);
    }
    
    //*****************************************************************************
    //
    // Generate a filtered version of the supplied filename with all "/", " " and
    // "." characters replaced with underscores.
    //
    //*****************************************************************************
    void
    FilterFilename(char *pszDest, char *pszSrc)
    {
        int iLoop, iToken, iNumTokens;
        char *pcToken;
    
        //
        // Get a pointer to our list of token characters.
        //
        pcToken = FILENAME_TOKENS;
        iNumTokens = strlen(pcToken);
    
        //
        // Loop through each character in the filename.  Make sure we include the
        // terminating zero.
        //
        for(iLoop = 0; iLoop < (strlen(pszSrc) + 1); iLoop++)
        {
            //
            // Check this character against each of the character in our token
            // string.
            //
            for(iToken = 0; iToken < iNumTokens; iToken++)
            {
                //
                // Does this source character match the token character?
                //
                if(pszSrc[iLoop] == pcToken[iToken])
                {
                    //
                    // Yes - replace it with an underscore and exit the loop.
                    //
                    pszDest[iLoop] = '_';
                    break;
                }
            }
    
            //
            // If we drop out at the end of the inner loop, we didn't find a token
            // so copy the character from the source to the destination unmodified.
            //
            if(iToken == iNumTokens)
            {
                pszDest[iLoop] = pszSrc[iLoop];
            }
        }
    }
    
    //*****************************************************************************
    //
    // Process a single file, copying it into the output and updating the file
    // list to include information necessary to build the file information list at
    // the end of the output file.
    //
    //*****************************************************************************
    bool
    ProcessSingleFile(char *pszFile, char *pszRootDir)
    {
        tFileInfo *pFileInfo;
        char *pszFSFileName;
        bool bRetcode;
    
        //
        // Tell the user what we are up to.
        //
        if(g_bVerbose)
        {
            printf("Processing %s...\n", pszFile);
        }
    
        //
        // Get a pointer to the start of the filename as it will be in the
        // new file system. This means removing the pszRootDir substring from the
        // start of pszFile.
        //
        if(!strncmp(pszFile, pszRootDir, strlen(pszRootDir)))
        {
            pszFSFileName = pszFile + strlen(pszRootDir);
            if(g_bVerbose)
            {
                printf("Final filename is %s\n", pszFSFileName);
            }
        }
        else
        {
            //
            // Weird - the root directory doesn't appear in the passed filename.
            //
            return(false);
        }
    
        //
        // Create a new entry for the file list.
        //
        pFileInfo = malloc(sizeof(tFileInfo));
    
        if(!pFileInfo)
        {
            if(g_bVerbose)
            {
                printf("Can't allocate memory to store file information!\n");
            }
            return(false);
        }
    
        //
        // Allocate memory to hold the file name in both its original and
        // filtered forms.
        //
        pFileInfo->pszFileName = malloc(strlen(pszFSFileName) + 1);
        pFileInfo->pszStructName = malloc(strlen(pszFSFileName) + 1);
    
        //
        // Make sure we got the required memory.
        //
        if(!pFileInfo->pszFileName || !pFileInfo->pszStructName)
        {
            if(g_bVerbose)
            {
                free(pFileInfo);
                printf("Can't allocate memory to store filename information!\n");
            }
            return(false);
        }
    
        //
        // Copy the filename into the file info structure.
        //
        strcpy(pFileInfo->pszFileName, pszFSFileName);
    
        //
        // Generate the output structure name by replacing all dots and slashes in
        // the filename with underscores.
        //
        FilterFilename(pFileInfo->pszStructName, pszFSFileName);
    
        if(g_bVerbose)
        {
            printf("Filtered filename is %s\n", pFileInfo->pszStructName);
        }
    
        //
        // Dump the contents of the file to the output.
        //
        bRetcode = DumpFileContents(g_fhOutput, pszFile, pFileInfo,
                                    g_bExcludeHeaders);
    
        //
        // Was there a problem?
        //
        if(!bRetcode)
        {
            //
            // Yes - free the memory we allocated.
            //
            free(pFileInfo->pszFileName);
            free(pFileInfo->pszStructName);
            free(pFileInfo);
        }
        else
        {
            //
            // The file was dumped successfully so link its information into the
            // list for later use in building the directory.
            //
            pFileInfo->psNext = g_sFileHead.psNext;
            g_sFileHead.psNext = pFileInfo;
        }
    
        //
        // Tell the caller how things went.
        //
        return(bRetcode);
    }
    
    //*****************************************************************************
    //
    // This recursive function processes all the files in the directory tree below
    // the directory whose name is passed.
    //
    // pszDir is the path to the directory to process relative to the working
    // directory of the application.
    //
    //*****************************************************************************
    bool
    ProcessFilesInDirectory(char *pszDir)
    {
        int iRetcode;
        DIR *hDir;
        struct stat sFileInfo;
        struct dirent *psDirEntry;
        char szPath[FILENAME_MAX];
        bool bRetcode;
    
        //
        // Increment the number of directories we have processed.
        //
        g_iDirCount++;
    
        if(g_bVerbose)
        {
            printf("Changing to directory %s\n", pszDir);
        }
    
        //
        // Open the directory we have been passed.
        //
        hDir = opendir(pszDir);
    
        //
        // Read and process each entry in the directory
        //
        while((psDirEntry = readdir(hDir)) != NULL)
        {
            //
            // Ignore "." and ".." directories and any file which is listed
            // in the exclude list.
            //
            if(!strcmp(psDirEntry->d_name, ".")  ||
               !strcmp(psDirEntry->d_name, "..") ||
               !IncludeThisFile(psDirEntry->d_name))
            {
                if(g_bVerbose)
                {
                    printf("Excluding %s\n", psDirEntry->d_name);
                }
                continue;
            }
    
            //
            // Get information on this file (remembering to add the path from
            // the current working directory first).
            //
            snprintf(szPath, FILENAME_MAX, "%s/%s",pszDir, psDirEntry->d_name);
            iRetcode = stat(szPath, &sFileInfo);
    
            if(iRetcode == 0)
            {
                //
                // Is this a directory?
                //
                if(S_ISDIR(sFileInfo.st_mode))
                {
                    //
                    // Yes - make a recursive call to this function to process the
                    // new directory.
                    //
                    bRetcode = ProcessFilesInDirectory(szPath);
                }
                else
                {
                    //
                    // It's a file so go ahead and process it.
                    //
                    bRetcode = ProcessSingleFile(szPath, g_pszInputDir);
                }
    
                //
                // If something went wrong, return an error.
                //
                if(!bRetcode)
                {
                    if(g_bVerbose)
                    {
                        printf("Error reported processing %s\n", szPath);
                    }
                    break;
                }
            }
            else
            {
                printf("Can't get file info for %s! Returned %d. Errno %d\n",
                       szPath, iRetcode, errno);
                bRetcode = false;
                break;
            }
        }
    
        //
        // Close the directory and return
        //
        closedir(hDir);
        return(bRetcode);
    }
    
    //*****************************************************************************
    //
    // The main entry point of the application.
    //
    //*****************************************************************************
    int
    main(int argc, char *argv[])
    {
        int iRetcode;
        int iFileCount;
        long lSize;
        tFileInfo *pFileInfo;
        char *pszPrevious;
        bool bRetcode;
    
        iRetcode = ParseCommandLine(argc, argv);
        if(!iRetcode)
        {
            return(1);
        }
    
        //
        // Echo the command line settings to stdout in verbose mode.
        //
        DumpCommandLineParameters();
    
        //
        // Open the output file for writing in ASCII mode.
        //
        g_fhOutput = OpenOutputFile(g_pszOutput);
        if(!g_fhOutput)
        {
            if(g_pszUserExcludeStrings)
            {
                free(g_pszUserExcludeStrings);
            }
            return(2);
        }
    
        //
        // Was -f specified?  If so, we just dump one file to the output as a
        // C-style array of unsigned chars in hex format.  This is here to save me
        // spending any more time mucking with "od" and regular expressions to
        // generate a C array containing a single binary file.
        //
        if(g_bSingleFile)
        {
            tFileInfo FileInfo;
    
            FileInfo.pszStructName = "File";
            FileInfo.pszFileName = g_pszInputDir;
            bRetcode = DumpFileContents(g_fhOutput, g_pszInputDir, &FileInfo, true);
    
            iFileCount = 1;
            g_iDirCount = 1;
            g_ulTotalSize = FileInfo.lFileSize;
            iRetcode = (bRetcode ? 0 : 1);
        }
        else
        {
            //
            // Start the (recursive) process of processing the files.
            //
            bRetcode = ProcessFilesInDirectory(g_pszInputDir);
    
            //
            // If we processed all the files successfully and are outputing ASCII,
            // we have some more to do.
            //
            if(bRetcode)
            {
                //
                // If we are outputing binary, the whole output is now complete aside
                // from patching the final "pNext" offset in the file. If generating
                // ASCII, however, we still need to generate the file descriptor list.
                // This could have been done during the processing of the files as it
                // is for binary mode but by keeping the table to the end, it makes
                // the structure of the file system easier to understand when reading
                // the file so we do this instead.
                //
    
                //
                // Clear our file counter and previous file marker.
                //
                iFileCount = 0;
                pszPrevious = NULL;
    
                //
                // Walk through the information we gathered on each file and output
                // the relevant structure definition.
                //
                while(g_sFileHead.psNext)
                {
                    //
                    // Increment our file counter.
                    //
                    iFileCount++;
    
                    //
                    // Which file are we dealing with just now?
                    //
                    pFileInfo = g_sFileHead.psNext;
    
                    //
                    // If outputing ASCII, dump the file descriptor for this file.
                    //
                    if(!g_bBinaryOutput)
                    {
                        //
                        // What is the size of the filename string embedded in the file
                        // data?
                        //
                        lSize = strlen(pFileInfo->pszFileName) + 1;
    
                        fprintf(g_fhOutput, "const struct fsdata_file file%s[] =\n",
                                pFileInfo->pszStructName);
                        fprintf(g_fhOutput,
                                "{\n\t{\n\t\t%s%s,\n\t\tdata%s,\n\t\tdata%s + %ld,\n\t\tsizeof(data%s) - %ld\n\t}\n};\n\n",
                                (pszPrevious ? "file" : ""),
                                (pszPrevious ? pszPrevious : "NULL"),
                                 pFileInfo->pszStructName,
                                 pFileInfo->pszStructName, lSize,
                                 pFileInfo->pszStructName, lSize);
    
                        //
                        // Update the binary size.
                        //
                        g_ulTotalSize += 16;
                    }
    
                    //
                    // Free the previous filename string if one exists.
                    //
                    if(pszPrevious)
                    {
                        free(pszPrevious);
                    }
    
                    //
                    // Remember this filename for next time round.
                    //
                    pszPrevious = pFileInfo->pszStructName;
    
                    //
                    // Unlink this node from the file list.
                    //
                    g_sFileHead.psNext = pFileInfo->psNext;
    
                    //
                    // If this is the very last file, we need to output
                    // one additional line to finish things off before we
                    // free the file info structure.
                    //
                    if((pFileInfo->psNext == NULL) && !g_bBinaryOutput)
                    {
                        fprintf(g_fhOutput, "#define FS_ROOT file%s\n\n",
                                pFileInfo->pszStructName);
                    }
    
                    //
                    // Free the memory associated with this node in the list.  We free
                    // the pszStructName field next time round since it is saved in
                    // pszPrevious;
                    //
                    free(pFileInfo->pszFileName);
                    free(pFileInfo);
                }
    
                //
                // Free the final previous filename string if one exists.
                //
                if(pszPrevious)
                {
                    free(pszPrevious);
                }
    
                //
                // All files have been processed so now finish things off with the
                // #define which indicates the number of files.
                //
                if(!g_bBinaryOutput)
                {
                    iRetcode = fprintf(g_fhOutput, "#define FS_NUMFILES %d\n\n",
                                       iFileCount);
                }
                else
                {
                    //
                    // In binary mode, we need to patch the offset of the last file
                    // descriptor written to the output to mark it as the last file
                    // in the list.
                    //
                    fseek(g_fhOutput, g_lLastFileHeaderOffset, SEEK_SET);
                    iRetcode = (int)WriteLittleEndianDWORD(g_fhOutput, 0);
    
                    //
                    // Adjust the total size since the previous write doesn't
                    // contribute to the overall binary size.
                    //
                    g_ulTotalSize -= 4;
    
                    //
                    // We also need to add the final binary size to the file system
                    // header.
                    //
                    if(iRetcode)
                    {
                        fseek(g_fhOutput, g_lFileSizeOffset, SEEK_SET);
                        iRetcode = (int)WriteLittleEndianDWORD(g_fhOutput,
                                                               g_ulTotalSize);
                    }
    
                    //
                    // Once again, adjust the total size to ignore the last write.
                    //
                    g_ulTotalSize -= 4;
                }
    
                //
                // Make sure we wrote the last string successfully.  The assumption
                // here is that if any failure occured in earlier fprintf calls, this
                // last one will also fail so we don't need to check on every call.
                // Valid? Let's see...
                //
                if(!iRetcode)
                {
                    //
                    // Set a non-zero application return code to indicate a failure.
                    //
                    iRetcode = 4;
                }
                else
                {
                    //
                    // Set the final application return code to 0 to indicate success.
                    //
                    iRetcode = 0;
                }
            }
            else
            {
                //
                // Set an error return code since we didn't complete the file
                // processing successfully.
                //
                iRetcode = 3;
            }
        }
        //
        // Close the output file.
        //
        fclose(g_fhOutput);
    
        //
        // Free the user exclude list if one exists.
        //
        if(g_pszUserExcludeStrings)
        {
            free(g_pszUserExcludeStrings);
        }
    
        //
        // Tell the user what happened.
        //
        if(!g_bQuiet)
        {
            if(iRetcode == 0)
            {
                printf("Completed successfully. "
                       "%d files from %d director%s processed.\n"
                       "Binary size %ld (0x%08lx) bytes\n",
                       iFileCount, g_iDirCount,
                       ((g_iDirCount == 1) ? "y" : "ies"), g_ulTotalSize,
                       g_ulTotalSize);
            }
            else
            {
                printf("An error (%d) occured while processing files!\n",
                       iRetcode);
            }
        }
    
        //
        // Send the required exit code.
        //
        return(iRetcode);
    }
    
    

    Thanks at all!

  • Hello Martin.,

    The makefsfile.c has to be modified for the addition as per the post.

    In the enet_fs.c you have sent (it seems to be modified) the lines is 598 for the 3rd change. However the 2nd change is not required since you are not opening a file on the sd card.

    Regards
    Amit
  • Amit, I have added the line code, in the enet_fs.c file, as you see:

    Also I have run again the makefsfile.exe:

    And the message still goes on.

    Perhaps I have to modify the lines in the makefsfile.c, that's what i didn't get you the first time.

    Please explain me (in detail if it's possible) what lines do I have to change here:

     if(!g_bBinaryOutput) //line 1676 of makefsfile.c file
                    {
                        //
                        // What is the size of the filename string embedded in the file
                        // data?
                        //
                        lSize = strlen(pFileInfo->pszFileName) + 1;

                        fprintf(g_fhOutput, "const struct fsdata_file file%s[] =\n",
                                pFileInfo->pszStructName);
                        fprintf(g_fhOutput,
                                "{\n\t{\n\t\t%s%s,\n\t\tdata%s,\n\t\tdata%s + %ld,\n\t\tsizeof(data%s) - %ld\n\t}\n};\n\n",
                                (pszPrevious ? "file" : ""),
                                (pszPrevious ? pszPrevious : "NULL"),
                                 pFileInfo->pszStructName,
                                 pFileInfo->pszStructName, lSize,
                                 pFileInfo->pszStructName, lSize);

                        //
                        // Update the binary size.
                        //
                        g_ulTotalSize += 16;
                    }

                    //
                    // Free the previous filename string if one exists.
                    //
                    if(pszPrevious)
                    {
                        free(pszPrevious);
                    }

                    //
                    // Remember this filename for next time round.
                    //
                    pszPrevious = pFileInfo->pszStructName;

                    //
                    // Unlink this node from the file list.
                    //
                    g_sFileHead.psNext = pFileInfo->psNext;

                    //
                    // If this is the very last file, we need to output
                    // one additional line to finish things off before we
                    // free the file info structure.
                    //
                    if((pFileInfo->psNext == NULL) && !g_bBinaryOutput)
                    {
                        fprintf(g_fhOutput, "#define FS_ROOT file%s\n\n",
                                pFileInfo->pszStructName);
                    }

                    //
                    // Free the memory associated with this node in the list.  We free
                    // the pszStructName field next time round since it is saved in
                    // pszPrevious;
                    //
                    free(pFileInfo->pszFileName);
                    free(pFileInfo);
                }

                //
                // Free the final previous filename string if one exists.
                //
                if(pszPrevious)
                {
                    free(pszPrevious);
                }

                //
                // All files have been processed so now finish things off with the
                // #define which indicates the number of files.
                //
                if(!g_bBinaryOutput)
                {
                    iRetcode = fprintf(g_fhOutput, "#define FS_NUMFILES %d\n\n",
                                       iFileCount);
                }
                else
                {
                    //
                    // In binary mode, we need to patch the offset of the last file
                    // descriptor written to the output to mark it as the last file
                    // in the list.
                    //
                    fseek(g_fhOutput, g_lLastFileHeaderOffset, SEEK_SET);
                    iRetcode = (int)WriteLittleEndianDWORD(g_fhOutput, 0);

                    //
                    // Adjust the total size since the previous write doesn't
                    // contribute to the overall binary size.
                    //
                    g_ulTotalSize -= 4;               //line 1769 of makefsfile.c file

    Thank you very much!!

    Martin C!

  • Hello Martin,

    If you check the link to the post you sent, the changes to be made are shown. Once those changes are completed you would need to compile the makefsfile.c and generate a new exe instead of the existing exe file.

    Regards
    Amit
  • Hi Amit i follow the steps named in the post, resulting on these codes:

    1. makefsfile.c:

    2.enet_fs.c file:

    I built and compiled the proyect again but the error message still goes on.

    Did I do something wrong?

    What do you specifically mean to compile the makefsfile.c and generate a new exe instead of the existing exe file.?
     Because what i have done is: right click on makefsfile.c, rebuild project. But I'm not sure that is what you're asking for.

    Thank you at all! sorry for being so repetitve but i really need to solve this issue.

  • Hello Martin,

    makefsfile is a windows application and not something to do in the CCS. The makefsfile takes the web page files and converts it into a hex format for the MCU to manage. Updating the C Code is not going to do the trick.
    You need to build the updated makefsfile using a Generic C Compiler like GCC in a Cygwin shell.

    Regards
    Amit
  • Thanks Amit, I could solved it, as the post said. GCC console works fine. I'll paste the .exe download link in case someone has the same trouble, so the didn't have to lose time downloading a compiler. Just download this .exe and change it in the bin reposit.

    www.dropbox.com/.../makefsfile.exe

    As always thank you Amit you've been very helpful!!

    Regards, Martin C!

  • Hello Martin,

    CCS has a gmake utility. You can perhaps try using the same as well on Windows Command Line

    Regards
    Amit