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.

TM4C129ENCPDT: TI-RTOS SDSPI / USB Stick File Timestamp

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: EK-TM4C129EXL

Hi,

I'm using the EK-TM4C129EXL, TIVA TI-RTOS. I was able to successfully create and write characters to a file using SDSPI and USB Host Mass Storage drivers. The problem is that the timestamp on the file is not correct. How do I set the file timestamp to my current time? It looks like stdio.h is used to create and write to the file. I looked at functions in stdio but I couldn't find anything that pertains to changing the timestamp. I am also okay with not having a timestamp at all. Is there a way to just get rid of it on the file? Any help is appreciated.

Thanks

AJ

  • Hi AJ,

      I'm currently out of office. I will back to answer your question tomorrow. Sorry for the delayed response.

  • Hi Charles,

    Thanks for the response. 

    It looks like the post talks about setting the correct timestamp for my MCU, but it looks like it has nothing to do with the timestamp of the file saved on an SD card or USB flash

    When I tried running the examples for fatsd and fatsdusbcopy, the files are written to the storage device successfully but the time on the file is incorrect. It doesn't match my current time. You know how when you save a file to a directory there is a timestamp to it. The time on the file shows 4/11/2023 but when but it should have been 5/10/2023

    Thanks

    AJ 

  • Charles,

    Sorry, I'd like to correct myself. So when I ran the sample code fatsd, the file that got saved did not have a timestamp.

    However, when I ran my own program, which is my actual application with all the stuff that includes TCP, seconds, timestamp modules, etc, I would generate a file that has a time stamp but the time on the file is incorrect.

    How could I either get rid of the time or correct it?

    Thanks

    AJ 

  • Hi Charles, 

    I've done more investigating, and it looks like the Seconds_set function has something to do with the timestamp on the file. On the sample codes, the Seconds module is not used and Seconds_set is never called. In my application, I use Seconds_set(UTC_TIME) to validate a cert. I know I am getting the right UTC time because I'm getting it from an NTP Server, and I am comparing this value to a website displaying the current seconds since Jan 1970 (epoch time) just to be sure I got it right. I just realized that the timestamp on the file is a month off. The UTC time at the time I created the file is 5/12/2023 1:51. The file created is being dated 4/12/2023 1:51. It's a month off. However, I am inputting the correct UTC time in Seconds_set soI don't really know what's going on.

    One test I did was to set the time to zero by calling Seconds_set(0) right before creating the file. When I did this, the file saved did not have a time stamp. I'm convinced that the file timestamp is influenced by the Seconds module. Could there be a bug going on in the file API when getting the time from the Seconds module?

    Regards,

    AJ

  • Hi AJ,

      I don't know much of the inner working of how Seconds_set works. MCU cannot know the current time by itself. In order to provide correct timestamp, it must need to acquire the local time from the network, e.g. using SNTP protocol. 

      I will need to do some research myself as my knowledge in how timestamp works in TI-RTOS is very limited. Sorry for lack of guidance so far. 

  • No Problem Charles. Pls let me know if you figure something out.

    The fix I did isn't exactly that great. I call Seconds_set(0), and then write to the file. This prevents time stamp from being added to the file. And then I connect to NTP again to set Seconds_set back to correct time.

    Regards,

    AJ

  • Hi AJ,

      If you are able to obtain the time from NTP then can you look at the below example code to get the correct time and see if it helps. 

    /*
     *  ======== sntp.c ========
     *  SNTP Client example application
     */
    #include <string.h>
    #include <time.h>
    
    /* XDCtools Header files */
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    
    /* TI-RTOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/hal/Seconds.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/net/http/httpcli.h>
    #include <ti/net/sntp/sntp.h>
    
    /* Example/Board Header file */
    #include "Board.h"
    
    #include <sys/socket.h>
    
    /*
     * NTP server and port to obtain network time and number of servers to attempt
     */
    #define NTP_HOSTNAME "north-america.pool.ntp.org"
    #define NTP_PORT         "123"
    #define NTP_SERVERS      3
    #define NTP_SERVERS_SIZE (NTP_SERVERS * sizeof(struct sockaddr_in))
    #define NTPTASKSTACKSIZE 2048
    
    /*
     * Time Zone Adjustment.
     * TODO: Adjust your local time zone with respect to Greenwich Mean Time (GMT)
     * For example, North America Central Time Zone is 6 hours behind GMT
     */
    #define CENTRAL_TIME_ADJUST -6*60*60
    #define TIME_ZONE_ADJUST CENTRAL_TIME_ADJUST
    
    unsigned char ntpServers[NTP_SERVERS_SIZE];
    static Semaphore_Handle semHandle = NULL;
    
    /*
     *  ======== printError ========
     */
    void printError(char *errString, int code)
    {
        System_printf("Error! code = %d, desc = %s\n", code, errString);
        BIOS_exit(code);
    }
    
    /*
     *  ======== timeUpdateHook ========
     *  Called after NTP time sync
     */
    void timeUpdateHook(void *p)
    {
        Semaphore_post(semHandle);
    }
    
    /*
     *  ======== startNTP ========
     *  This is the function that generates the request to the NTP server for network time.
     */
    void startNTP(void)
    {
        int ret;
        int currPos;
        time_t ts;
        struct sockaddr_in ntpAddr;
        struct addrinfo hints;
        struct addrinfo *addrs;
        struct addrinfo *currAddr;
        Semaphore_Params semParams;
    
        /*
         * Clear the addrinfo first.
         */
        memset(&hints, 0, sizeof(struct addrinfo));
    
        /*
         * Use SOCK_DGRAM (UDP) as the socket type
         */
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;
    
        /*
         * First resolve the IP Address of the NTP server using the DNS service..
         * The getaddrinfo can return a linked-list of IP addresses
         */
        ret = getaddrinfo(NTP_HOSTNAME, NTP_PORT, NULL, &addrs);
        if (ret != 0) {
            printError("startNTP: NTP host cannot be resolved!", ret);
        }
    
        currPos = 0;
    
        /*
         * Loop through the NTP servers
         */
        for (currAddr = addrs; currAddr != NULL; currAddr = currAddr->ai_next) {
            if (currPos < NTP_SERVERS_SIZE) {
                ntpAddr = *(struct sockaddr_in *)(currAddr->ai_addr);
                /*
                 * Copy the list of NTP servers to netServers
                 */
                memcpy(ntpServers + currPos, &ntpAddr, sizeof(struct sockaddr_in));
                currPos += sizeof(struct sockaddr_in);
            }
            else {
                break;
            }
        }
    
        freeaddrinfo(addrs);
    
        /*
         * Initialize and start the SNTP client Task. Called to create and start SNTP
         * client Task and Semaphores. User must pass in pointers to functions for
         * getting and setting the current time and the list of NTP servers to
         * communicate with. timeUpdateHook() is called upon successful time
         * synchronization.
         */
        ret = SNTP_start(Seconds_get, Seconds_set, timeUpdateHook,
                (struct sockaddr *)&ntpServers, NTP_SERVERS, 0);
        if (ret == 0) {
            printError("startNTP: SNTP cannot be started!", -1);
        }
    
        /*
         * Create a semaphore that will block until after successful NTP time
         * synchronization.  Once unblocked, we will print the current time to the
         * console.
         */
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        semHandle = Semaphore_create(0, &semParams, NULL);
        if (semHandle == NULL) {
            printError("startNTP: Cannot create semaphore!", -1);
        }
    
        SNTP_forceTimeSync();
        /*
         * Wait here until the semaphore is posted.
         */
        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
    
        /*
         * Adjust for the Central Time Zone.
         */
        Seconds_set((unsigned int)((int)Seconds_get()+TIME_ZONE_ADJUST));
        ts = time(NULL);
    
        /*
         * Print the current time to the console.
         */
        System_printf("Current time: %s\n", ctime(&ts));
        System_flush();
    
    }
    
    /*
     *  ======== netIPAddrHook ========
     *  This function is called when IP Addr is added/deleted
     */
    void netIPAddrHook(unsigned int IPAddr, unsigned int IfIdx, unsigned int fAdd)
    {
        static Task_Handle taskHandle;
        Task_Params taskParams;
        Error_Block eb;
    
        /* Create a NTP task when the IP address is added */
        if (fAdd && !taskHandle) {
            Error_init(&eb);
    
            Task_Params_init(&taskParams);
            taskParams.stackSize = NTPTASKSTACKSIZE;
            taskParams.priority = 1;
            taskHandle = Task_create((Task_FuncPtr)startNTP, &taskParams, &eb);
            if (taskHandle == NULL) {
                printError("netIPAddrHook: Failed to create NTP Task\n", -1);
            }
        }
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
        Board_initEMAC();
    
        /* Turn on user LED */
        GPIO_write(Board_LED0, Board_LED_ON);
    
        System_printf("Starting the SNTP example\nSystem provider is set to "
                "SysMin. Halt the target to view any SysMin contents in ROV.\n");
        /* SysMin will only print to the console when you call flush or exit */
        System_flush();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }