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.

TMDSCNCD263: How to process data at 100usec intervals

Part Number: TMDSCNCD263
Other Parts Discussed in Thread: SYSCONFIG

We are trying to receive data from external sensors with a 100usec intervals and process it with a TMDSCNCD263.

When importing data into a microcontroller at 100usec intervals, is there any sample code to refer to?

According to the implementation of launching a fixed-period task with a mutex, there is a difference between the variable increment in the interrupt and the variable increment in the periodic task in units of 100 usec interrupt frequency.

| 5. 49s : CPU load = 18.00 %
| Timer Count : Task = 50330 / ISR = 50405
| 10. 49s : CPU load = 17.91 %
| Timer Count : Task = 100327 / ISR = 100405

The left side of the Timer Count is the count for periodic tasks, and the right side is the interrupt handling count.
Even if miss the time difference until the start of the fixed-period task, it is lost about 3 times out of 50,000 times, and the trend will continue in the same way after that.

  • Hi

    Could you try by referring to the FreeRTOS Task Switch Example using Semaphore. Location: examples/kernel/freertos/task_switch

    https://software-dl.ti.com/mcu-plus-sdk/esd/AM263X/latest/exports/docs/api_guide_am263x/EXAMPLES_KERNEL_FREERTOS_TASK_SWITCH.html

    Regards

    Sri Vidya

  • Hi

    I'm already experimenting with handling task switches.

    When interrupt processing is performed at a 100USEC period, there is a difference in the number of task processing times between interrupt handling and steady state processing.

    Since there is a difference in the amount of task processing between interrupt processing and steady state processing, we think that interrupt processing is failing.

  • Hi 

    Is it possible to share your code for reference?

    | 5. 49s : CPU load = 18.00 %
    | Timer Count : Task = 50330 / ISR = 50405
    | 10. 49s : CPU load = 17.91 %
    | Timer Count : Task = 100327 / ISR = 100405

    From this print, I see ISR is getting triggered more times than the Task. I assume ISR must be getting the data from the sensors, and Task would be processing this data.

    Is it possible to use FreeRtos Event Groups and Event Bits, 

    such that Task would be waiting on an event from ISR, and whenever ISR gets data from the sensors, it can send a signal to the Task to wake it up from wait. -- xEventGroupSetBitsFromISR().

    So both getting the data and processing it happens synchronously.

    Regards

    Sri Vidya

  • Hi,

    Attach the source code.

    <main.c>

    #include <stdlib.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_board_config.h"
    #include "FreeRTOS.h"
    #include "task.h"
    /* For semaphores used for steady state processing */
    #include <lwip/sys.h>
    /* For interrupt semaphores */
    #include <semphr.h>

    #define MAIN_TASK_PRI (configMAX_PRIORITIES-1)
    #define MAIN_THREAD_PRI (configMAX_PRIORITIES-2)

    #define MAIN_TASK_SIZE (16384U/sizeof(configSTACK_DEPTH_TYPE))
    StackType_t gMainTaskStack[MAIN_TASK_SIZE] __attribute__((aligned(32)));

    StaticTask_t gMainTaskObj;
    TaskHandle_t gMainTask;

    /* Thread Launch Semaphores */
    //sys_sem_t gThreadSem;
    StaticSemaphore_t gThreadSemObj;
    SemaphoreHandle_t gThreadSem;

    void enet_lwip_example(void *args);

    void freertos_main(void *args)
    {
    enet_lwip_example(NULL);

    vTaskDelete(NULL);
    }

    /* Periodic threads */
    StackType_t gThreadStack[MAIN_TASK_SIZE] __attribute__((aligned(32)));
    StaticTask_t gThreadObj;
    TaskHandle_t gThread;
    void freertos_thread(void *args);

    int main()
    {
    /* init SOC specific modules */
    System_init();
    Board_init();

    /* This task is created at highest priority, it should create more tasks and then delete itself */
    gMainTask = xTaskCreateStatic( freertos_main, /* Pointer to the function that implements the task. */
    "freertos_main", /* Text name for the task. This is to facilitate debugging only. */
    MAIN_TASK_SIZE, /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
    NULL, /* We are not using the task parameter. */
    MAIN_TASK_PRI, /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
    gMainTaskStack, /* pointer to stack base */
    &gMainTaskObj ); /* pointer to statically allocated task object memory */
    configASSERT(gMainTask != NULL);

    /* Semaphore generation */
    // err_t err;
    // err = sys_sem_new(&gThreadSem, 0);
    // LWIP_ASSERT("failed to create init_sem", err == ERR_OK);
    /* 以下はISR用 */
    gThreadSem = xSemaphoreCreateBinaryStatic(&gThreadSemObj);
    configASSERT(gThreadSem != NULL);
    vQueueAddToRegistry(gThreadSem, "Thread Sem"); /* This makes the semaphore visible in ROV within CCS IDE */

    /* Periodic threads */
    gThread = xTaskCreateStatic(freertos_thread,
    "freertos_thread",
    MAIN_TASK_SIZE,
    NULL,
    MAIN_THREAD_PRI, /* Higher priority than MAIN_TASK */
    gThreadStack,
    &gThreadObj);
    configASSERT(gThread != NULL);

    /* Start the scheduler to start the tasks executing. */
    vTaskStartScheduler();

    /* The following line should never be reached because vTaskStartScheduler()
    will only return if there was not enough FreeRTOS heap memory available to
    create the Idle and (if configured) Timer tasks. Heap management, and
    techniques for trapping heap exhaustion, are described in the book text. */
    DebugP_assertNoLog(0);

    return 0;
    }

    <test.c>

    /* C runtime includes */
    #include <stdio.h>
    #include <stdarg.h>
    #include <string.h>

    /* lwIP core includes */
    #include "lwip/opt.h"
    #include "test_enet_lwip.h"
    #include <enet_board_cfg.h>
    /* SDK includes */
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    #include <kernel/dpl/TaskP.h>
    #include <kernel/dpl/ClockP.h>

    #include <FreeRTOS.h>

    /* For interrupt semaphores */
    #include <semphr.h>

    extern void Board_cpswMuxSel(void);
    extern void Board_TxRxDelaySet(const EnetBoard_PhyCfg *boardPhyCfg);
    extern uint32_t Board_getEthBoardId(void);
    extern uint32_t Board_getEthType(void);

    /* Timer count */
    int gTimerCount;
    int gTimerCountISR;
    /* Thread Launch Semaphores */
    //extern sys_sem_t gThreadSem;
    extern StaticSemaphore_t gThreadSemObj;
    extern SemaphoreHandle_t gThreadSem;

    void print_cpu_load()
    {
    static uint32_t start_time = 0;
    uint32_t print_interval_in_secs = 5;
    uint32_t cur_time = ClockP_getTimeUsec()/1000;

    if(start_time==0)
    {
    start_time = cur_time;
    }
    else
    if( (cur_time-start_time) >= (print_interval_in_secs*1000) )
    {
    uint32_t cpu_load = TaskP_loadGetTotalCpuLoad();
    // uint32_t cpu_load = 0;

    DebugP_log(" %6d.%3ds : CPU load = %3d.%02d %%\r\n",
    cur_time/1000, cur_time%1000,
    cpu_load/100, cpu_load%100 );

    /* Timer processing count printing */
    DebugP_log(" Timer Count : Task = %d / ISR = %d\r\n",
    gTimerCount, gTimerCountISR);

    start_time = cur_time;

    TaskP_loadResetAll();
    }
    }

    void EnetApp_initLinkArgs(EnetPer_PortLinkCfg *linkArgs,
    Enet_MacPort macPort)
    {
    EnetPhy_Cfg *phyCfg = &linkArgs->phyCfg;
    EnetMacPort_LinkCfg *linkCfg = &linkArgs->linkCfg;
    EnetMacPort_Interface *mii = &linkArgs->mii;
    EnetBoard_EthPort ethPort;
    const EnetBoard_PhyCfg *boardPhyCfg;
    int32_t status;

    /* Setup board for requested Ethernet port */
    ethPort.instId = 0;
    ethPort.macPort = macPort;
    ethPort.boardId = Board_getEthBoardId();
    ethPort.enetType = Board_getEthType();
    ethPort.mii.layerType = ENET_MAC_LAYER_GMII;
    ethPort.mii.sublayerType = ENET_MAC_SUBLAYER_REDUCED;
    ethPort.mii.variantType = ENET_MAC_VARIANT_FORCED;

    status = EnetBoard_setupPorts(&ethPort, 1U);
    EnetAppUtils_assert(status == ENET_SOK);

    if (Enet_isCpswFamily(ethPort.enetType))
    {
    CpswMacPort_Cfg *macCfg = (CpswMacPort_Cfg *)linkArgs->macCfg;
    CpswMacPort_initCfg(macCfg);
    if (EnetMacPort_isSgmii(mii) || EnetMacPort_isQsgmii(mii))
    {
    macCfg->sgmiiMode = ENET_MAC_SGMIIMODE_SGMII_WITH_PHY;
    }
    else
    {
    macCfg->sgmiiMode = ENET_MAC_SGMIIMODE_INVALID;
    }
    }

    boardPhyCfg = EnetBoard_getPhyCfg(&ethPort);
    if (boardPhyCfg != NULL)
    {
    EnetPhy_initCfg(phyCfg);
    phyCfg->phyAddr = CONFIG_ENET_CPSW0_PHY0_ADDR;
    phyCfg->isStrapped = boardPhyCfg->isStrapped;
    phyCfg->loopbackEn = false;
    phyCfg->skipExtendedCfg = boardPhyCfg->skipExtendedCfg;
    phyCfg->extendedCfgSize = boardPhyCfg->extendedCfgSize;
    /* Setting Tx and Rx skew delay values */
    Board_TxRxDelaySet(boardPhyCfg);
    memcpy(phyCfg->extendedCfg, boardPhyCfg->extendedCfg, phyCfg->extendedCfgSize);

    }
    else
    {
    DebugP_log("No PHY configuration found for MAC port %u\r\n",
    ENET_MACPORT_ID(ethPort.macPort));
    EnetAppUtils_assert(false);
    }

    mii->layerType = ethPort.mii.layerType;
    mii->sublayerType = ethPort.mii.sublayerType;
    mii->variantType = ENET_MAC_VARIANT_FORCED;
    linkCfg->speed = ENET_SPEED_AUTO;
    linkCfg->duplexity = ENET_DUPLEX_AUTO;

    if (Enet_isCpswFamily(ENET_CPSW_3G))
    {
    CpswMacPort_Cfg *macCfg = (CpswMacPort_Cfg *)linkArgs->macCfg;

    if (EnetMacPort_isSgmii(mii) || EnetMacPort_isQsgmii(mii))
    {
    macCfg->sgmiiMode = ENET_MAC_SGMIIMODE_SGMII_WITH_PHY;
    }
    else
    {
    macCfg->sgmiiMode = ENET_MAC_SGMIIMODE_INVALID;
    }
    }
    }

    void EnetApp_getEnetInstInfo(Enet_Type *enetType,
    uint32_t *instId,
    Enet_MacPort macPortList[],
    uint8_t *numMacPorts)
    {
    *enetType = Board_getEthType();
    *instId = 0;
    *numMacPorts = 1;
    macPortList[0] = ENET_MAC_PORT_1;
    }

    int enet_lwip_example(void *args)
    {
    Enet_Type enetType;
    uint32_t instId;
    Enet_MacPort macPortList[1];
    uint8_t numMacPorts;

    Drivers_open();
    Board_driversOpen();

    Board_cpswMuxSel();

    DebugP_log("==========================\r\n");
    DebugP_log(" ENET LWIP App \r\n");
    DebugP_log("==========================\r\n");
    DebugP_log("portTICK_RATE_MS = %d\r\n", portTICK_RATE_MS);
    DebugP_log("configMAX_PRIORITIES = %d\r\n", configMAX_PRIORITIES);

    EnetApp_getEnetInstInfo(&enetType,
    &instId,
    macPortList,
    &numMacPorts);
    EnetAppUtils_enableClocks(enetType, instId);

    #if 0
    /* Semaphore generation */
    // err_t err;
    // err = sys_sem_new(&gThreadSem, 0);
    // gThreadSem = xSemaphoreCreateBinaryStatic(&gThreadSemObj);
    // configASSERT(gThreadSem != NULL);
    // vQueueAddToRegistry(gThreadSem, "Thread Sem"); /* This makes the semaphore visible in ROV within CCS IDE */
    #endif

    /* Start timer */
    gTimerCount = 0;
    gTimerCountISR = 0;
    TimerP_start(gTimerBaseAddr[CONFIG_TIMER0]);

    /* no stdio-buffering, please! */
    //setvbuf(stdout, NULL,_IONBF, 0);
    main_loop(NULL);
    return 0;
    }

    /* Periodic timer */
    void timer0_ISR(void)
    {
    // DebugP_log("timer0_ISR()\r\n");
    // sys_sem_signal(&gThreadSem);
    BaseType_t doTaskSwitch = 0;

    xSemaphoreGiveFromISR( gThreadSem, &doTaskSwitch); /* wake up pong task */
    portYIELD_FROM_ISR( doTaskSwitch );

    gTimerCountISR++;
    }

    /* Periodic threads */
    void freertos_thread(void *args)
    {
    DebugP_log("==========================\r\n");
    DebugP_log(" freertos_thread() \r\n");
    DebugP_log("==========================\r\n");
    while (1) {
    // sys_sem_wait(&gThreadSem);
    xSemaphoreTake(gThreadSem, portMAX_DELAY);
    gTimerCount++;
    }
    }

  • Hi 

    From the code you shared I see one task - "freertos_thread" running forever. So this should not cross the 100usec window. Are you running any other high-priority tasks that might consume the 100usec window?

    Could you try the same code with a Counting Semaphore? In that way, even though the ISR is ahead of the task, the task will not miss any of the Semaphore posts. I would suggest a counting semaphore value of atleast 10. I think this should solve the issue.

    Regards

    Sri Vidya

  • Hi 

    I could not reproduce the issue at my end with one task running forever and one timer ISR. I have made slight change in the code as below:

    Timer Configuration in Sysconfig - Is this same as yours?

    void TimerP_isr0(void *args)
    {
    void timer0_ISR(void *args);

    timer0_ISR(args);
    TimerP_clearOverflowInt(gTimerBaseAddr[CONFIG_TIMER0]);
    HwiP_clearInt(CONFIG_TIMER0_INT_NUM);
    }

    /* Periodic timer */
    void timer0_ISR(void)
    {
    // DebugP_log("timer0_ISR()\r\n");
    // sys_sem_signal(&gThreadSem);
    BaseType_t doTaskSwitch = 0;

    xSemaphoreGiveFromISR( gThreadSem, &doTaskSwitch); /* wake up pong task */
    portYIELD_FROM_ISR( doTaskSwitch );

    gTimerCountISR++;
    }

    /* Periodic threads */
    void freertos_thread(void *args)
    {
    DebugP_log("==========================\r\n");
    DebugP_log(" freertos_thread() \r\n");
    DebugP_log("==========================\r\n");
    static int startTimer = 1;
    while (1) {
    // sys_sem_wait(&gThreadSem);
    if(startTimer == 1)
    {
    TimerP_start(gTimerBaseAddr[CONFIG_TIMER0]);
    startTimer = 0;
    }
    xSemaphoreTake(gThreadSem, portMAX_DELAY);
    gTimerCount++;
    if(gTimerCount < gTimerCountISR)
    {
    DebugP_log("Error");
    }}}

    My Counter Values:

  • Hi,

    It seems that the priority setting was wrong, so I will change it and make it work.

    best regards

  • Hi 

    Could you tell me if you need more support on this, or could we close this thread?

    Regards

    Sri Vidya

  • Hi,

    You may want to close this thread.

    If additional questions arise, ask them again.

    best regards