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.

CC2650STK - Semaphore_pend blocks Hwi

Other Parts Discussed in Thread: SYSBIOS, CC2650

Hi, 

I'm just starting with development on TI-RTOS, and I tried to follow Introduction workshop, but I have some problem with semaphores, when I use semaphore_pend in my code it just loops there and don't allow any Hwi, or any other events to occur. Here's my code:

main.c

When i comment line: 64 and 65 and uncomment line: 73 It works as it should, but when i try to use semaphores it just loops in while(1)

program.cfg

I tried with both Hwi, using m3 i typed:

var hwi0Params = new M3Hwi.Params();
hwi0Params.instance.name = "hwi0";
Program.global.hwi0 = M3Hwi.create(35, "&hwi_start", hwi0Params);

And follow up question, if i use M3Hwi should i disable "var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');" ? Because it mess up my XDCtools view and sometimes i can't see custom M3 config, i tried to use only m3 and it seems to work. What are advantage of using m3 hwi?

Best regards

  • Hi Koper,

    Sorry for the delayed response.

    Unfortunately, I cannot see your code, what are you trying to accomplish, can you upload the source to this post directly (click "Use rich formatting" on the lower right, attach button appears)?

    As for the Hwi question, "ti.sysbios.hal.Hwi" is the our generic Hwi module, when you build your application this gets resolved to use the "ti.sysbios.family.arm.m3.Hwi". If you are already using the m3 Hwi, you can remove the generic once from your *.cfg file.

    Regards,

    -- Emmanuel
  • Anyone encountered this problem? Sorry to bump this topic but I'm really at dead end in charge of Hwi.
  • #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Log.h>
     
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
     
    /* TI-RTOS Header files */
    #include <ti/drivers/I2C.h>
    #include <ti/drivers/i2c/I2CCC26XX.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    //#include <ti/drivers/Power.h>
    #include <ti/sysbios/family/arm/cc26xx/Power.h>
    #include <ti/sysbios/family/arm/cc26xx/PowerCC2650.h>
    //#include <ti/drivers/SDSPI.h>
    //#include <ti/drivers/SPI.h>
    //#include <ti/drivers/spi/SPICC26XXDMA.h>
    //#include <ti/drivers/dma/UDMACC26XX.h>
    //#include <ti/drivers/UART.h>
    //#include <ti/drivers/uart/UARTCC26XX.h>
    //#include <ti/drivers/Watchdog.h>
    //#include <ti/drivers/watchdog/WatchdogCC26XX.h>
     
    /*Driver Libs*/
    #include <driverlib/sys_ctrl.h>
    #include <driverlib/prcm.h>
    #include <driverlib/timer.h>
    #include <driverlib/osc.h>
    #include <inc/hw_ints.h>
    #include <inc/hw_types.h>
    #include <inc/hw_memmap.h>
     
    /* Board Header files */
    #include "Board.h"
     
    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;
     
     
    void ledToggle();
    void taskDemo();
    void hwi_start();
     
    PIN_Config ledPinTable[] = {
        Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
     
     
    void ledToggle()
    {
            PIN_setOutputValue(ledPinHandle, Board_LED1,
                                       !PIN_getOutputValue(Board_LED1));
    }
     
    void taskDemo()
    {
            while(1)
            {
                    Semaphore_pend(ledSem,BIOS_WAIT_FOREVER);
                    ledToggle();
            }
    }
     
    void hwi_start()
    {
            TimerIntClear(GPT2_BASE, TIMER_TIMA_TIMEOUT);
            Semaphore_post(ledSem);
            //ledToggle();
    }
     
     
    int main(void)
    {
        /* Call board init functions. */
        Board_initGeneral();
     
        /*Timer Init*/
        PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
        PRCMLoadSet();
        PRCMPeripheralSleepEnable(PRCM_PERIPH_TIMER2);
        PRCMLoadSet();
        PRCMPeripheralDeepSleepEnable(PRCM_PERIPH_TIMER2);
        PRCMLoadSet();
        PRCMPeripheralRunEnable(PRCM_PERIPH_TIMER2);
        PRCMLoadSet();
     
        TimerDisable(GPT2_BASE, TIMER_BOTH);
        TimerConfigure(GPT2_BASE, TIMER_CFG_PERIODIC);
        TimerLoadSet(GPT2_BASE, TIMER_A, 48000000);
        TimerIntClear(GPT2_BASE, TIMER_TIMA_TIMEOUT);
        TimerIntEnable(GPT2_BASE, TIMER_TIMA_TIMEOUT);
        TimerEnable(GPT2_BASE, TIMER_A);
     
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        if(!ledPinHandle) {
            System_abort("Error initializing board LED pins\n");
        }
        PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
     
        /* Start BIOS */
        BIOS_start();
     
        return (0);
    }
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var ROM = xdc.useModule('ti.sysbios.rom.ROM');
    var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
     
    var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Error = xdc.useModule('xdc.runtime.Error');
    var Log = xdc.useModule('xdc.runtime.Log');
    var Main = xdc.useModule('xdc.runtime.Main');
    var Memory = xdc.useModule('xdc.runtime.Memory');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    //var Types = xdc.useModule('xdc.runtime.Types');
    //var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
    //var Reset = xdc.useModule('xdc.runtime.Reset');
     
    var Boot = xdc.useModule('ti.sysbios.family.arm.cc26xx.Boot');
    var Power = xdc.useModule('ti.sysbios.family.arm.cc26xx.Power');
    //var TimestampProvider = xdc.useModule('ti.sysbios.family.arm.cc26xx.TimestampProvider');
    //var Seconds = xdc.useModule('ti.sysbios.family.arm.cc26xx.Seconds');
    //var Alarm = xdc.useModule('ti.sysbios.family.arm.cc26xx.Alarm');
     
    var M3Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
    var ti_sysbios_family_arm_m3_Timer = xdc.useModule('ti.sysbios.family.arm.m3.Timer');
     
     
    /* ================ Driver configuration ================ */
    //TIRTOS.usePower = true;
    //TIRTOS.useGPIO = true;
    //TIRTOS.useI2C = true;
    //TIRTOS.libType = TIRTOS.LibType_Instrumented;
     
    //Task.enableIdleTask = true; /* Enable idle task (default). */
    //Text.isLoaded = false; /* Don't load diagnostic/descriptive text strings on the target */
    //Task.numPriorities = 6; /* Reduce number of Task priority levels to save RAM */
    //Task.defaultStackSize = 512; /* Set the default Task stack size - used if one is not specified */
    //Task.checkStackFlag = false; /* Don't check stacks for overflow - saves cycles (and power) and Flash */
     
    Boot.customerConfig = false;
    //Boot.trimDevice = true;
    //Boot.driverlibVersion = 2;
    //Boot.customerConfig = false;
    //Boot.checkBackdoor = true;
     
    //Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF; /* compile out all Assert's */
    //Defaults.common$.namedModule = false; /* Don't load string names of modules on the target */
    //Defaults.common$.memoryPolicy = Types.CREATE_POLICY; /* Allow Mod_create() and Mod_construct() but not delete() or destruct() */
     
    ROM.romName = ROM.CC2650; /*use the kernel in the ROM*/
     
    System.SupportProxy = SysMin; /* ================ System configuration ================ */
    //System.SupportProxy = SysCallback; /* Use the minimal user-supplied callback provider */
    //System.maxAtexitHandlers = 0; /* no exit handlers needed */
    //System.abortFxn = System.abortSpin; /* Abort and exit functions -- just spin */
    //System.exitFxn = System.exitSpin; /* Abort and exit functions -- just spin */
     
    BIOS.libType = BIOS.LibType_Custom; /* Use Custom library */
    BIOS.cpuFreq.lo = 48000000; /* Set the default CPU frequency */
    BIOS.logsEnabled = false; /* no logging - all compiled out */
    BIOS.assertsEnabled = false; /* disable Asserts in SYS/BIOS code */
    BIOS.swiEnabled = true;
    BIOS.heapSize = 1668; /* Create a small heap */
    BIOS.includeXdcRuntime = true;
    BIOS.runtimeCreatesEnabled = true;  /* false: Compile out reference to Memory in BIOS  true:  Allow runtime creation of e.g. semaphores */
     
    //Error.raiseHook = null; /* null = default while loop function. Use e.g. "&myFxn" to your own handler function. */
    //Error.maxDepth = 2; /* Minimize Flash and RAM usage of Error module */
    //Error.policyFxn = Error.policySpin; /* Change default error function -- just spin */
     
    Hwi.dispatcherAutoNestingSupport = true;
    Hwi.dispatcherSwiSupport = true;
    Hwi.dispatcherTaskSupport = true;
    Hwi.dispatcherIrpTrackingSupport = true;
    Hwi.initStackFlag = true;
     
    M3Hwi.enableException = true; /* Disable exception handling to save Flash - undo during active development */
    M3Hwi.excHandlerFunc = null; /* null = default while loop function. Use e.g. "&myFxn" to use your own function. */
    M3Hwi.nvicCCR.UNALIGN_TRP = 0;
    M3Hwi.nvicCCR.DIV_0_TRP = 0;
    M3Hwi.resetVectorAddress  = 0x0; /* Put reset vector at start of Flash */
    M3Hwi.vectorTableAddress  = 0x20000000; /* Put interrupt vector at start of RAM so interrupts can be configured at runtime */
    M3Hwi.NUM_INTERRUPTS = 50; /* CC2650 has 50 interrupts */
     
    //Program.stack = 1024; /* main() and Hwi, Swi stack size */
    //Program.argSize = 0; /* no command-line arguments main(argc, argv) needed */
    //Program.stack = 768;
     
    Power.idle = true;
    Power.policyFunc = Power.standbyPolicy;
    Power.calibrateRCOSC = false;
     
    //Clock.timerId = 0;
     
    //TimestampProvider.useClockTimer = true;
     
    var task0Params = new Task.Params();
    task0Params.instance.name = "task0";
    task0Params.stackSize = 512;
    task0Params.vitalTaskFlag = false;
    Program.global.task0 = Task.create("&taskDemo", task0Params);
     
    var hwi0Params = new Hwi.Params();
    hwi0Params.instance.name = "hwi0";
    Program.global.hwi0 = Hwi.create(35, "&hwi_start", hwi0Params);
     
    var semaphore0Params = new Semaphore.Params();
    semaphore0Params.instance.name = "ledSem";
    Program.global.ledSem = Semaphore.create(0, semaphore0Params);

  • Hi koper89,

    Sorry I completely lost track of your post. Are you still experiencing this issue?

    Regards,
    -- Emmanuel
  • Hi Emmanuel,
    Yes I still cannot make semaphore_pend to work, as described:
    " I have some problem with semaphores, when I use semaphore_pend in my code it just loops there and don't allow any Hwi, or any other events to occur. "
    My code is in my last post, hwi works as it should when I have semaphore_pend commented, as soon as I add sepahore_pend to my task, It cannot get out of the while loop.
  • Hi Koper89,

    Thanks again for providing your source, I have run the code and was able to reproduce what you are seeing.  The explanation is a little lengthy, so please bear with me.

    Firstly, I need to mention power management is deeply ingrained in the kernel and drivers for CC2650.  The power management algorithm runs in the idle task and aggressively tries to reach the lowest power consumption possible.  This results in peripheral clock sources and power domains being shut off by the power module is not informed to keep them on.  

    What is happening in your application is that once you call semaphore_pend() the power routine in the idle task runs and since it has no knowledge that the timer is running, it shuts off its clocks and power domain (effectively the timer is off).  The easiest way of testing this is by setting "Power.idle = true"  to "false" in the config file and running.  The application should now run as expected.

    There are two ways to solve this issue, firstly, instead of using driverlib APIs to configure your timer, you can use the TI-RTOS Timer module to create timers in your application.  The lm4 timer module automatically notifies the power module of the resources.  Instead of using the m3 timer in your config file ("ti_sysbios_family_arm_m3_Timer"), use the lm4 timer by adding the following to your config file:

    var Timer = xdc.useModule("ti.sysbios.family.arm.lm4.Timer");

    In your application you can create timers as follows:

    #include <xdc/runtime/Error.h>
    #include <ti/sysbios/family/arm/lm4/Timer.h>
    
    ...
    Error_Block eb;
    Timer_Params timerParams;
    
    Error_init(&eb);
    Timer_Params_init(&timerParams);
    timerParams.period = 2040;
    timer2 = Timer_create(2, 0, &timerParams, &eb);
    ...

    The other approach is to explicitly notify the power module not to turn off the timer peripheral (set a dependency) and set a constraint to prevent the power module from reaching a power mode where the timer is disabled.  To do so you need to add the following in a task in your application (in this case in the taskDemo before the while):

    void taskDemo() {
    	Power_setDependency(PERIPH_GPT2);
    	Power_setConstraint(Power_SB_DISALLOW);
    	while (1) {
    		Semaphore_pend(ledSem, BIOS_WAIT_FOREVER);
    		ledToggle();
    	}
    }

    The trade-off is that you will need to set a dependency and constraint for each timer you use (you must also release the constraint & dependency when you shutoff the timer).  

    Please read the Power Management for CC26xx document in the <tirtos install>/docs directory.

    Hope this helps,

    -- Emmanuel

  • Thank you Emmanuel for explanation.

    Best regards!

  • Thank you very much for this post Emmanuel,

    we have the following problem:

    we use a cc2650 and use a Hw timer. The Timer is used only for count. And we see no problem with the Dubugger! Everything is works fine. After we disconnect the debugger we see that the timer dont count anymore.


    After i change the config settings from Idle= true to idle=false. Everything works fine!.

    Perfect! Thank you very much!