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/AM3358:GateMutex 导致退出

Guru**** 2591240 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/641112/rtos-am3358-gatemutex-causing-exit

器件型号:AM3358

工具/软件:TI-RTOS

早上好、

我最近尝试将 GateMutexPri 添加到项目中、以控制对文件系统、UART、 以太网等以及我所做的初始检查似乎效果良好、但当长时间离开时、它进入_exit (int)、我在窗口中看到下面的红色文本

"无法在"/db/ztree/library/trees/xdctargets/xdctargets-j04/src/gnu/targets/arm/rtsv7A/syscalls.c 上找到源文件"
找到文件或编辑源查找路径以包括其位置。"

ROV 不会像这种反应通常那样报告异常。  我使用的是 XDCtools ver 3.31.0.24_core、SYS/BIOS 版本6.42.3.35、编译器 GNU v4.4.8 (Linaro)、最后是 CCS 版本6.1.00022。

下面是我用来设置 GateMutexPri 的代码、以及一个信标版本、就我所能告诉的、它的工作效果绝对不错。

//#define USE_GATE _mutex_PRI
#ifdef USE_GATE _mutex_PRI
IArgATE _KEY = 0;
GateMutexPri_Handle GATE = NULL;
#else
static Semaphore_handle SEM = NULL;
#endif


Int32_t MutTS_init (













PRI){#ifdeUSE_GATE _mute_mutex (sem)= NULL);#iftex Resource Enpend (pend = void = 0


);#iftex sem (rate_sem (pend);#iftex static Resource (pend);void Resource (pend);#iftex sem (pend_ret_em_em_en_en_ret_em_en_em_en_en_emule_sem (pend);#iftex
#endif
return;
}

静态空 FreeResource (void)
{
if (dONT_Offer_resource =0)
{
#ifdef use_gate_mutex_PRI
GateMutexPri_leave (gate、gate_key);
#else
semaphore_post (sem);
#endif
}
return;
} 

代码非常简单、所以我很难看到我可能会出错的地方、或者我可以尝试不同的地方、我所尝试的只是把密钥作为一个本地的而不是全局的、它没有什么不同。

任何帮助或想法都得到了衷心的恢复。

谢谢

