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.

CC1352R: How to implement delay function in the application which is based on TI-RTOS

Part Number: CC1352R

Hi TI experts,

We are porting MSP430 bootloader host(BSL-SIMPLELINK-HOST) to CC1352R1 application(which is based on example <<simple_peripheral_CC13X2R1_LAUNCHXL_tirtos_ccs>>) but no luck:

The problem is the PC could not return from the delay function in the BSLEntrySequence(). Here is the source code, could you help to review it?

void BSLEntrySequence()
{

	GPIO_IF_setOutputHighOnPin(Board_TEST_PIN);
	GPIO_IF_setOutputHighOnPin(Board_RESET_PIN);
	bslDelayMs(200);//200ms

	GPIO_IF_setOutputLowOnPin(Board_TEST_PIN);
	bslDelayUs(800);
	GPIO_IF_setOutputLowOnPin(Board_RESET_PIN);
	bslDelayUs(20);

	GPIO_IF_setOutputHighOnPin(Board_TEST_PIN);
	bslDelayUs(20);
	GPIO_IF_setOutputLowOnPin(Board_TEST_PIN);
	bslDelayUs(20);

	GPIO_IF_setOutputHighOnPin(Board_TEST_PIN);
	bslDelayUs(20);
	GPIO_IF_setOutputHighOnPin(Board_RESET_PIN);
	bslDelayUs(20);
	GPIO_IF_setOutputLowOnPin(Board_TEST_PIN);
	bslDelayUs(20);

}
/*
 * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
 *
 *  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.
 *
*/

//******************************************************************************
// Version history:
// 1.0 07/17             Initial version. (Nima Eskandari)
// 1.1 07/17             Added Comments. (Nima Eskandari)
//----------------------------------------------------------------------------
//   Designed 2017 by Texas Instruments
//
//   Nima Eskandari
//   Texas Instruments Inc.
//   August 2017
//   Built with CCS Version: Code Composer Studio v7
//******************************************************************************

#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#include <unistd.h>
//#include <time.h>

/* Driver configuration */
#include "ti_drivers_config.h"
#include <ti/drivers/timer/GPTimerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/runtime/Types.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>

//#include <config.h>
//#include <debug.h>

GPTimerCC26XX_Handle bslDelayTimer;
GPTimerCC26XX_Params bslTimerParams;
//Types_FreqHz  freq;
static Semaphore_Handle bslTimerSemHandle;
static Semaphore_Struct bslTimerSemaphore;

uint32_t counter = 0;

void bslTimerCallback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask)
{
    counter --;
    if (counter <= 0)
        Semaphore_post(bslTimerSemHandle);
}

void InitializeDelayTimer()
{
    Semaphore_Params semParamsBslTimer;

    // Create bslDelayTimer semaphore
    Semaphore_Params_init(&semParamsBslTimer);
    semParamsBslTimer.mode = Semaphore_Mode_BINARY;
    Semaphore_construct(&bslTimerSemaphore, 0, &semParamsBslTimer);
    bslTimerSemHandle = Semaphore_handle(&bslTimerSemaphore);

    //BIOS_getCpuFreq(&freq);
    GPTimerCC26XX_Params_init(&bslTimerParams);
    bslTimerParams.width          = GPT_CONFIG_16BIT;
    bslTimerParams.mode           = GPT_MODE_PERIODIC_UP;
    bslTimerParams.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
}

//*****************************************************************************
// Get delay in milli seconds *************************************************
// time: The number of milliseconds to delay **********************************
//*****************************************************************************
void bslDelayMs(uint32_t time)
{
    if (time <= 0)
    {
        return;
    }
    else if (time <= 2)
    {
        counter = 1;
    }
    else
    {
        counter = time - 1;
    }

    bslDelayTimer = GPTimerCC26XX_open(CONFIG_GPTIMER_1, &bslTimerParams);
    if(bslDelayTimer == NULL) {

    }
    GPTimerCC26XX_Value loadVal = (48 * 1000) - 1 ; //47999
    GPTimerCC26XX_setLoadValue(bslDelayTimer, loadVal);
    GPTimerCC26XX_registerInterrupt(bslDelayTimer, bslTimerCallback, GPT_INT_TIMEOUT);

    GPTimerCC26XX_start(bslDelayTimer);
    Semaphore_pend(bslTimerSemHandle, BIOS_WAIT_FOREVER);
    GPTimerCC26XX_unregisterInterrupt(bslDelayTimer);
    GPTimerCC26XX_stop(bslDelayTimer);
    GPTimerCC26XX_close(bslDelayTimer);
}

