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.

TDA4AEN-Q1: How to use the timerP to create a 10m base ISR?

Part Number: TDA4AEN-Q1
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hi:

     1. I work on mcu_plus_sdk_j722s_10_01_00_22

    2.  attachment my example.syscfg. I add below line in the example.syscfg for the timer setup.

timer1.$name = "CONFIG_TIMER0";
timer1.usecPerTick = 10000;
timer1.timerCallback = "TimerISR";
timer1.MCU_TIMER.$assign = "MCU_DMTIMER1";

     3. attachment the code ti_dpl_config.c and ti_dpl_config.h

     4. Check the TimerISR(args) don't call inside. Please help me check if there have any problem. I want to build it on mcu-r5fss0-0_freertos.

ti_dpl_config.h

/*
 *  Copyright (C) 2021 Texas Instruments Incorporated
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Auto generated file 
 */
#include <stdio.h>
#include <drivers/soc.h>
#include <kernel/dpl/AddrTranslateP.h>
#include "ti_dpl_config.h"
#include "ti_drivers_config.h"
#if defined(OS_SAFERTOS)
#include "SafeRTOS_API.h"

extern const xPORT_INIT_PARAMETERS xPortInit;

portBaseType Dpl_kernelInit(void)
{
    portBaseType xInitSchedResult;

    /* Initialise the kernel by passing in a pointer to the xPortInit structure
     * and return the resulting error code. */
    xInitSchedResult = xTaskInitializeScheduler( &xPortInit );

    if( pdPASS == xInitSchedResult )
    {
#if ( configQUEUE_REGISTRY_SIZE > 0 )
        vQueueAddToRegistry( acTimerCommandQueueBuffer, "Timer Command Q" );
#endif
    }

    return xInitSchedResult;
}
#endif

/* ----------- HwiP ----------- */
HwiP_Config gHwiConfig = {
    .intcBaseAddr = 0x7FF0000u,
};

/* ----------- ClockP ----------- */
#define MCU_TIMER0_CLOCK_SRC_MUX_ADDR (0x4508060u)
#define MCU_TIMER0_CLOCK_SRC_HFOSC0_CLKOUT (0x0u)
#define MCU_TIMER0_BASE_ADDR     (0x4800000u)

ClockP_Config gClockConfig = {
    .timerBaseAddr = MCU_TIMER0_BASE_ADDR,
    .timerHwiIntNum = 28,
    .timerInputClkHz = 25000000,
    .timerInputPreScaler = 1,
    .usecPerTick = 1000,
};

/* ----------- DebugP ----------- */
void putchar_(char character)
{
    /* Output to memory trace buffer */
    DebugP_memLogWriterPutChar(character);
    /* Output to UART console */
    DebugP_uartLogWriterPutChar(character);
}

/* DebugP log buffer memory and size
 * - This log can be viewed via ROV in CCS
 * - When linux is enabled, this log can also be viewed via linux debugfs
 */
char gDebugMemLog[DebugP_MEM_LOG_SIZE] __attribute__ ((section (".bss.debug_mem_trace_buf"), aligned (128)));
uint32_t gDebugMemLogSize = DebugP_MEM_LOG_SIZE;


/* ----------- CacheP ----------- */
CacheP_Config gCacheConfig = {
    .enable = 1,
    .enableForceWrThru = 0,
};

/* ----------- MpuP_armv7 ----------- */
#define CONFIG_MPU_NUM_REGIONS  (9u)

MpuP_Config gMpuConfig = {
    .numRegions = CONFIG_MPU_NUM_REGIONS,
    .enableBackgroundRegion = 0,
    .enableMpu = 1,
};