肖恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    RTOS 团队已收到通知。 他们将在这里作出回应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    供参考我的 GateMutex 设置函数如下所示:

    GateMutexPri_Handle SetupGateMutex (void)
    {
    GateMutexPri_Handle GATE _h = NULL;
    Gate_h = GateMutexPri_create (NULL、NULL);
    assert (GATE!= NULL);
    return GATE _h;
    } 

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

    您好 Sean、

    GATE 关键字在哪里定义? 它应该是 ClaimResource 的本地值和从 API 返回的值。 然后、该值应传递到 FreeResource 中。 密钥允许门递归、因此同一线程可以多次调用 ENTER (注:然后需要使门保持相同的次数)。

    Todd

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

    在上面的示例中、它是一个全局变量、我尝试了它作为局部变量、但它似乎没有帮助、但我会按照您的建议更改代码、因为它听起来就像这样、然后再试一次。

    谢谢

    肖恩
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    听起来不错。 让我知道发生了什么。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Todd、  

    没有帮助。  我将功能更改为下面、几个小时后它仍然崩溃。  BTW 此时只有一个上下文访问 GateMutesPri 所保护的内容。

    静态 IARg ClaimResource (void)
    {
    #ifdef use_gate_mutex_return
    GateMutexPri_enter (gate);
    #else
    semaphore_pend (
    
    
    
    
    
    
    
    
    
    sem、BIOS_WAIT_Forever);#endif return 0;}static void FreeResource (IArg key){#ifdef use_mutex_mutex、r_gate_for_return
    
    
    ;#iftex (semipr_emPri) 

    谢谢

    肖恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不好。 发生这种情况时、任务的状态是什么? 您是否在内核中启用了断言(即 BIOS.assertsEnabled = true;在.cfg 文件中)?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Todd、

    以下代码可即时可靠地导致崩溃。

    静态 GateMutexPri_Handle GATE = NULL;
    
    静态空任务(UARg arg0、UARg arg1){
    IARg KEY = GateMutexPri_enter (GATE);
    GateMutexPri_leave (GATE、KEY);
    
    
    void}idle_function (void){
    Task_handle task = NULL;
    
    //设置并输入 GATE
    = paratePri
    !任务
    
    
    
    
    = parategrate&Params (Gate_parategrate=);task_parateg&a (task_parateg&a);任务=任务!任务!任务=任务!任务!任务!任务!任务!任务!任务!任务!任务!任务!任务!任务!任务!任务
    taskParams.priority = 6;
    task = Task_create ((Task_FuncPtr) Task、taskParams、&taskParams、 null);
    assert (task!= NULL);
    
    GateMutexPri_leave (gate、key);//从不从这里返回或按
    应有的方式返回到任务 while (1);
    } 

    当 GateMutexPri_leave 在空闲循环中执行并且永远不会返回到任务中时、会发生中的情况。  在 ROV 中、您可以看到 GateMutexPri 具有空闲循环、并且由于任务已请求选通、其当前优先级为6。  不显示异常、在任务视图中、ti 显示空闲循环已被抢先、优先级为6、另一个任务被阻止。  在我的完整代码中还有另一个对 GatMutexPri 的访问、我错过了、因为你可能会猜到它在空闲循环中、因此我是如何发现它的。

    我曾尝试过:

    • 将空闲循环更改为优先级为1的任务、并且工作正常。
    • 运行空闲循环而不启动任务、运行正常
    • 将 GateMutexPri 更改为标准 GateMutex、同样效果不错

    因此、问题似乎在于空闲任务由于任务的选通请求而继承了更高的优先级、从而导致 SYS/BIOS 崩溃。  不确定我还能做些什么来调查这个问题、如果你能建议一个很好的解决方法、现在我只需要解决这个问题。

    谢谢

    肖恩

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

    您好 Sean、

    虽然在空闲函数中使用 GateMutexPri_enter 很奇怪、但我无法重现您的问题。 您的示例运行正常。 我除了 myIdleFunc 函数被插入空闲状态(在.cfg 文件中)之外没有其他东西。 我确实增加了堆和空闲堆栈大小、以确保没有分配或堆栈问题。

    我运行了该示例、并在空闲函数中具有 GateMutexPri_leave 断点。

    注意:我已经在任务函数中的 GateMutexPr_enter 处达到断点。

    这是“任务”->“详细”视图

    同样奇怪的是空闲优先级为6、但这不会导致问题。

    当我运行时、我在任务函数中的 GateMutexPri_leave 处单击断点。 同样、任务看起来也不错。

    我继续、当我停止时、我看到任务终止、空闲卡在 while (1)循环中。  

    您在此设置中看到什么崩溃?

    Todd

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

    它只是中断_exit (int)、我在窗口中看到下面的红色文本。

    "无法在"/db/ztree/library/trees/xdctargets/xdctargets-j04/src/gnu/targets/arm/rtsv7A/syscalls.c 上找到源文件"
    找到文件或编辑源查找路径以包括其位置。"

    您是否使用与我相同版本的 SYS/BIOS 等尝试过此操作?

    谢谢

    肖恩
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、我使用了相同的版本。 我的 XDCtools 和 CCS 版本稍有不同、但这不应该重要。

    您能否确认您有足够的堆并且堆栈未熔断? 请注意、由于您没有提供任务堆栈、因此正在从堆中分配任务堆栈。 堆大小通过.cfg 文件中的 BIOS.heapSize 变量进行设置。 例如:

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

    是的,我们有128MB,BIOS.heapSize =128*1024*1024;//128M。

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

    您能否使用与上述相同的断点尝试我的确切步骤。 您是否遇到了全部4个问题? 然后、在最后一个断点之后、目标应该刚刚运行、如果您暂停、它将在 while (1);处处于空闲状态。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尝试了这个问题、我还从项目中删除了所有其他内容、以获得该代码、就像我之前有一些课程等、这些课程在 main 之前就已经运行过、因此运气不好。  已尝试改为 c 而不是 cpp、并始终换用至 TI 编译器、并且行为相同

    这是我的配置文件 btw

    VAR Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Error = xdc.useModule('xdc.runtime.Error');
    var Log = xdc.useModule('xdc.runtime.Log');
    var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
    var Main = xdc.useModule('xdc.runtime.Main');
    var SYSMIN = xdc.useModule('xdc.runtime.SysMin');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');
    var GateAll = xdc.useModule('ti.sysbios.gates.GateAll');
    var GateMutexPri = xdc.useModule('ti.sysbios.gates.GateMutexPri');
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var 内存= xdc.useModule('xdc.runtime.Memory');
    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var ti_sysbios_family_arm_A8_intcps_Hwi = xdc.useModule('ti.sysbios.family.arm.a8.intcps.Hwi');
    var 闲置= xdc.useModule('ti.sysbios.knl.Idle');
    var 任务= xdc.useModule('ti.sysbios.knl.Task');
    var 信号量= xdc.useModule('ti.sysbios.knl.Semaphore');
    var 高速缓存= xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    var MMU = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
    
    var ti_SYSBIOS_family_ARM_A8_TimestampProvider = xdc.useModule('ti.sysbios.family.arm.a8.TimestampProvider');
    ti_sysbios_family_arm_a8_TimestampProvider.autoRefreshEnable = false;
    
    /*
    禁用默认情况下启用的模块。
    //
    BIOS.clockEnabled = false;
    BIOS.swiEnabled = false;
    
    //
    *取消注释此行以全局禁用断言。
    *所有模块继承'库'模块的默认值。 您
    *可以使用 Module.common$按模块覆盖这些默认值。
    *禁用断言将节省代码空间并提高运行时性能。
    Defaults.common$.diags_ASSERT = Diags.always_off;
    */
    
    *
    取消注释此行以防止模块名称加载到目标上。
    *模块名称字符串放置在.const 段中。 将此
    *参数设置为 false 将节省.const 段中的空间。 错误和
    *断言消息将包含"未知模块"前缀、而
    不是*实际模块名称。
    Defaults.common$.namedModule = false;
    */
    
    /*
    将系统中的 exit 处理程序数组最小化。 System 模块包括
    *一组函数,这些函数在 System_atexit()中注册,
    *由 System_exit()调用。
    //
    System.maxAtexitHandlers = 4;
    
    /*
    取消注释此行以禁用错误打印功能。
    *禁用时,我们会丢失错误信息,因为
    *不打印错误。 如果
    *由于 Error_print()函数
    *调用 System_printf(),禁用 raiseHook 将节省一些代码空间。
    error.raiseHook =空;
    */
    
    /*
    取消注释此行以防止*在
    目标上加载错误、断言和日志字符串。 这些字符串放置在.const 段中。
    *将此参数设置为 false 将节省.const 段中的空间。
    *错误、断言和日志消息将打印原始 ID 和 args、而不是
    *格式化的消息。
    text.isLoaded = false;
    */
    
    /*
    取消注释此行以在
    程序退出时禁用 SysMin *的字符输出。 SysMin 向循环缓冲区写入字符。
    *可以使用 ROV 中的 SysMin Output 视图查看该缓冲器。
    SysMin.flushAtExit = false;
    *//var
    
    heapSection = new Program.SectionSpec ();
    //heapSection.loadSegment ="DDR3_Hi";
    //heapSection.type ="NOINIT";
    //heapSection.type ="NoLoad";
    
    //创建为全局变量,以便在缺省情况下使用它
    
    ;var/Memphaps.c ="1024;var/Paraphs = news/Parheaps.c ="128;//设置为缺省值*1024
    heapMemParams.sectionName
    //Program.global.noInitHeap = HeapMem.create (heapMemParams);
    //Memory.defaultHeapInstance = Program.global.noinitHeap;
    
    //Program.sectMap[".heapSection"]="DDR3_HI";
    
    //HeapMem.common$.instanceSection =".heapStatic";
    //Program.sectMap[".heapStatic"]= new Program.SectionSpec ();
    //Program.sectMap[".heapStatic"].loadSegment ="DDR3_HI";
    //Program.sectMap[".heapStatic"].runSegment ="DDR3_HI";
    //Program.sectMap[".heapStatic"].type ="NOINIT";
    //Program.sectMap[".heapStatic"].type ="空载";
    
    /*
    从源构建自定义 SYS/BIOS 库。
    //
    BIOS.libType = BIOS.LibType_Custom;
    
    // System_printf ()的循环缓冲区大小*/
    SysMN.bufSize = 0x200;
    
    //
    *为整个系统创建并安装记录器
    */
    var logerBufParams = new LoggerBuf.Params ();
    logerBufParams.numEnags =
    
    Defaults.common$.logger = 0_LoggerBufParams
    Main.common$.diags_INFO;var LogerLoggerLogger0=0=0=;var LoggerLoggerLoggerLoggon.LoggerLoggerLoggors.numEnags == 0=0=0=;var Loggon.LoggerLoggerLoggerLoggerLoggon.Log
    
    
    Defaults.common$.diags_ASSERT
    Defaults.common$.diags_INTERNAL = Diags.always_on;
    
    //
    *高速缓存和 MMU 设置
    *//
    
    启用高速缓
    存。enableCache = true;
    
    //启用 MMU (L1/L2数据高速缓存所需)并配置内存区域
    MMU。enableMMU = true;
    
    //强制外设段为不可高速缓存
    var Peripheral_Attrs ={
    键入:MMU.FirstLevelDesc_section,//段描述符
    TEX:0、
    可缓冲:false,//可缓冲
    可高速缓存:false,//可高速缓存
    可共享:false,//可共享
    NoExecute:true,//不可执行
    };
    
    //为(
    var i=0x44000000;i < 0x8000000000;i = i + 0x00100000){的地址范围内的每个条目设置描述符
    //每个“描述符”条目跨越1MB 地址范围
    Mmu.setFirstLevelDescMeta(i、i、Peripheral_Attrs);
    }
    
    //描述符属性结构
    var DDR3_Attrs ={
    键入:MMU。FirstLevelDesc_section、//段描述符
    TEX:0x1、
    可缓冲:真、 //可缓冲
    可高速缓存:true、 //可高速缓冲
    };
    
    //为
    (var i=0x8000000;i < 0xC0000000;i = i + 0x00100000){的地址范围内的每个条目设置描述符
    //每个“描述符”条目跨越1MB 地址范围
    Mmu.setFirstLevelDescMeta(i、i、DDR3_Attrs);
    }/*
    
    
    BIOS 模块将为系统创建默认堆。
    *指定此默认堆的大小。
    //
    BIOS.heapSize = 128*1024*1024;//128M
    
    IdleFxns[0]=“&idle_function”;
    
    BIOS.cpufreq.lo = 1000000000;
    Task.idleTaskStackSize = 8*1024*1024;//8M
    Task.defaultStackSize
    
    
    
    
    Program.sectMap[".c_int00"]
    
    Program.sectMap[".c_int00"].runAddress = 4*1024;//系统堆栈大小(由 sisscle编 程使用)= 0x80000000;Program.sectMap[".c_int00"].loadAddress = 0x80000000*= 0*/SW1000;SW1000 = 0X1000;SW1000 = 0X1000 = 0X1000;SW1000 = 0X1000;/1000 = 0X1000;/1000 = 0X1000 = 0X1000 = 0X1000;/1000;/1000;/1000
    

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

    您好、Todd、这样它将进入空闲循环中的离开、然后当您步入或运行时、您将获得退出、这样它不会在任务中遇到离开、也不会进入 while (1)。

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

    您好 Sean、

    很抱歉、我对您的描述不是很了解。 让我们在断点上放置标签。

    如果在断点之间运行、则应按此顺序单击断点。 您未达到哪个断点?

    Todd

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

    您好 Todd、

    我没有点击3或4、因为它退出空闲循环中的2号保留调用内部。

    肖恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您说的"离开呼叫内部"是什么意思? 这种情况发生在哪里? 是否还有其他正在运行的处理器(例如、更高优先级的任务或 Hwi)、或者它是否会进入到工作中? 这种情况是否会在这个简单的测试用例中出现?