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:从 GPIO 唤醒后发送一个专有数据包

Guru**** 2393205 points
Other Parts Discussed in Thread: LP-EM-CC2340R5

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1466603/cc2340r5-send-a-proprietary-packet-after-wake-up-from-gpio

器件型号:CC2340R5

工具与软件:

我想做一个简单的程序:

从 GPIO 唤醒、发出数据包、进入睡眠状态、等等。
它根据示例 rfPacketTx 和 rfPacketRx 进行工作。

void SendPacket (void)

   
   rcl_init();
   
   rclHandle = RCL_open (&R rclClient、&L LRF_config);
   rclPacketTxCmdGenericTx.rfFrequency =频率;

   /*请尽快启动命令*/
   rclPacketTxCmdGenericTx.common.scheduling = RCL_RCL_ Schedule_Now;
   rclPacketTxCmdGenericTx.common.status = RCL_20A Status_Idle;

   rclPacketTxCmdGenericTx.config.fsOff = FS_OFF;//关闭 FS

   /*在最后一条命令完成时触发回调*/
   rclPacketTxCmdGenericTx.common.runtime.callback = defaultCallback;
   rclPacketTxCmdGenericTx.common.runtime.rclCallbackMask.value = RCL_EventLastCmdDone.value;

   /*将 RCL TX 缓冲数据包设置为数据包缓冲*/
   txPacket =(RCL_表带* Buffer_Tx)&packet;
   

  
   //创建具有随机负载的数据包
   uint8_t * txData;
   txData = RCL_TxBuffer_init (txPacket、NUM_PAD_BYTES、HDR_LEN、MAX_LENGTH);

   //在长度字段之前将标头中的数据清零
   for (int s = 0;s < LEN_INDEX;s++)
   {
       txData[s]= 0U;
   }

   //设置数据包长度
   txData[LEN_index]= MAX_LENGTH;

   //生成随机有效载荷
   对于(int I = HDR_LEN;I < MAX_LENGTH;I++)
   {
       txData[i]= rand ();
   }

   //设置要传输的数据包
   RCL_TxBuffer_put (&R rclPacketTxCmdGenericTx.txBuffers、txPacket);

   rclPacketTxCmdGenericTx.common.status = RCL_20A Status_Idle;

   //提交命令
   RCL_Command_Submit (rclHandle、&R rclPacketTxCmdGenericTx);

   //在命令完成时挂起
   RCL_Command_pend (&R rclPacketTxCmdGenericTx);
   
   while (!gCmdDone)
   {};
       gCMDDONE = 0;
   RCL_Close (rclHandle);
   
}

现在、我想将该程序分为两部分:

以下函数在程序开始时运行一次:
空初始化(空)


   rcl_init();
   
   rclHandle = RCL_open (&R rclClient、&L LRF_config);
   rclPacketTxCmdGenericTx.rfFrequency =频率;

   //立即启动命令
   rclPacketTxCmdGenericTx.common.scheduling = RCL_RCL_ Schedule_Now;
   rclPacketTxCmdGenericTx.common.status = RCL_20A Status_Idle;

   rclPacketTxCmdGenericTx.config.fsOff = FS_OFF;//关闭 FS

   //在最后一条命令完成时触发回调
   rclPacketTxCmdGenericTx.common.runtime.callback = defaultCallback;
   rclPacketTxCmdGenericTx.common.runtime.rclCallbackMask.value = RCL_EventLastCmdDone.value;
 
   //将 RCL TX 缓冲数据包设置为数据包缓冲
   txPacket =(RCL_表带* Buffer_Tx)&packet;

}
每次由 GPIO 唤醒时运行以下函数:
void SendPacket (void)

   
   
   //创建具有随机负载的数据包
   uint8_t * txData;
   txData = RCL_TxBuffer_init (txPacket、NUM_PAD_BYTES、HDR_LEN、MAX_LENGTH);

   //在长度字段之前将标头中的数据清零
   for (int s = 0;s < LEN_INDEX;s++)
   {
       txData[s]= 0U;
   }

   //设置数据包长度
   txData[LEN_index]= MAX_LENGTH;

   //生成随机有效载荷
   对于(int I = HDR_LEN;I < MAX_LENGTH;I++)
   {
       txData[i]= rand ();
   }

   //设置要传输的数据包
   RCL_TxBuffer_put (&R rclPacketTxCmdGenericTx.txBuffers、txPacket);

   rclPacketTxCmdGenericTx.common.status = RCL_20A Status_Idle;

   //提交命令
   RCL_Command_Submit (rclHandle、&R rclPacketTxCmdGenericTx);

   //在命令完成时挂起
   RCL_Command_pend (&R rclPacketTxCmdGenericTx);
   
   while (!gCmdDone)
   {};
       gCMDDONE = 0;
       
}
程序似乎在运行、但它无法正常工作。 从不会接收到包。
每次处理器从睡眠模式唤醒以发出新数据包时、是否必须进行 RCL 初始化?