//*****************************************************************************
// Get delay in micro seconds *************************************************
// time: Number of micro seconds to delay *************************************
//*****************************************************************************
void bslDelayUs(uint32_t time)
{
    if (time <= 0)
        return;

    if (time <= 200)
    {
        counter = 1;
    }
    else
    {
        counter = time / 100 - 1;
    }

    bslDelayTimer = GPTimerCC26XX_open(CONFIG_GPTIMER_1, &bslTimerParams);
    if(bslDelayTimer == NULL) {

    }
    GPTimerCC26XX_Value loadVal = (48 * 100) - 1 ; //4799
    GPTimerCC26XX_setLoadValue(bslDelayTimer, loadVal);
    GPTimerCC26XX_registerInterrupt(bslDelayTimer, bslTimerCallback, GPT_INT_TIMEOUT);

    GPTimerCC26XX_start(bslDelayTimer);
    Semaphore_pend(bslTimerSemHandle, BIOS_WAIT_FOREVER);
    GPTimerCC26XX_unregisterInterrupt(bslDelayTimer);
    GPTimerCC26XX_stop(bslDelayTimer);
    GPTimerCC26XX_close(bslDelayTimer);
}

For comparison, the delay timer of software_uart.c worked very well, the difference is software_uart used <<CONFIG_GPTIMER_0>> with "GPT_MODE_ONESHOT_UP" mode but BSLEntrySequence() used <<CONFIG_GPTIMER_1>> with "GPT_MODE_PERIODIC_UP" mode.

