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.

[参考译文] CC1310:邮箱的堆栈溢出和内存分配

Guru**** 2482205 points
Other Parts Discussed in Thread: CC1310

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

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1227275/cc1310-stack-overflow-and-memory-allocation-for-mailboxes

器件型号:CC1310

您好!  

我的邮箱存在某种内存分配问题、但我不确定问题出在何处。  我在 main 中创建邮箱/信标等、将句柄捆绑在结构中(需要传递超过2个参数)、并通过 arg1参数将它们传递给线程。 创建线程并启动 BIOS。 到目前为止一切顺利。 一旦我达到射频内核设置的点、即频率同步、

    globalRfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    RF_postCmd(globalRfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);

包含邮箱句柄的结构的部分被覆盖、一旦我调用邮箱发布/挂起、程序显然会进入硬故障处理程序。    在"Memory Browser"中、结构的地址是0x20004fb4、靠近指定_stack 的区域的末尾(从0x20004c00开始直到0x20004fff、此时开始是某种存储器锁定区域)。 什么是__stack? 该重复内容的前半部分用0xBE 字节填充、其余部分则填充在 main 中创建的信标句柄等。  

我玩了一个线程 PRIOOS 和禁用/启用某些线程、并且传递邮箱/信标句柄似乎可以正常工作、直到我将 cmdFS 发布到无线电中。 此时、一些(但不是全部)(总共约20到30字节) 似乎随机写入与包含所有句柄的结构相同的区域。 所需要的是、没有一个大块被覆盖、而是这里和那里有几个字节。 所以、大多数信标/邮箱仍然可以工作、而其他信标则不工作(但这个可重现、即我的 TxMailbox 不工作、而 Rx 邮箱工作)。  

我在 SRAM 上受到了一定的限制、"Memory Allocation"视图(在 CCS 中)告诉我、我将使用大约20kB 的90-95%的 SRAM、具体取决于实现方式。 我确实单独检查了任务堆栈要求、并与正在运行的其他线程组合检查、 至少在可能的情况下检查并相应地调整了堆栈大小。 即、让所有内容运行几分钟、在 ROV 任务视图中选中 maxStackSize 并相应地调整堆栈大小、通常有100个字节左右的剩余空间、但在问题发生之前、我绝不会超过任何任务堆栈。 我的确将堆从0x1000字节减少到了0xbb8字节、但是 ROV 仍然告诉我应该仍然有0x360字节可用。  

我的主要内容:

/* RTOS header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Mailbox.h>

/* TI driver files */
#include <ti/drivers/SPI.h>
#include <ti/drivers/I2C.h>
#include <ti/drivers/ADC.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/NVS.h>

/* Own files */
#include "Board.h"
#include "ImageAcquisition.h"
#include "TempAcquisition.h"
#include "RfCommunication.h"
#include "NVMModule.h"
#include "Bloodsensor.h"
#include "MessageObjects.h"

/* Thread stacks */
Char rfTxStack[RF_TX_STACK_SIZE];
Char rfRxStack[RF_RX_STACK_SIZE];
Char rfCtrlStack[RF_CTRL_STACK_SIZE];
Char imgStack[IMG_STACK_SIZE];
Char tmpStack[TMP_STACK_SIZE];
Char bsStack[BS_STACK_SIZE];