MpuP_RegionConfig gMpuRegionConfig[CONFIG_MPU_NUM_REGIONS] =
{
    {
        .baseAddr = 0x0u,
        .size = MpuP_RegionSize_2G,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 0,
            .isBufferable = 0,
            .isSharable = 1,
            .isExecuteNever = 1,
            .tex = 0,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0x0u,
        .size = MpuP_RegionSize_32K,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 0,
            .isBufferable = 0,
            .isSharable = 1,
            .isExecuteNever = 0,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0x41010000u,
        .size = MpuP_RegionSize_32K,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 0,
            .isBufferable = 0,
            .isSharable = 1,
            .isExecuteNever = 0,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0x79100000u,
        .size = MpuP_RegionSize_512K,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 1,
            .isBufferable = 1,
            .isSharable = 0,
            .isExecuteNever = 0,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0x80000000u,
        .size = MpuP_RegionSize_2G,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 1,
            .isBufferable = 1,
            .isSharable = 0,
            .isExecuteNever = 0,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0x60000000u,
        .size = MpuP_RegionSize_64M,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 1,
            .isBufferable = 1,
            .isSharable = 0,
            .isExecuteNever = 0,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0xA5000000u,
        .size = MpuP_RegionSize_16M,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 0,
            .isBufferable = 0,
            .isSharable = 1,
            .isExecuteNever = 1,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0xA1000000u,
        .size = MpuP_RegionSize_1M,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 0,
            .isBufferable = 0,
            .isSharable = 1,
            .isExecuteNever = 1,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
    {
        .baseAddr = 0xA1100000u,
        .size = MpuP_RegionSize_1M,
        .attrs = {
            .isEnable = 1,
            .isCacheable = 0,
            .isBufferable = 0,
            .isSharable = 1,
            .isExecuteNever = 1,
            .tex = 1,
            .accessPerm = MpuP_AP_ALL_RW,
            .subregionDisableMask = 0x0u
        },
    },
};

/* ----------- TimerP ----------- */
#define CONFIG_TIMER0_CLOCK_SRC_MUX_ADDR (0x4508064u)
#define CONFIG_TIMER0_CLOCK_SRC_HFOSC0_CLKOUT (0x0u)


HwiP_Object gTimerHwiObj[TIMER_NUM_INSTANCES];
uint32_t gTimerBaseAddr[TIMER_NUM_INSTANCES];

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

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

void TimerP_init()
{
    TimerP_Params timerParams;
    HwiP_Params timerHwiParams;
    int32_t status;

    /* set timer clock source */
    SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MCU, 2);
    *(volatile uint32_t*)AddrTranslateP_getLocalAddr(CONFIG_TIMER0_CLOCK_SRC_MUX_ADDR) = CONFIG_TIMER0_CLOCK_SRC_HFOSC0_CLKOUT;
    SOC_controlModuleLockMMR(SOC_DOMAIN_ID_MCU, 2);

    gTimerBaseAddr[CONFIG_TIMER0] = (uint32_t)AddrTranslateP_getLocalAddr(CONFIG_TIMER0_BASE_ADDR);

    TimerP_Params_init(&timerParams);
    timerParams.inputPreScaler = CONFIG_TIMER0_INPUT_PRE_SCALER;
    timerParams.inputClkHz     = CONFIG_TIMER0_INPUT_CLK_HZ;
    timerParams.periodInNsec   = CONFIG_TIMER0_NSEC_PER_TICK;
    timerParams.oneshotMode    = 0;
    timerParams.enableOverflowInt = 1;
    timerParams.enableDmaTrigger  = 0;
    TimerP_setup(gTimerBaseAddr[CONFIG_TIMER0], &timerParams);

    HwiP_Params_init(&timerHwiParams);
    timerHwiParams.intNum = CONFIG_TIMER0_INT_NUM;
    timerHwiParams.callback = TimerP_isr0;
    timerHwiParams.isPulse = 0;
    timerHwiParams.priority = 4;
    status = HwiP_construct(&gTimerHwiObj[CONFIG_TIMER0], &timerHwiParams);
    DebugP_assertNoLog(status==SystemP_SUCCESS);

}

void TimerP_deinit()
{
    TimerP_stop(gTimerBaseAddr[CONFIG_TIMER0]);
    HwiP_destruct(&gTimerHwiObj[CONFIG_TIMER0]);

}

#define BOOT_SECTION __attribute__((section(".text.boot")))