Meanwhile, I also tried usleep() but still could not work.

  • Added <software_uart.c> for comparison: 

    /*
     * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
     *
     *  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.
     *
    */
    
    //******************************************************************************
    // Version history:
    // 1.0 07/17             Initial version. (Nima Eskandari)
    // 1.1 07/17             Added Comments. (Nima Eskandari)
    //----------------------------------------------------------------------------
    //   Designed 2017 by Texas Instruments
    //
    //   Nima Eskandari
    //   Texas Instruments Inc.
    //   August 2017
    //   Built with CCS Version: Code Composer Studio v7
    //******************************************************************************
    
    #include <stdio.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <unistd.h>
    #include <string.h>
    /* Driver configuration */
    #include "ti_drivers_config.h"
    #include <BSL/software_uart.h>
    
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    GPTimerCC26XX_Handle uartDelayTimer;
    GPTimerCC26XX_Params uartTimerParams;
    // Semaphore used to post UART timer expired event
    static Semaphore_Handle uartTimerSemHandle;
    static Semaphore_Struct uartTimerSem;
    
    void delayOneBit();
    
    void uartTimerCallback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask)
    {
        Semaphore_post(uartTimerSemHandle);
    }
    
    void InitializeSWUartDelayTimer()
    {
        Semaphore_Params semParamsUartTimer;
    
        // Create UartTimer semaphore
        Semaphore_Params_init(&semParamsUartTimer);
        semParamsUartTimer.mode = Semaphore_Mode_BINARY;
        Semaphore_construct(&uartTimerSem, 0, &semParamsUartTimer);
        uartTimerSemHandle = Semaphore_handle(&uartTimerSem);
    
        GPTimerCC26XX_Params_init(&uartTimerParams);
        uartTimerParams.width          = GPT_CONFIG_16BIT;
        uartTimerParams.mode           = GPT_MODE_ONESHOT_UP;
        uartTimerParams.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
    }
    
    void delayOneBit()
    {
        uartDelayTimer = GPTimerCC26XX_open(CONFIG_GPTIMER_0, &uartTimerParams);
        if(uartDelayTimer == NULL) {
    
        }
        GPTimerCC26XX_Value loadVal = (48 * 10) - 1 ;
        GPTimerCC26XX_setLoadValue(uartDelayTimer, loadVal);
        GPTimerCC26XX_registerInterrupt(uartDelayTimer, uartTimerCallback, GPT_INT_TIMEOUT);
    
        GPTimerCC26XX_start(uartDelayTimer);
        Semaphore_pend(uartTimerSemHandle, BIOS_WAIT_FOREVER);
        GPTimerCC26XX_unregisterInterrupt(uartDelayTimer);
        GPTimerCC26XX_stop(uartDelayTimer);
        GPTimerCC26XX_close(uartDelayTimer);
    }
    
    void SoftwareUartPrintString(uint8_t * array)
    {
        int i = 0;
        for (i = 0; i < strlen((const char *)array); i++)
        {
            SoftwareUartPrintChar(array[i]);
        }
    }
    
    void SoftwareUartPrintChar(uint8_t data)
    {
        int cnt = 0;
        // start bit
        GPIO_write(Board_SW_UART_TX, 0);
        delayOneBit();
    
        //data
        for(cnt = 0 ; cnt < 8 ; cnt++)
        {
            if((data >> cnt) & 0x01)
            {
                GPIO_write(Board_SW_UART_TX, 1);
            }
            else
            {
                GPIO_write(Board_SW_UART_TX, 0);
            }
            delayOneBit();
        }
    
        //stop bit
        GPIO_write(Board_SW_UART_TX, 1);
        delayOneBit();
    }
    
    

    Please help to look into it asap, it has stuck me for several days...

  • Hi Siyou,

    Could you share more information on your application such as the main() function and how you start up the RTOS in question? 

    A few questions on the implementations as such, is there a particular reason you want to use the MSP bootloader (backward compatibility maybe)? These devices have a serial bootloader in ROM in case you are not locked to this particular solution.

    As for the software UART, is this something you use, do you require more then two UARTs (there is two UART peripherals on this device)?

  • Hi M-W,

    Thanks for your quick response. Here is my source of main():

    int main()
    {
      /* Register Application callback to trap asserts raised in the Stack */
      RegisterAssertCback(AssertHandler);
    
      Board_initGeneral();
    
      // Enable iCache prefetching
      VIMSConfigure(VIMS_BASE, TRUE, TRUE);
      // Enable cache
      VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
    
    #if !defined( POWER_SAVING )
      /* Set constraints for Standby, powerdown and idle mode */
      // PowerCC26XX_SB_DISALLOW may be redundant
      Power_setConstraint(PowerCC26XX_SB_DISALLOW);
      Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    #endif // POWER_SAVING
    
      /* Update User Configuration of the stack */
      user0Cfg.appServiceInfo->timerTickPeriod = Clock_tickPeriod;
      user0Cfg.appServiceInfo->timerMaxMillisecond  = ICall_getMaxMSecs();
    
      /* Initialize ICall module */
      ICall_init();
    
      /* Start tasks of external images - Priority 5 */
      ICall_createRemoteTasks();
    
    #ifdef PTM_MODE
      /* Start task for NPI task */
      //NPITask_createTask(ICALL_SERVICE_CLASS_BLE);
      NPITask_createTask(0x0000);
    #endif // PTM_MODE
    
      SimplePeripheral_createTask();
    
      /* enable interrupts and start SYS/BIOS */
      BIOS_start();
    
      return 0;
    }

    There are two MCUs in my design: MSP430F5xx and CC1352R1, we are trying to upgrade MSP430 firmware by CC1352R OAD, so we need to implement the MSP430 BSL host in CC1352 appliction. 

    CC1352 has two UARTs, UART1 is connected to MSP430 UART for application communication, and UART0 is connected to MSP430 BSL UART for MSP430 firmware update. So we need software UART for debug log print, and the software UART is working well.

  • Hi Siyou,

    Thanks for the elaboration. First of all I would advice to use "Task_sleep()" if you do not require delays smaller than ~120 us (minimum of 4 RTC ticks). This is a less complicated way compared to using the GPTimer module. You could also just use the "timeout" value of the Semaphore, it works just like the Task_sleep().

    As you seem to be using steps of "100us" based on the Timer setup then I guess you might be OK with the "Task_sleep()" approach. Have you tried this? To use the usleep() API mentioned before, "POSIX" need to be defined in the kernel configuration which is not always the case. In the end, usleep() would map to Task_sleep() anyway so might as well go straight to the source unless you need to be POSIX compliant. 

  • Hi M-W,

    Thanks for your sharing, it works.

    I also need 20us delay at some time, I invoked the CPUdelay() in that case.