int main(void)
{
	Board_initGeneral();

	GPIO_init();
	SPI_init();
	ADC_init();
	NVS_init();
	I2C_init();

	nvmData strNvmData; 
	bool bStatus; 
	bStatus = NVMRead(&strNvmData);

	Mailbox_Handle mbxTxQueue;
	Mailbox_Handle mbxRxQueue;
    Mailbox_Params mbxParams;
	Mailbox_Params_init(&mbxParams);
	mbxTxQueue = Mailbox_create(sizeof(ovePktMsg), NO_TX_MBX_MSG, &mbxParams, NULL);
	mbxRxQueue = Mailbox_create(sizeof(ovePktMsg), NO_RX_MBX_MSG, &mbxParams, NULL);

	rfCfg strRfCfg;

	Semaphore_Handle semTxAllowed;
	Semaphore_Handle semRxAllowed;
	Semaphore_Handle semRxTimeout;
	Semaphore_Params semRfParams;
	Semaphore_Params_init(&semRfParams);
	semRfParams.mode= Semaphore_Mode_BINARY;
	semTxAllowed 	= Semaphore_create(1, &semRfParams, NULL);
	semRxAllowed 	= Semaphore_create(0, &semRfParams, NULL);
	semRxTimeout 	= Semaphore_create(0, &semRfParams, NULL);

	telemetryParams strTelemetryParams; 
	strTelemetryParams.hMbxTxQueue 		= mbxTxQueue; 
	strTelemetryParams.hMbxRxQueue 		= mbxRxQueue; 
	strTelemetryParams.hNvmData			= &strNvmData; 
	strTelemetryParams.hSemTxAllowed	= semTxAllowed; 
	strTelemetryParams.hSemRxAllowed	= semRxAllowed; 
	strTelemetryParams.hSemRxTimeout	= semRxTimeout; 
	strTelemetryParams.hRfCfg			= &strRfCfg;


    Task_Params taskParams;
	Task_Params_init(&taskParams);

    taskParams.stackSize= RF_CTRL_STACK_SIZE; 
    taskParams.stack 	= &rfCtrlStack;
	taskParams.priority = PRIO_RF_CTRL;
	taskParams.arg1 	= (UArg) &strTelemetryParams; 
	Task_create( (Task_FuncPtr) TelemetryControlThread, &taskParams, NULL );

    taskParams.stackSize= RF_TX_STACK_SIZE; 
    taskParams.stack 	= &rfTxStack;
	taskParams.priority = PRIO_RF_TX;
	taskParams.arg1 	= (UArg) &strTelemetryParams; 
	Task_create( (Task_FuncPtr) TelemetryTxThread, &taskParams, NULL );

    taskParams.stackSize= RF_RX_STACK_SIZE;
    taskParams.stack 	= &rfRxStack;
	taskParams.priority = PRIO_RF_RX;
	taskParams.arg1 	= (UArg) &strTelemetryParams; 
	Task_create( (Task_FuncPtr) TelemetrySingleRxThread, &taskParams, NULL );

    taskParams.stackSize= IMG_STACK_SIZE;
    taskParams.stack	= &imgStack;
	taskParams.priority = PRIO_IMG;
	taskParams.arg0 	= (UArg) mbxTxQueue; 
	Task_create( (Task_FuncPtr) ImageAcquisitionThread, &taskParams, NULL ); 

    taskParams.stackSize= TMP_STACK_SIZE;
    taskParams.stack 	= &tmpStack;
	taskParams.priority = PRIO_TMP;
	taskParams.arg0 	= (UArg) mbxTxQueue; 
	Task_create( (Task_FuncPtr) TempAcquisitionThread, &taskParams, NULL );

    taskParams.stackSize= BS_STACK_SIZE;
    taskParams.stack 	= &bsStack;
	taskParams.priority = PRIO_BS;
	taskParams.arg0 	= (UArg) mbxTxQueue; 
	Task_create( (Task_FuncPtr) BloodsensorAcquisitionThread, &taskParams, NULL );

    BIOS_start();				/* start thread scheduling and hope for the best */ 

    return (0);
}

好、更新:  

我将主函数更改如下所示:  

/* Thread stacks */

#define TEST_STACK_SIZE 800

Char testStack[TEST_STACK_SIZE];


int main(void)
{
	Board_initGeneral();

	GPIO_init();
	SPI_init();
	ADC_init();
	NVS_init();
	I2C_init();

    Task_Params taskParams;
	Task_Params_init(&taskParams);

    taskParams.stackSize= TEST_STACK_SIZE;
    taskParams.stack 	= &testStack;
	taskParams.priority = 1;
	Task_create( (Task_FuncPtr) TelemetryThread, &taskParams, NULL );


    BIOS_start();				/* start thread scheduling and hope for the best */ 

    return (0);
}