/* This function is called by _c_int00 */
void BOOT_SECTION __mpu_init()
{
    CacheP_init();
    MpuP_init();
}

void Dpl_init(void)
{
#if defined (OS_SAFERTOS)
    portBaseType xInitSchedResult;
#endif

    /* initialize Hwi but keep interrupts disabled */
    HwiP_init();

    /* init debug log zones early */
    /* Debug log init */
    /* Initialize linux trace log writer */
    DebugP_memLogWriterInit(CSL_CORE_ID_MCU_R5FSS0_0);
    /* UART console to use for reading input */
    DebugP_uartSetDrvIndex(CONFIG_UART0);


    /* set timer clock source */
    SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MCU, 2);
    *(volatile uint32_t*)(MCU_TIMER0_CLOCK_SRC_MUX_ADDR) = MCU_TIMER0_CLOCK_SRC_HFOSC0_CLKOUT;
    SOC_controlModuleLockMMR(SOC_DOMAIN_ID_MCU, 2);
    /* initialize Clock */
    ClockP_init();


    TimerP_init();
    /* Enable interrupt handling */
    HwiP_enable();

#if defined(OS_SAFERTOS)
    xInitSchedResult = Dpl_kernelInit();
    DebugP_assertNoLog(xInitSchedResult == pdPASS);
#endif
}

