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.

[参考译文] RTOS/TI-RTOS:tsk_setPri 问题

Guru**** 2537590 points
Other Parts Discussed in Thread: SYSBIOS

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/596477/rtos-ti-rtos-tsk_setpri-problem

器件型号:TI-RTOS

工具/软件:TI-RTOS

我已经将现有项目从 DSP/BIOS 移植到 SYS/BIOS 中、并且在 Task.c 模块的 Task_schedule()中的堆栈检查中遇到了断言的触发。 问题是新任务句柄是无效的指针。 指针值是'ti_SysBIOS_KNL_Task_Module_State_0_readyQ__A'中的一个值、但它不是系统中任何任务的地址。

在研究情况后、我发现如果我不使用 Task_setPri ()函数、我可以解决这个问题。 在不使用 Task_setPri 函数的情况下、项目运行稳定。 (但不符合我们的时序要求)

我还尝试理解 Task_schedule()方法,并将以下过程放在末尾:

静态空 taskTest()
{
//待办事项
uint32 curSet;
void * readyQ;
void *curQ;
void * MaxQ;
UINT maxbit;
UINT ptrSize;
UINT 手柄大小;
int i;

对于(I = 0;I < 7;+I){
if (Task_module->curSet &(1 << i)){
curSet = Task_module->curSet;
readyQ = Task_module->readyQ;
maxbit =内在函数_maxbit (Task_module->curSet);
MaxQ =(Queue_handle)((uint8 *)(Task_module->readyQ)+(uINT)(i*(2*sizeof (ptr))));
curQ = Task_module->curQ;
assert_isTrue (!Queue_empty (MaxQ)、Task_a_badTimeout);
}
}



这个新的附加断言在栈的断言之前被触发。

系统配置:
CPU:28377S
编译器:6.2.6
SYS/BIOS:v6.42.03.35
CGT:3.36.67

请提供一些我可以检查的建议。

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

    您能不能给出调用 Task_setPri 的代码片段以及如何调用它的一些说明(例如、被禁用中断的任务等)。

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

    我简化了代码并检查了问题是否仍然存在。

    方法 sendRequest 从优先级为2 (多)、3 (多)、4、5的任务线程调用。 系统中还有两个优先级为1和6的附加任务。

    int test_Class::sendRequest(){
    
    Task_handle tskHle;
    
    tskHle = Task_self ();
    int oldpri = Task_setPri (tskHle、m_tskPri);
    对于(int i = 0;i < 30000;++I){volatile int tmp = i;}
    Task_setPri (tskHle、oldpri);
    
    返回0;
    
    } 

    其中、在初始化期间 m_tskPri 设置为5

    调用方法 sendRequest()时启用中断(HWI、SWI)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    看起来不错。 您是否使用了 Tools->ROV->Task->Detailed 来验证优先级是否未更改?

    通过删除 Task_setPri、您要避免的根本问题是什么? 它是您提到的堆栈吗? 是否可以尝试增加获取断言的任务的堆栈大小?

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

    >看起来不错。 您是否使用了 Tools->ROV->Task->Detailed 来验证优先级是否未更改?

    我没有抱怨优先级没有改变。

    >通过删除 Task_setPri 可以避免的根本问题是什么?

    由于调度程序状态损坏而重新启动系统。

    >这是您提到的熔断堆栈吗?

    我写过、由于任务指针无效、执行在检查栈大小的断言处停止。 我还在"Memory"窗口中检查了所有任务的堆栈内存+系统堆栈、它们都正常。

    您能否验证我正确理解调度程序行为的函数 taskTest()?

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

    您能否与 Task_setPri ()共享您的原始应用程序? 我可以用它来重新处理我的问题

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

    否 我无法共享原始应用程序。 即使我要共享它、您也无法执行它、因为它取决于许多外部外设(SRAM、闪存磁盘...)

    不过、我可能会尝试创建一些示例应用。

    以及我的附加断言。 我是否正确理解了调度程序? 这将有助于我确定我断开调度程序的位置。

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

    尊敬的 Lukas:

    如果您可以创建一个展示该问题的截止应用程序、这将非常有用。

    此外,是否可以启用任务日志记录? 任务日志可能会显示有用的内容。

    >> 以及我的附加断言。 我是否正确理解了调度程序? 这将有助于我确定我断开调度程序的位置。

    一些内核数据结构似乎已损坏、并导致调度程序发生故障。

    最棒的

    Ashish

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

    您好!

      我还没有能够以一些极简的配置再现这种行为。 我尝试为不同的表达式添加断言。

    最有趣的是检查 Task_module->readyQ (AUX1)(如果它包含有效数据)。 执行一段时间后、它返回一些随机大数(0x6F129A45)、并触发我的断言。

    我已登录 CCS:

    • Task_module (aux)指针包含值0x001001C0。 它是结构 ti_sysbios_KNL_Task_Module_state__V 的正确地址
    • Task_module 中的 readyQ 包含值0x100240。 可能是正确的。

    我不知道变量 AUX1如何包含与 Task_module 结构中保存的值不同的值。

    我的理论是、外部 SRAM 存储器与 EMIF 连接时会出现某种干扰、并尝试读取 Task_module->readyQ 两次并检查这两次。 由于两个变量包含相同的大随机值、因此未确认理论。

    您能给我一些提示吗、因为它看起来不像 SYS/BIOS 有问题、而是 SRAM/EMIF 有问题。

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

    为了确认,AUX1值在每次调用 CHECK 函数时都是一致的,直到它被损坏? 您对 AUX1执行什么检查以确保其一致性? 此外,您是在任务开关挂钩函数中还是在常规任务中执行这些检查?

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

    是的、AUX1在某些 N 次运行时保持一致。

    我在 Sys/BIOS Task.c 中添加了检查 我只需检查地址是否< 0x200000。 我在 Zone6中有地址为0x100000 - 0x200000的数据段

    Tasks.c 中的扩展部分(查找 TODO):

    UINT Task_setPri (Task_Object * tsk、int 优先级)
    {
    int oldPri;
    UINT newMask、tskKey、hwiKey;
    queue_handle newQ;
    void *aux = NULL;
    void * AUX1;
    
    assert_isTrue ((((优先级==1)||(优先级>0)||
    ((优先级=0 && Task_module->idleTask == NULL))&&
    (优先级<(int) Task_numPriorities))、
    Task_a_badPriority);
    
    log_write4 (Task_LM_setPri、(UArg) tsk、(UArg) tsk->fxn、
    (UARg)tsk->priority,(UARg)priority);
    
    tskKey = Task_disable();
    hwiKey = Hwi_disable();
    // aux0 = Task_module->readyQ;
    // if (aux = NULL){
    AUX = Task_module;
    } 否则{
    assert_isTrue (aux =Task_module、Task_a_badTimeout);
    }
    *
    AUX =任务模块;
    oldPri = tsk->priority;
    
    if (oldPri => priority){
    Hwi_restore (hwiKey);
    Task_restore (tskKey);
    返回(oldPri);
    }
    
    如果(优先级< 0){
    NewMask = 0;
    newQ = Task_Module_State_inactiveQ();
    }
    否则{
    //待办事项
    newMask = 1 << priority;
    
    AUX1 = Task_module->readyQ;
    assert_isTrue ((unsigned long) AUX1 < 0x200000、Task_a_badTimeout);
    newQ =(Queue_handle)((uint8 *)(Task_module->readyQ)+
    (uINT)(priority*(2*sizeof (ptr))));
    // assert_isTrue ((unsigned long) newQ < 0x200000、Task_a_badTimeout);
    }
    
    if (tsk->mode =Task_Mode_ready){
    Queue_remove ((Queue_Elem *) tsk);
    
    /*如果 readyQ 中的最后一个任务,请删除 curSet 中的相应位*/
    if (Queue_empty (tsk->readyQ)){
    Task_module->curSet ~tsk->mask;
    }
    
    if (Task_module->curTask == tsk){
    Task_module->curQ = newQ;//强制使用 Task_switch()*/
    /*如果不再是 MaxQ */
    /*将当前任务置于其新的 readyQ 的前面*/
    Queue_insert (((Queue_elem *)(newQ))-> next、(Queue_Elem *) tsk);
    assert_isTrue ((unsigned long) newQ < 0x200000、Task_a_badTimeout);
    }
    否则{
    /*将任务放置在其 readyQ 的末尾*/
    Queue_enqueue (newQ、(Queue_Elem *) tsk);
    }
    
    Task_module->curSet |= newMask;
    }
    
    tsk->priority = priority;
    tsk->mask = newMask;
    tsk->readyQ = newQ;
    
    如果(优先级< 0){
    Task_module->curQ = NULL;//强制一个 Task_switch()*/
    }
    
    Task_module->workFlag = 1;
    //taskTest();
    
    Hwi_restore (hwiKey);
    Task_restore (tskKey);
    
    返回 oldPri;
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    新信息:
    我签入了汇编器、发现 CPU DP 寄存器用于访问 readyQ 地址、我发现 CPU DP 寄存器损坏。 值得注意的是、DP 寄存器包含与 IER 寄存器相同的值。 在我引起的每个系统击穿中都会出现这种情况。 (即使我更改 IER)

    这让我相信堆栈上有问题。 但我通过'dd. exe'检查了程序不组装、并且没有出现推送 DP、推送 DP:ST1、POP DP、POP DP:ST1。
    +
    我还检查了 IER 值是否不等于 MOVW 中的任何值 DP、#number

    在没有上述说明的情况下、如何更改 CPU DP 寄存器?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Lukas:

    这是一个很好的发现。 损坏的 DP 可能会导致模块状态读取损坏。 让我们尝试深入探究一下、以确定 DP 损坏的原因。

    以下是几个问题:
    -您提到了 DP 寄存器值与 IER 相同。 当您更改 IER 时,DP 是否会更改为相同的值?
    -我假设您的应用程序不包含任何修改 DP 的汇编代码。 您可以确认吗?
    -当一个中断发生并且 DP 是其中之一时、C28x 自动将几个寄存器保存在堆栈上。 如果堆栈以某种方式损坏、DP 寄存器可能会恢复为错误的值。 要确认是否有中断在运行,是否可以启用任务和 Hwi 日志记录?

    最棒的
    Ashish

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

    >-您提到 DP 寄存器值与 IER 相同。 当您更改 IER 时,DP 是否会更改为相同的值?

    是的

    >-我假设您的应用程序不包含任何修改 DP 的汇编代码。 您可以确认吗?

    确认

    >若要确认是否有中断在运行、您能否启用任务和 Hwi 日志记录

    稍后会尝试

    我尝试移至最新的编译器、SYS/BIOS 和 xdctools、问题不再出现。 我将使用此配置几天来验证它是否解决了问题。

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

    嗯、几天过去了、问题不再发生。 我认为它已经关闭了。