基本上是将所有内容从主体之前移动到单个线程,即在治疗遥测线程中启动所有其它线程,此时错误不会发生,就我所知,整个系统运行正常, 即没有硬故障并且 LED 按预期的时间间隔闪烁。  

虽然这是进步,现在我更困惑,有点担心我只是幸运,如果我改变了东西,整个事情会再次打破。 在主程序中实例化所有内容时、我是做了一些概念上的错误操作、还是我只是在某个位置幸运/不幸运? 我的行为显然是错误的吗? 很抱歉,如果这有点不连贯,很乐意提供额外信息。  

一般信息:CC1310、CCS v11.1、SimpleLink SDK v4.20.XX、TI-RTOS

您好!

最大值

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

    您好、Max:  

    当您在遥测线程中创建任务时、代码是否与 mainThread 相同?  特别是 arg0和 arg1参数。

    此致、

    SID

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

    尊敬的 Sid:  

    是的、都是一样的。 复制/粘贴、再添加一个函数级别。  

    您好

    最大值  

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

    小更新、我完成了整个系统的实施、现在我再次收到相同的错误。 线程开始运行、一旦我遇到邮箱挂起、系统就会崩溃。 此时、ROV BIOS 扫描没有发现任何错误、也没有任何堆栈溢出。 很显然我只是幸运地在一个特定的情况下,但错误仍然存在,所以我显然是在做一些错误的事情。  

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

    您好、Max:

    我在这里没有看到明显的问题。

    不过、有几件事需要检查。

    1.在 Mailbox_pend()中,msg 指向的目标缓冲区是否足够大,可以容纳任何消息?  

    您是否有可能仅为某些消息溢出该缓冲区? MAILBOX_PEND 被执行时、不对这个进行检查。

    2.您还可以尝试仅提供 taskParams.STACKSIZE 并将 taskParams.stack 参数保留为默认值吗? 不提供堆栈缓冲区指针。 在文档中的示例中、它似乎保留为默认值。

    dev.ti.com/.../index.html

    3.如果它不是2.如果它不是用于调试,您能评论一下射频部分吗?  

    一旦我达到射频内核设置的点、即频率同步、

    全屏
    1
    2
    globalRfHandle = RF_OPEN (&rfObject、&RF_prop、(RF_RadioSetup*)&RF_cmdPropRadioDivSetup、&rfParams);
    RF_postCmd (globalRfHandle、(RF_Op*)和 RF_cmdfs、RF_PriorityNormal、NULL、0);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    包含邮箱句柄的结构的部分被覆盖、一旦我调用邮箱发布/挂起、程序显然会进入硬故障处理程序。    在"Memory Browser"中、结构的地址是0x20004fb4、靠近指定_stack 的区域的末尾(从0x20004c00开始直到0x20004fff、此时开始是某种存储器锁定区域)。

    [/报价]

    这是否仍然有效?  

    3._stack 是系统堆栈的起点。

    此致、

    SID

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

    好的、我不是完全确定、但它似乎现在起作用、至少到5分钟的测试为止。 未显式设置任务堆栈运行进入一个运行时间错误"Error_PolicyMin"。 但是、这似乎可以通过再次增加堆大小来解决。 这样做有什么不利方面吗? 它显然这样也使用了少得多的 SRAM 空间。  

    不管怎样,这让我看着你再次张贴的文档,我不知何故设法呼叫  

    uint8_t stack[STACK_SIZE];
    taskParams.stack = &stack;

    而不是

     

    uint8_t stack[STACK_SIZE];
    taskParams.stack = stack;

    现在我觉得有点愚蠢,希望这是我所有的问题...  

    在哪里可以检查系统堆栈(__stack)的使用情况? 在 ROV 中、我只找到了任务堆栈和堆使用情况。 内存分配窗口只告诉我.stack 的大小为1024 (如.cmd 中定义的那样)、但没有当前的使用情况或溢出。  

    您好

    最大值

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

    尊敬的 Sid:  

    抱歉、接下来的问题。 我所做的错误显然只负责部分内存损坏。 项目的 Tx 侧现在可以正常工作、 我假设 Rx 也可以正常工作、但使用_stack 时、我遇到了更多错误。  如果我调用一个 TI 驱动程序函数、即 RF_OPEN (...)、UART_OPEN (...)、或访问 RF 命令、即 RF_cmdPropTxAdv.startTrigg.triggerType = trig_now;我的_stack 中的某些区域会被覆盖、并且毫不奇怪地发生应用程序崩溃。  

    我有一个在主代码中被实例化的结构、它保存指向某些线程所需的所有邮箱和信标的指针。 创建信标等不是问题(与原始问题中发布的代码类似)、并且将结构传递给各个线程也可行。 此结构的地址有点像0x20004F、因此接近_stack 的末尾(范围为0x20004a20到0x20004fff)、第二个结构位于0x20004fd0。 然后有24个字节、直到_stack 结束。 堆栈的前半部分用0xBE 字节填充、因此我假设它未使用。  

    一切似乎开始运行良好,没有明显的堆栈溢出(在 ROV 视图中),直到我调用 RF_OPEN(..). 此时、0x20004F 之后的区域会被覆盖。 我取消了该部分的注释(正如您建议的那样)、然后代码运行到 uart_open (..) 这同样会覆盖同一区域。 我再次取消了该部分的注释、现在代码一直运行到  

        RF_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropTxAdv.pktConf.bUseCrc = 1;
    它再次覆盖了我的结构。 我认为__stack 上的内存配置或变量使用有问题、但我似乎无法弄清有什么问题。  

    您好!

    最大值

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

    更新:显然问题不在于对 TxAdv 命令的调用、而在于函数调用本身。 我将函数更改为  

    void RfDriverSetupTxCommands(rfCfg* hRfCfg)
    {
    
    	volatile int foo = 1;
    	foo = 2;
    	foo++;
    
        RF_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropTxAdv.pktConf.bUseCrc = 1;
    }
    

    现在相关的存储器区域根本不会被覆盖。 我插入了"volatile foo"语句、只是为了看看问题是与 TxAdv 命令还是在函数条目上、结果就是函数条目...  

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

    我尝试将任务堆栈指针保留在默认值、而只是设置堆栈大小。 如果我理解正确、那么系统将自动在堆上创建任务堆栈空间(需要相应地增加)。  

    不过、相同的错误仍然存在。   

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

    您好、Max:  

    您可以执行几个额外的调试步骤来确定问题的根本原因。

    在 CCS 中、右键单击 您的项目、然后单击添加文件。

    2、将 RFCC26XX_MODE模式 驱动程序源文件添加到您的项目中。 此文件位于"sdk_path\source\ti\drivers\rf"中。

    3.重新编译工程,然后运行调试会话。 现在、您能够单步执行射频驱动器代码。 但请勿修改该文件。 不建议对此进行修改。

    通过它、你也许可以缩小具体细分该结构的指令的范围。  

    4.还请将您的.map 文件与为 rfPacketTx 等示例项目生成的.map 文件进行比较? 可能   

    5.另请仔细检查传递给 RF API 的句柄和参数,如检查是否有任何对象代替指针传递。 这不太可能、但值得检查射频功能的输入参数。  

    此致、
    SID  

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

    尊敬的 Sid:

    谢谢你的信息将尝试这些,如果我再次遇到问题。 就目前而言、它似乎起作用:如上所述、我创建了一个额外的"应用程序线程"(这次也是针对我遇到问题的接收端。) 其中创建了所有共享信标和邮箱。 这似乎解决了问题。 在 BIOS_start()之前在 main 中创建对象似乎有问题  

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

    如果您再次遇到问题、请在此处回答、目前我将关闭该主题