void Dpl_deinit(void)
{
    /* de-initialize Clock */
    ClockP_deinit();
    TimerP_deinit();
    /* Disable interrupt handling */
    HwiP_disable();
}

  • Hi:

         Attachment the example.syscfg again.

    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "J722S_TDA4VEN_TDA4AEN_AM67" --package "AMW" --part "Default" --context "mcu-r5fss0-0" --product "MCU_PLUS_SDK@07.03.01"
     * @versions {"tool":"1.20.0+3587"}
     */
    
    /**
     * Import the modules used in this configuration.
     */
    const ipc        = scripting.addModule("/drivers/ipc/ipc");
    const debug_log  = scripting.addModule("/kernel/dpl/debug_log");
    const mpu_armv7  = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false);
    const mpu_armv71 = mpu_armv7.addInstance();
    const mpu_armv72 = mpu_armv7.addInstance();
    const mpu_armv73 = mpu_armv7.addInstance();
    const mpu_armv74 = mpu_armv7.addInstance();
    const mpu_armv75 = mpu_armv7.addInstance();
    const mpu_armv76 = mpu_armv7.addInstance();
    const mpu_armv77 = mpu_armv7.addInstance();
    const mpu_armv78 = mpu_armv7.addInstance();
    const mpu_armv79 = mpu_armv7.addInstance();
    const timer      = scripting.addModule("/kernel/dpl/timer", {}, false);
    const timer1     = timer.addInstance();
    
    /**
     * Write custom configuration values to the imported modules.
     */
    ipc.vringAllocationPDK = false;
    
    debug_log.enableLogZoneWarning = false;
    debug_log.enableLogZoneError   = false;
    debug_log.enableCssLog         = false;
    debug_log.enableUartLog        = true;
    debug_log.uartLog.$name        = "CONFIG_UART0";
    debug_log.uartLog.intrEnable   = "DISABLE";
    
    mpu_armv71.baseAddr   = 0x0;
    mpu_armv71.size         = 31; /* 2 GB */
    mpu_armv71.attributes   = "Device";
    mpu_armv71.allowExecute = false;
    mpu_armv71.$name        = "CONFIG_MPU_REGISTER";
    
    mpu_armv72.baseAddr   = 0x0;
    mpu_armv72.size       = 15; /* 32 KB */
    mpu_armv72.$name      = "CONFIG_MPU_TCMA";
    mpu_armv72.allowExecute = true;
    mpu_armv72.attributes = "NonCached";
    
    mpu_armv73.baseAddr   = 0x41010000;
    mpu_armv73.size       = 15; /* 32 KB */
    mpu_armv73.$name      = "CONFIG_MPU_TCMB";
    mpu_armv73.allowExecute = true;
    mpu_armv73.attributes = "NonCached";
    
    mpu_armv74.baseAddr = 0x79100000;
    mpu_armv74.size     = 19; /* 512 KB */
    mpu_armv74.$name    = "CONFIG_MPU_MCU_MSRAM";
    mpu_armv74.allowExecute = true;
    
    mpu_armv75.baseAddr = 0x80000000;
    mpu_armv75.size     = 31; /* 2 GB */
    mpu_armv75.$name    = "CONFIG_MPU_DDR";
    mpu_armv75.allowExecute = true;
    
    mpu_armv76.baseAddr = 0x60000000;
    mpu_armv76.size     = 26; /* 64 MB */
    mpu_armv76.$name    = "CONFIG_MPU_FLASH";
    mpu_armv76.allowExecute = true;
    
    mpu_armv77.baseAddr = 0xA5000000;
    mpu_armv77.size     = 24; /* 32 MB */
    mpu_armv77.$name    = "RTOS_IPC_VRING";
    mpu_armv77.allowExecute = false;
    mpu_armv77.attributes   = "NonCached";
    
    mpu_armv78.$name        = "LINUX_VRING";
    mpu_armv78.baseAddr     = 0xA1000000;
    mpu_armv78.attributes   = "NonCached";
    mpu_armv78.size         = 20;
    mpu_armv78.allowExecute = false;
    
    mpu_armv79.attributes   = "NonCached";
    mpu_armv79.size         = 20;
    mpu_armv79.allowExecute = false;
    mpu_armv79.baseAddr     = 0xA1100000;
    mpu_armv79.$name        = "RESOURCE_TABLE_AND_TRACE";
    
    timer1.$name             = "CONFIG_TIMER0";
    timer1.usecPerTick       = 10000;
    timer1.timerCallback     = "TimerISR";
    timer1.MCU_TIMER.$assign = "MCU_DMTIMER1";
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    debug_log.uartLog.MCU_UART.$suggestSolution     = "MCU_USART0";
    debug_log.uartLog.MCU_UART.RXD.$suggestSolution = "MCU_UART0_RXD";
    debug_log.uartLog.MCU_UART.TXD.$suggestSolution = "MCU_UART0_TXD";
    

  • Hi,

    Can you expand on what the issue is? You are unable to reach the Timer ISR callback function with the generated code using sysconfig?

    Thanks,

    Neehar

  • Hi Neehar:

          No, I have generated the example.syscfg. As above a attachment. Base on the example.syscfg, I have been build the code and generated the R5F image. But when I run it on MCU R5F. I can't saw the TimerISR() will be call. And I have set the timer call userPerTick as 1000us. And Why there haven't periodic call thie TimerISR() function. 

  • Hi Neehar:

          My target goal that I want create a time periodic function. As example, I want a function will be periodic 10ms call. As now I want try to use the TimerP module to doing that. Or can you have any example code to provide to me on the J722S platform?

  • Hi,

    I will look into this further and get back to you.

    Thanks,

    Neehar

  • Hi Neehar:

            I already work for create timer 10m periodic. 10m periodic trigger my TimerISR() and call SemaphoreP_post signal to another task. 

            Thanks your help! Close case!

    example.syscfg

    /**
     * Import the modules used in this configuration.
     */
    const ipc        = scripting.addModule("/drivers/ipc/ipc");
    const debug_log  = scripting.addModule("/kernel/dpl/debug_log");
    const mpu_armv7  = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false);
    const mpu_armv71 = mpu_armv7.addInstance();
    const mpu_armv72 = mpu_armv7.addInstance();
    const mpu_armv73 = mpu_armv7.addInstance();
    const mpu_armv74 = mpu_armv7.addInstance();
    const mpu_armv75 = mpu_armv7.addInstance();
    const mpu_armv76 = mpu_armv7.addInstance();
    const mpu_armv77 = mpu_armv7.addInstance();
    const mpu_armv78 = mpu_armv7.addInstance();
    const mpu_armv79 = mpu_armv7.addInstance();
    const timer      = scripting.addModule("/kernel/dpl/timer", {}, false);
    const timer1     = timer.addInstance();
    
    /**
     * Write custom configuration values to the imported modules.
     */
    ipc.vringAllocationPDK = false;
    
    debug_log.enableLogZoneWarning = false;
    debug_log.enableLogZoneError   = false;
    debug_log.enableCssLog         = false;
    debug_log.enableUartLog        = true;
    debug_log.uartLog.$name        = "CONFIG_UART0";
    debug_log.uartLog.intrEnable   = "DISABLE";
    
    mpu_armv71.baseAddr   = 0x0;
    mpu_armv71.size         = 31; /* 2 GB */
    mpu_armv71.attributes   = "Device";
    mpu_armv71.allowExecute = false;
    mpu_armv71.$name        = "CONFIG_MPU_REGISTER";
    
    mpu_armv72.baseAddr   = 0x0;
    mpu_armv72.size       = 15; /* 32 KB */
    mpu_armv72.$name      = "CONFIG_MPU_TCMA";
    mpu_armv72.allowExecute = true;
    mpu_armv72.attributes = "NonCached";
    
    mpu_armv73.baseAddr   = 0x41010000;
    mpu_armv73.size       = 15; /* 32 KB */
    mpu_armv73.$name      = "CONFIG_MPU_TCMB";
    mpu_armv73.allowExecute = true;
    mpu_armv73.attributes = "NonCached";
    
    mpu_armv74.baseAddr = 0x79100000;
    mpu_armv74.size     = 19; /* 512 KB */
    mpu_armv74.$name    = "CONFIG_MPU_MCU_MSRAM";
    mpu_armv74.allowExecute = true;
    
    mpu_armv75.baseAddr = 0x80000000;
    mpu_armv75.size     = 31; /* 2 GB */
    mpu_armv75.$name    = "CONFIG_MPU_DDR";
    mpu_armv75.allowExecute = true;
    
    mpu_armv76.baseAddr = 0x60000000;
    mpu_armv76.size     = 26; /* 64 MB */
    mpu_armv76.$name    = "CONFIG_MPU_FLASH";
    mpu_armv76.allowExecute = true;
    
    mpu_armv77.baseAddr = 0xA5000000;
    mpu_armv77.size     = 24; /* 32 MB */
    mpu_armv77.$name    = "RTOS_IPC_VRING";
    mpu_armv77.allowExecute = false;
    mpu_armv77.attributes   = "NonCached";
    
    mpu_armv78.$name        = "LINUX_VRING";
    mpu_armv78.baseAddr     = 0xA1000000;
    mpu_armv78.attributes   = "NonCached";
    mpu_armv78.size         = 20;
    mpu_armv78.allowExecute = false;
    
    mpu_armv79.attributes   = "NonCached";
    mpu_armv79.size         = 20;
    mpu_armv79.allowExecute = false;
    mpu_armv79.baseAddr     = 0xA1100000;
    mpu_armv79.$name        = "RESOURCE_TABLE_AND_TRACE";
    
    timer1.$name             = "CONFIG_TIMER0";
    timer1.usecPerTick       = 10000;
    timer1.timerCallback     = "TimerISR";
    timer1.MCU_TIMER.$assign = "MCU_DMTIMER1";
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    debug_log.uartLog.MCU_UART.$suggestSolution     = "MCU_USART0";
    debug_log.uartLog.MCU_UART.RXD.$suggestSolution = "MCU_UART0_RXD";
    debug_log.uartLog.MCU_UART.TXD.$suggestSolution = "MCU_UART0_TXD";
    

    Timer task isr code:

    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>
    
    #include <kernel/dpl/HwiP.h>
    #include <kernel/dpl/TimerP.h>
    #include <kernel/dpl/SemaphoreP.h>
    
    #include <cmd_common.h>
    #include <fih_timer_task_client.h>
    #include "ti_dpl_config.h"
    
    #define MSGSIZE  256U
    #define FBPAYLAD_SIZE 128
    #define LOG_TAG_TIMER "TimerClient"
    
    /* ========================================================================================================== */
    /* ============================================ Variable define ============================================= */
    /* ========================================================================================================== */
    static SemaphoreP_Object g_TaskSem;
    
    volatile uint64_t g_timerIsrCount  = 0U;
    uint32_t g_timer_task_ms = 0;
    
    /* ========================================================================== */
    /*                             FIH client task                                */
    /* ========================================================================== */
    static bool fih_timer_semaphore_init(void)
    {
    	/* Create semaphore to signal completion of load tasks */
    	if(SemaphoreP_constructBinary(&g_TaskSem, 0) != SystemP_SUCCESS) {
    		print_log(LOG_LV_ERR, "[%s %s]: SemaphoreP_constructBinary fail\n", LOG_TAG_TIMER, __func__);
    		return false;
    	}
    
    	return true;
    }
    
    static void timer_task_trigger(uint64_t base_timer_cnt)
    {
    	if ((base_timer_cnt % (g_timer_task_ms/TIMER_BASE_MS)) == 0) {
    		SemaphoreP_post(&g_TaskSem);
    	}
    }
    
    static bool fih_timer_create(void)
    {
    	/* pass timer ISR count value to ISR as argument */
    	HwiP_setArgs(&gTimerHwiObj[CONFIG_TIMER0], (void*)&g_timerIsrCount);
    
    	return true;
    }
    
    void TimerISR(void *arg)
    {
        volatile uint64_t *pTimerIsrCount = (uint64_t *)arg;
    	*pTimerIsrCount = *pTimerIsrCount + 1;
    
    	if(!g_timer_task_ms) {
    		return;
    	}
    
    	timer_task_trigger(*pTimerIsrCount);
    }
    
    bool fih_timer_init(void)
    {
    	/* init the semaphore for timer */
    	if(!fih_timer_semaphore_init()) {
    		print_log(LOG_LV_ERR, "[%s %s]: fail call fih_timer_semaphore_init\n", LOG_TAG_TIMER, __func__);
    		return false;
    	}
    
    	/* Create timer */
    	if(!fih_timer_create()) {
    		print_log(LOG_LV_ERR, "[%s %s]: fail call fih_timer_create\n", LOG_TAG_TIMER, __func__);
    		return false;
    	}
    
    	return true;
    }
    
    bool fih_timer_task_start(uint32_t base_timer_ms, uint32_t task_timer_ms)
    {
    	/* Valid the task_timer_ms value */
    	if((task_timer_ms % 10) != 0) {
    		print_log(LOG_LV_ERR, "[%s %s]: task_timer_ms doesn't 10\n", LOG_TAG_TIMER, __func__);
    		return false;
    	}
    	if(task_timer_ms < TIMER_BASE_MS) {
    		print_log(LOG_LV_ERR, "[%s %s]: task_timer_ms less then TIMER_BASE_MS\n", LOG_TAG_TIMER, __func__);
    		return false;
    	}
    
    	/* */
    	g_timer_task_ms = task_timer_ms;
    
    	/* Start timer process */
    	TimerP_start(gTimerBaseAddr[CONFIG_TIMER0]);
    
    	return true;
    }
    
    bool fih_timer_task_stop(void)
    {
    	/* Stop timer process */
    	TimerP_stop(gTimerBaseAddr[CONFIG_TIMER0]);
    
    	/* Clear timer count value */
    	g_timer_task_ms = 0;
    	g_timerIsrCount = 0;
    
    	/* Signal to timer task unlock last time SemaphoreP */
    	SemaphoreP_post(&g_TaskSem);
    
    	return true;
    }
    
    bool Timer_task_chk(void)
    {
    	/* Valid if the task timer setup */
    	if(g_timer_task_ms == 0) {
    		return false;
    	}
    
    	/* Block wait signal from timer isr processs */
    	if(SystemP_SUCCESS == SemaphoreP_pend(&g_TaskSem, SystemP_WAIT_FOREVER)) {
    		/* Got the signal from timer isr. */
    		return true;
    	}
    
    	return false;
    }