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.

CC2340R5: Question about mq_receive and low power

Part Number: CC2340R5

In basic_ble example, mq_receive is used in BLEAppUtil_Task to wait for the messages from the stack. My question is that is mq_receive a blocking call in this task? If yes why does it not prevent the device into low power mode? From my understanding if it is a blocking call the CPU should be active to execute this call when waiting for messages.

Best regards,

Shuyang

  • Adding some background about the question: I'm asking this because a customer wants to use the watchdog with the message queue in their application. They feed the watchdog in the idle function vApplicationIdleHook(), but when mq_receive() is called the idle function will not be called anymore because mq_receive() is blocking.

    The question is what is the recommended way to feed the watchdog when mq_receive() is used? Is there an example for reference? Thanks.

    Best regards,

    Shuyang

  • Hi Shuyang,

    I recommend the customer reference the WatchDog API documentation, the LPF3 WatchDog API documentation, and Watchdog example. The driver should continue to count while in standby after the counter has been started. The watchdog can be configured to trigger an interrupt which can then perform whatever function is desired by the user.

    Best Regards,

    Jan

  • Hi Jan,

    Customer is feeding the watchdog in the idle function now, the problem is when mq_receive() is called it will block the task and wait for a message, during the waiting the idle function is not called therefore the watchdog is not fed. It cannot be garanteed a message will arrive before the watchdog timeout, so there is risk the watchdog reset will happen under this condition.

    The question is what is the recommended way to feed the watchdog with such implementation? Or is there another way to replace the message queue?

    Best regards,

    Shuyang

  • Hi Shuyang, 

    My apologies for the delay here. First of all, I would highly recommend migrating to the 7.20 SDK release that was recently provided on ti.com. This release contains several bug fixes and improvements that will improve the customer's development experience. 

    Can the customer share the code that shows how they ar efeeding the watchdog into the idle function?

    Best Regards,

    Jan

  • Hi Jan,

    The customer tested the new SDK and it seems to fix the issue, thanks for your support!

    Sorry for the confusion, I replied to the wrong post, this issue is not solved yet, please go on to support this, thanks!

    BR,

    Shuyang

  • Hi Shuyang,

    No worries! Thank you for checking if the issue was still in 7.20. Could you provide the watchdog code mentioned in my previous response? I would like to see how it is being set up in the customer's project.

    Best Regards,

    Jan

  • Hi Jan,

    Please find the customer's code as below. They feed the watchdog in the idle function vApplicationIdleHook() and use xQueueReceive() in the while loop to wait for the messages.

    We found out this implementation will cause the watchdog to timeout because xQueueReceive() is a blocking call. So our goal is not to resolve the "issue" but to find a workaround to timely feed the watchdog while using xQueueReceive().

    /*
     * Copyright (c) 2015-2019, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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.
     */
    
    /*
     *  ======== watchdog.c ========
     */
    #include <stdint.h>
    #include <stddef.h>
    #include <unistd.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/Watchdog.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    
    #define TIMEOUT_MS 1000
    #define SLEEP_US   500000
    
    /*
     *  ======== watchdogCallback ========
     */
    void watchdogCallback(uintptr_t watchdogHandle)
    {
        /*
         * If the Watchdog Non-Maskable Interrupt (NMI) is called,
         * loop until the device resets. Some devices will invoke
         * this callback upon watchdog expiration while others will
         * reset. See the device specific watchdog driver documentation
         * for your device.
         */
        while (1) {}
    }
    
    /*
     *  ======== gpioButtonIsr ========
     */
    void gpioButtonIsr(uint_least8_t index)
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
        /*
         * Simulate the application being stuck in an ISR. This ISR can be
         * preempted by the watchdog Non-Maskable Interrupt (NMI).
         */
        while (1) {}
    }
    Watchdog_Handle watchdogHandle;
    
    void vApplicationIdleHook(void)
    {
        Watchdog_clear(watchdogHandle);
    }
    /*
     *  ======== mainThread ========
     */
    #include <FreeRTOS.h>
    #include "task.h"
    #include "queue.h"
    #define QUEUE_LEN 128 /* 队列的长度,最大�包�多少个消� */
    #define QUEUE_SIZE 1 /* 队列中�个消�大�(字节) */
    uint32_t send_data1 = 1;
    
    QueueHandle_t Test_Queue = NULL;
    
    void *mainThread(void *arg0)
    {
        BaseType_t xReturn = pdTRUE;/* 定义一个创建信�返回值,默认为 pdTRUE */
          uint32_t r_queue; /* 定义一个接收消�的�� */
    
    
     //   Watchdog_Handle watchdogHandle;
        Watchdog_Params params;
        uint32_t reloadValue;
    
        /* Call driver init functions */
        GPIO_init();
        Watchdog_init();
    
        /* Configure the LED and button pins */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_setConfig(CONFIG_GPIO_BUTTON_0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
        GPIO_setCallback(CONFIG_GPIO_BUTTON_0, gpioButtonIsr);
    
        /* Open a Watchdog driver instance */
        Watchdog_Params_init(&params);
        params.callbackFxn    = (Watchdog_Callback)watchdogCallback;
        params.debugStallMode = Watchdog_DEBUG_STALL_ON;
        params.resetMode      = Watchdog_RESET_ON;
    
        watchdogHandle = Watchdog_open(CONFIG_WATCHDOG_0, &params);
        if (watchdogHandle == NULL)
        {
            /* Error opening Watchdog */
            while (1) {}
        }
    
        /*
         * The watchdog reload value is initialized during the
         * Watchdog_open() call. The reload value can also be
         * set dynamically during runtime.
         *
         * Converts TIMEOUT_MS to watchdog clock ticks.
         * This API is not applicable for all devices.
         * See the device specific watchdog driver documentation
         * for your device.
         */
        reloadValue = Watchdog_convertMsToTicks(watchdogHandle, TIMEOUT_MS);
    
        /*
         * A value of zero (0) indicates the converted value exceeds 32 bits
         * OR that the API is not applicable for this specific device.
         */
        if (reloadValue != 0)
        {
            Watchdog_setReload(watchdogHandle, reloadValue);
        }
    
        /* Turn on CONFIG_GPIO_LED_1 and enable CONFIG_GPIO_BUTTON_0 interrupt */
        GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_ON);
        GPIO_enableInt(CONFIG_GPIO_BUTTON_0);
    
    
        taskENTER_CRITICAL(); //进入临界区
    
        /* 创建 Test_Queue */
        Test_Queue = xQueueCreate((UBaseType_t ) QUEUE_LEN,/* 消�队列的长度 */
                                 (UBaseType_t ) QUEUE_SIZE);/* 消�的大� */
        if (NULL != Test_Queue)
        {
           printf("创建 Test_Queue 消�队列�功!\r\n");
        }
        taskEXIT_CRITICAL();
    
    
        while (1)
        {
            GPIO_toggle(CONFIG_GPIO_LED_1);
            //usleep(SLEEP_US);
    
           /*open this code */
          xReturn = xQueueReceive(Test_Queue, /* 消�队列的�柄 */
                                                          &r_queue, /* ��的消�内容 */
                                                          portMAX_DELAY); /* 等待时间 一直等 */
    
    
    
    
    //        /*
    //         * Disabling power policy will prevent the device from entering
    //         * low power state. The device will stay awake when the CPU is
    //         * idle.
    //         */
    //        Power_disablePolicy();
    //
    //        /* Sleep for SLEEP_US before clearing the watchdog */
    //        usleep(SLEEP_US);
    //        Watchdog_clear(watchdogHandle);
    //        GPIO_toggle(CONFIG_GPIO_LED_0);
    //
    //        /*
    //         * Enabling power policy will allow the device to enter a low
    //         * power state when the CPU is idle. How the watchdog peripheral
    //         * behaves in a low power state is device specific.
    //         */
    //        Power_enablePolicy();
    //
    //        /* Sleep for SLEEP_US before clearing the watchdog */
    //        usleep(SLEEP_US);
    //        Watchdog_clear(watchdogHandle);
    //        GPIO_toggle(CONFIG_GPIO_LED_0);
        }
    }
    

    Best regards,

    Shuyang

  • Hi Shuyang,

    Understood. Thank you for the additional information. The vApplicationIdleHook() runs as part of the idle tasks which runs when the device is in idle (runs with the lowest possible priority and only runs when no higher priority tasks is running). If you a higher priority task does not pend, then the vApplicationIdleHook() will not execute. You could try disabling the watchdog before you know you will get stuck in a long pending statement or increase the timeout time. After the pending statement is executed, then you could set the settings to the normal values.

    Best Regards,

    Jan