此致、

Laurent

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Laurent、

    [quote userid="272888" url="~/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1466603/cc2340r5-send-a-proprietary-packet-after-wake-up-from-gpio 是否必须在每次处理器从休眠模式唤醒以发出新数据包时进行 RCL 初始化?

    不需要对每个数据包都执行 RCL_init/open。

    从我的初始外观来看、您的代码应该可以正常工作、因为您的 SendPacket 正在做一切工作、如 rfPacketTx.c 的 while (1)循环中所示

    该程序是否仅执行 TX (类似于 rfPacketTx)? 还是也执行 RX?

    您可以尝试 rfEchoTx 和 rfEchoRx 示例吗?
    (因为这些函数也只调用一次 RCL_init/open)。

    谢谢!
    Toby

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Toby:

    该程序仅执行 Tx。

    如果我没有修改使用 rfPacketTx 和 rfPacketRx、它是有效的。

    我对 rfPacketTx (见下文)进行了修改、它会进入睡眠状态、并在您按下 LP-EM-CC2340R5的 btn2时唤醒。

    按下按钮时、您可以看到 LED 闪烁、但未收到任何消息。

    我在配置方面可能缺少一些东西。

    此致、

    Laurent

    /*
     * Copyright (c) 2013-2022, 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.
     */
    
    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <limits.h>
    
    /* TI Drivers */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/rcl/RCL.h>
    #include <ti/drivers/rcl/RCL_Scheduler.h>
    #include <ti/drivers/rcl/commands/generic.h>
    
    /* SysConfig Generated */
    #include "ti_drivers_config.h"
    #include "ti_radio_config.h"
    
    
    /***** Defines *****/
    /* Packet TX Configuration */
    #define MAX_LENGTH              (30U) // Max packet length
    #define NUM_DATA_ENTRIES        (2U)  // Number of data entries
    #define NUM_PAD_BYTES           (3U)  // Number of pad bytes
    #define PACKET_INTERVAL     500000    // Set packet interval to 500000us or 500ms
    
    /* The index of the length in the TX packet and the length of the header */
    #define LEN_INDEX (RCL_REGISTER_FIELD_PBE_GENERIC_RAM_LENCFG_LENPOS/CHAR_BIT)
    #define HDR_LEN   (LEN_INDEX + (RCL_REGISTER_FIELD_PBE_GENERIC_RAM_LENCFG_NUMLENBITS/CHAR_BIT))
    
    /* Indicates if FS is off */
    #define FS_OFF                  (1U)  // 0: On, 1: Off
    
    #define FREQUENCY               (2440000000U)
    
    
    /***** Variable declarations *****/
    /* RCL Commands */
    extern RCL_CmdGenericTx rclPacketTxCmdGenericTx;
    
    /* RCL Client used to open RCL */
    static RCL_Client rclClient;
    
    /* TX packet buffer */
    uint32_t packet[NUM_DATA_ENTRIES][3 + ((MAX_LENGTH + 10)/ 4)];
    
    /* Counters for RCL event callback */
    volatile uint32_t gCmdDone = 0;     // Command done
    volatile uint32_t Count = 0;
    /***** Callback Functions *****/
    void defaultCallback(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEvents)
    {
        if (rclEvents.lastCmdDone)
        {
            gCmdDone += 1;
    
            GPIO_toggle(CONFIG_GPIO_GLED);
        }
    }
    void BTN_2WakeupCallback(uint_least8_t index) 
    {
      
    	  Count++;
    	
    }
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        /* Initialize and open RCL */
        RCL_init();
    
        RCL_Handle rclHandle = RCL_open(&rclClient, &LRF_config);
    
        /* Set RF frequency */
        rclPacketTxCmdGenericTx.rfFrequency = FREQUENCY;
    
        /* Start command as soon as possible */
        rclPacketTxCmdGenericTx.common.scheduling = RCL_Schedule_Now;
        rclPacketTxCmdGenericTx.common.status = RCL_CommandStatus_Idle;
    
        rclPacketTxCmdGenericTx.config.fsOff = FS_OFF; // Turn off FS
    
        /* Callback triggers on last command done */
        rclPacketTxCmdGenericTx.common.runtime.callback = defaultCallback;
        rclPacketTxCmdGenericTx.common.runtime.rclCallbackMask.value = RCL_EventLastCmdDone.value;
    
        /* Set RCL TX buffer packet to be packet buffer */
        RCL_Buffer_TxBuffer *txPacket = (RCL_Buffer_TxBuffer *)&packet;
    
        GPIO_setConfig(CONFIG_GPIO_GLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_write(CONFIG_GPIO_GLED, CONFIG_GPIO_LED_OFF);
    	
    	
    	// add the btn2 of the lp-emcc2340r5 to wake-up from sleep
    	GPIO_setConfig(BTN_2, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
        GPIO_setCallback(BTN_2, BTN_2WakeupCallback);
        GPIO_enableInt(BTN_2);
    
        while(1)
        {
            
     		Power_sleep(PowerLPF3_ENTERING_STANDBY); // PowerCC2340_IDLE, PowerCC2340_STANDBY, 
    
    		/* Create packet with random payload */
            uint8_t *txData;
            txData = RCL_TxBuffer_init(txPacket, NUM_PAD_BYTES, HDR_LEN, MAX_LENGTH);
    
            /* Zero out data in header before the length field */
            for (int s = 0; s < LEN_INDEX; s++)
            {
                txData[s] = 0U;
            }
    
            /* Set the packet length */
            txData[LEN_INDEX] = MAX_LENGTH;
    
            /* Generate a random payload */
            for (int i = HDR_LEN; i < MAX_LENGTH; i++)
            {
                txData[i] = rand();
            }
    
            /* Set packet to transmit */
            RCL_TxBuffer_put(&rclPacketTxCmdGenericTx.txBuffers, txPacket);
    
            rclPacketTxCmdGenericTx.common.status = RCL_CommandStatus_Idle;
    
            /* Submit command */
            RCL_Command_submit(rclHandle, &rclPacketTxCmdGenericTx);
    
            /* Pend on command completion */
            RCL_Command_pend(&rclPacketTxCmdGenericTx);
    
           /// usleep(PACKET_INTERVAL);
        }
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Laurent、

    感谢您分享更多详细信息/代码、对于我的延迟、我们深表歉意。

    我在代码中看到的主要问题是它会明确调用"Power_sleep"。 不应这样做、因为这样会干扰与 RTOS (FreeRTOS)集成的自动电源管理。 (有关更多详细信息、请 访问:https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1439063/lp-em-cc2340r5-after-putting-device-in-standby-mode-code-continues-running/5542530#5542530)

    我继续并将一些示例/驱动程序组合在一起(rfPacketTx + gpioInterrupt + Semaphore)、它似乎满足您的初始要求"从 GPIO 唤醒、发出数据包、进入睡眠状态"。

    zip 文件已附在后。 它们应该能够在一对 LP-EM-CC2340R5上正常运行。
    /cfs-file/__key/communityserver-discussions-components-files/667/example_5F00_pair.zip

    谢谢!
    Toby

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Toby:

    感谢你的帮助。
    我要尝试、我要让您及时了解最新情况。

    此致、

    Laurent

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Toby:

    您的代码能够按预期运行。 谢谢。

    我仍然有一个问题:我想用一个 RTC 计时器来唤醒处理器。

    我使用以下代码:

    #define RTC_PERIOD_MS 3000
    #define RTC_FREQ 31250  // 31.25 kHz
    HwiP_Struct rtcHwi;
    
    void rtcInterruptHandler(uintptr_t arg) {
        if (HWREG(RTC_BASE + RTC_O_RIS) & RTC_RIS_EV0) {
            HWREG(RTC_BASE + RTC_O_ICLR) |= RTC_RIS_EV0;
    
            GPIO_toggle(CONFIG_GPIO_LED_GREEN);
            HWREG(RTC_BASE + RTC_O_CTL) |= RTC_CTL_RST;
        }
    }
    
    void rtcInit(void) {
        uint32_t rtc_interval = RTC_PERIOD_MS * (RTC_FREQ / 1000);
    
        HWREG(RTC_BASE + RTC_O_CH0CC8U) = rtc_interval;
    
        HWREG(RTC_BASE + RTC_O_IMASK) |= RTC_RIS_EV0;
    
    
        HwiP_construct(&rtcHwi, INT_CPUIRQ0, rtcInterruptHandler, NULL);
        HwiP_enableInterrupt(INT_CPUIRQ0);
    
        HWREG(RTC_BASE + RTC_O_CTL) |= RTC_CTL_RST;
        HWREG(RTC_BASE + RTC_O_CTL) &= ~RTC_CTL_RST;
    }

    此代码位于以下主题: https://e2e.ti.com/support/clock-timing-group/clock-and-timing/f/clock-timing-forum/1442276/lp-em-cc2340r5-rts-timer-waking-up-from-standby-by-rtc-timer

    但不发生中断。

    我的低频时钟配置是:

    如果我读取寄存器 HWREG (RTC_BASE + RTC_O_TIME8U)或 HWREG (RTC_BASE + RTC_O_TIME524M)、我可以看到值发生变化。 这意味着 RTC 时钟在工作。

    计时器配置中是否遗漏了任何内容?

    此致、

    Laurent

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Laurent、

    感谢您的更新! 很高兴听到它在工作。

    关于 RTC 唤醒、您只需调用 SLEEP (your_sleep_time_sec)或 usleep (your_sleep_time_usec)。

    RTOS 层将自动处理唤醒、而这基于 RTC。

    谢谢!
    Toby

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Toby、

    我将尝试使用 usleep 的解决方案、但有一些与输入中断相关的链路。



    使用 RTC、如果我设置位 HWREG (RTC_BASE + RTC_O_ISET)|= 1并且我读取 HWREG (RTC_BASE + RTC_O_RIS)、则该位设置为1。

    这意味着中断发生、但不触发回调函数。

    此致、

    Laurent

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您计划在此应用中使用 RTOS 吗?

    如果愿意、您可以在此处使用与 POSIX 兼容的 FreeRTOS 计时器例程实现:C:\ti\simplelink_lowpower_f3_sdk_8_20_00_119\source\ti\posix\freertos\timer.c

    这可以在 超时时调用用户指定的回调。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、我会使用 RTOS。 主要问题是功耗。

    这就是我需要 RTC 计时器的原因。 我不知道该示例是否使用 RTC 计时器。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    RTOS 使用 RTC 计时器。 例如、调度依赖于计时器例程的下一次唤醒。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Toby:

    我成功地解决了我的问题与一个简单的睡眠,正如你建议我。

    感谢你的帮助。

    此致、

    Laurent