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/TMS320C6678:如何在 IPC Notify 中使用 IPC_Attach 函数?

Guru**** 2616675 points

Other Parts Discussed in Thread: SYSBIOS

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/661148/rtos-tms320c6678-how-to-use-ipc_attach-function-in-ipc-notify

器件型号:TMS320C6678
Thread 中讨论的其他器件:SYSBIOS

工具/软件:TI-RTOS

该文档指出:

对于 BIOS、应该在任务内的'while'循环内调用此函数。 应在循环中调用 Task_sleep()或 Task_yield (),以允许系统中的其它线程执行。 需要在循环中调用此函数、因为远程处理器可能未处于就绪状态。"

while (IPC_Attach (remoteProId)< 0){

Task_sleep (1);
} 

我有一个简单的示例:

#include 

/*-------------------- XDC.Runtime 模块头*/
#include 

/*-------------------- IPC 模块接头 */
#include 
#include 
#include 
/*-------------------- BIOS6模块标题 */
#include 
#include 
#include 

/*-------------------- 从.cfg 头*/
#include 获取全局变量 

#define interrupt_line 0

/*通知应用程序使用的事件编号*/
#define EventID 10

#define masterProc 6
#define sloverNum 6


uint16 received_num=0;

/*
=== cbFxn =====
*此函数已向 Notify 注册。
将任何事件*发送到该处理器时调用该函数。
//
void cbFxn (uint16 ProcID、uint16 lineId、
uint32 EventID、uArgarg、uint32有效载荷)
{
if (处理器!=主处理器)
{
已接收_num ++;
if (received_num == sloverNum)
{
Received_num = 0;
Semaphore_post (semHandle);
}
}
否则{
Semaphore_post (semHandle);
}
}


/*
=== tsk0_func ====
*向下一个处理器发送一个事件,然后在信标上挂起。
*信标由回调函数发布。
//
void tsk0_func (UArg0、UArg0 arg1)
{
int i = 0;
INT 状态;

if (MultiProc_self ()=masterProc){
while (I <sloverNum){
状态= Notify_sendEvent (i、interrupt_line、EventID、i、true);

if (status <0){
继续;
}

system_printf ("materCore 已将事件发送到 slaveCore %d\n",i);
i++;
}

system_printf ("已发送所有事件\n");

Semaphore_pend (semHandle、BIOS_WAIT_FOREVE);

system_printf ("所有从内核都已从主控器件接收到事件\n");

}
否则{
Semaphore_pend (semHandle、BIOS_WAIT_FOREVE);

状态= Notify_sendEvent (masterProc、interrupt_line、EventID、2、true);

if (status < 0){
System_abort ("sendEvent to MasterCore Failed\n");
}

system_printf ("slaveCore %d 已将事件发送到主内核"、MultiProC_self());
}
}

/*
=== main ====
*同步所有处理器(在 IPC_START 中)、调用 BIOS_START 和寄存器
*以接收事件
*/
int main (int argc、Char* argv[])
{
INT 状态;
int ProcID = 0;

status = IPC_START();
如果(状态< 0){
system_abort ("IPC_start failed\n");
}
if (MultiProc_self ()=masterProc){
while (ProcID < sloverNum)
{
while (IPC_Attach (ProcID)){
Task_sleep(1);
}
状态= Notify_registerEvent (ProceID、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);

如果(状态< 0)
{
system_abort ("Notify_registerEvent for sloverCore1 failed\n");
}
ProcID++;
}
}
否则{
while (IPC_Attach (masterProc)){
Task_sleep(1);
}
状态= Notify_registerEvent (masterProc、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);

if (status <0){
system_abort ("Notify_registerEvent for sloverCore1 failed\n");
}
}
BIOS_start();

返回(0);
}

我的 cfg 文件是

//
*版权所有(c) 2012,Texas Instruments Incorporated
*保留所有权利。
*
*
只要
符合以下条件*、允许以源代码和二进制形式重新分发和使用:
*
*源代码的重新分发必须保留上述版权
声明*、此条件列表和以下免责声明。
*
***二进制形式的再发行必须在

*随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
*
***未经

事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
*
*本软件由版权所有者和贡献者"按原样"提供
*、

不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
*贡献者都不对任何直接、间接、偶然、特殊、
*模范、 或相应的损害(包括但不限于
*采购替代产品或服务;丧失使用、数据或利润;
*或业务中断)、但出于任何责任理论
、*无论是在合同中、严格责任还是由于
使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
、*即使已获悉可能会发生此类损坏。
*//
var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');

//
*获取构建设备支持的名称列表。
*即["CORE0"、"Core1"、"Core..."。]
//
var namelist = MultiProc.getDeviceProcNames ();

//
*由于这是一个单映像示例,因此我们(在构建时)不
会为哪个*处理器构建。 因此、我们提供'null'
*作为本地 procName、并使用 MultiProc_setLocalId 在
运行时设置 ProcID *。
*/
MultiProc.setConfig(null,namelist);

var System = xdc.useModule('xdc.runtime.System');
var SysStd = xdc.useModule('xdc.runtime.SysStd');
System.SupportProxy = SysStd;

//应用程序中明确使用的模块*/
var Notify = xdc.useModule('ti.sdo.ipc.Notify');
var IPC = xdc.useModule('ti.sdo.ipc.Ipc');
var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.heapSize = 0x8000;
var 任务 = xdc.useModule('ti.sysbios.knl.Task');

var tsk0 = Task.create ('&tsk0_func');
tsk0.instance.name ="tsk0";

//为避免在 MessageQ 传输中浪费共享内存*/
对于(var i = 0;i < MultiProc.numProcessors;i++){
Ipc.setEntryMeta({
RemoteProId:i、
setupMessageQ:false、
});
}/*

同步所有处理器(这将在 IPC_START 中完成)*/
Ipc.procSync = IPC.ProcSync_PAIR;

//共享内存基址和长度*/
var SHAREMEM = 0x0C000000;
var SHAREDMEMSIZE = 0x00200000;

/*
需要定义共享区域。 IPC 模块使用此
*制作可移植指针。 所有处理器都需要添加此
*调用及其共享存储器区域的基址。
*如果处理器无法访问内存,请勿添加。
*/
var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
SharedRegion.setEntryMeta(0、
{基地址:SHAREMMEM,
Len:SHAREDMEMSIZE、
ownerProId:0、
IsValid:true、
名称:"DDR2_RAM"、
});

//创建计数为0的信标*/
var 信标= xdc.useModule('ti.sysbios.knl.Semaphore');
Program.global.semHandle = semaphore.create (0);

我 不会专门使用 IPC.ProcSync_all。  

调试时、我会遇到以下错误:

TI.SYSBIOS.KNL.Task:第565行:断言失败:A_slepTaskDisabled:在任务调度程序被禁用时无法调用 Task_sleep()。

如何在  IPC Notify 中将 IPC_Attach 函数与 Task_sleep 结合使用

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

    我正在使用:

    • CCSv7.3
    • Processor SDK RTOS v04.02.00
    • 编译器 TI v8.1.4
    • IPC v 3.46.2.04。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Michael、

    Swi_disable()和 Task_disable()将导致此断言失败,并且 Semaphore_pend ()和 Semaphore_post ()调用 Task_disable()。 但是、在 IPC_Attach 之前、您似乎不会使用任何一种。

    我附上了我们的一个示例、该示例使用 IPC_Attach 和 IPC.ProcSync_pair 配置。 它在一个 DO 循环中调用 IPC_Attach、但不使用 Task_sleep、我建议尝试一下、看看它是否也适合您。

    e2e.ti.com/.../1715.ex02_5F00_messageq.zip

    此外、如果您还没有、我建议查看我们的 IPC 用户指南:  

     

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

    你好, Sahin!

    我认为我了解了如何在 IPC Notify 中将 IPC_attach()函数与 Task_sleep()一起使用

    如果使用同步、则必须在任务中执行初始化:

    #include 
    
    /*-------------------- XDC.Runtime 模块头*/
    #include 
    
    /*-------------------- IPC 模块接头 */
    #include 
    #include 
    #include 
    /*-------------------- BIOS6模块标题 */
    #include 
    #include 
    #include 
    
    /*-------------------- 从.cfg 头*/
    #include 获取全局变量 
    
    #define interrupt_line 0
    
    /*通知应用程序使用的事件编号*/
    #define EventID 10
    
    #define masterProc 6
    #define sloverNum 6
    
    
    uint16 received_num=0;
    
    /*
    === cbFxn =====
    *此函数已向 Notify 注册。
    将任何事件*发送到该处理器时调用该函数。
    //
    void cbFxn (uint16 ProcID、uint16 lineId、
    uint32 EventID、uArgarg、uint32有效载荷)
    {
    if (处理器!=主处理器)
    {
    已接收_num ++;
    if (received_num == sloverNum)
    {
    Received_num = 0;
    Semaphore_post (semHandle);
    }
    }
    否则{
    Semaphore_post (semHandle);
    }
    }
    
    
    /*
    === tsk0_func ====
    *向下一个处理器发送一个事件,然后在信标上挂起。
    *信标由回调函数发布。
    //
    void tsk0_func (UArg0、UArg0 arg1)
    {
    int i = 0;
    INT 状态;
    int ProcID = 0;
    
    status = IPC_START();
    如果(状态< 0){
    system_abort ("IPC_start failed\n");
    }
    if (MultiProc_self ()=masterProc){
    while (ProcID < sloverNum)
    {
    while (IPC_Attach (ProcID)){
    Task_sleep(1);
    }
    状态= Notify_registerEvent (ProceID、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);
    
    如果(状态< 0)
    {
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    ProcID++;
    }
    }
    否则{
    while (IPC_Attach (masterProc)){
    Task_sleep(1);
    }
    状态= Notify_registerEvent (masterProc、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);
    
    if (status <0){
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    }
    
    if (MultiProc_self ()=masterProc){
    while (I <sloverNum){
    状态= Notify_sendEvent (i、interrupt_line、EventID、i、true);
    
    if (status <0){
    继续;
    }
    
    system_printf ("materCore 已将事件发送到 slaveCore %d\n",i);
    i++;
    }
    
    system_printf ("已发送所有事件\n");
    
    Semaphore_pend (semHandle、BIOS_WAIT_FOREVE);
    
    system_printf ("所有从内核都已从主控器件接收到事件\n");
    
    }
    否则{
    Semaphore_pend (semHandle、BIOS_WAIT_FOREVE);
    
    状态= Notify_sendEvent (masterProc、interrupt_line、EventID、2、true);
    
    if (status < 0){
    System_abort ("sendEvent to MasterCore Failed\n");
    }
    
    system_printf ("slaveCore %d 已将事件发送到主内核"、MultiProC_self());
    }
    }
    
    /*
    === main ====
    *同步所有处理器(在 IPC_START 中)、调用 BIOS_START 和寄存器
    *以接收事件
    */
    int main (int argc、Char* argv[])
    {
    INT 状态;
    int ProcID = 0;
    
    status = IPC_START();
    如果(状态< 0){
    system_abort ("IPC_start failed\n");
    }
    if (MultiProc_self ()=masterProc){
    while (ProcID < sloverNum)
    {
    while (IPC_Attach (ProcID)){
    Task_sleep(1);
    }
    状态= Notify_registerEvent (ProceID、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);
    
    如果(状态< 0)
    {
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    ProcID++;
    }
    }
    否则{
    while (IPC_Attach (masterProc)){
    Task_sleep(1);
    }
    状态= Notify_registerEvent (masterProc、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);
    
    if (status <0){
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    }
    BIOS_start();
    
    返回(0);
    } 

    您完全不能使用该函数并在 main 中执行初始化:

    int main (int argc、Char* argv[])
    {
    INT 状态;
    int ProcID = 0;
    
    status = IPC_START();
    如果(状态< 0){
    system_abort ("IPC_start failed\n");
    }
    if (MultiProc_self ()=masterProc){
    while (ProcID < sloverNum)
    {
    //等待连接
    DO {
    status = IPC_Attach (ProcID);
    } while (status < 0);
    
    状态= Notify_registerEvent (ProceID、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);
    
    如果(状态< 0)
    {
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    ProcID++;
    }
    }
    else{
    //等待连接
    DO{
    status = IPC_Attach (masterProc);
    }while (status < 0);
    
    状态= Notify_registerEvent (masterProc、interrupt_line、EventID、(Notif_FnNotifyCbck) cbFxn、NULL);
    
    if (status <0){
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    }
    BIOS_start();
    
    返回(0);
    } 

    如果在 cfg-file 中使用所有处理器的同步(Ipc.procSync = IPC.ProcSync_all)、则使用该函数

    需要 IPC_attach():它在函数 IPC_START()中自动调用。 此情况的一个示例如下:

    #include 
    
    /*-------------------- XDC.Runtime 模块头*/
    #include 
    
    /*-------------------- IPC 模块接头 */
    #include 
    #include 
    #include 
    /*-------------------- BIOS6模块标题 */
    #include 
    #include 
    #include 
    
    /*-------------------- 从.cfg 头*/
    #include 获取全局变量 
    
    #define interrupt_line 0
    
    /*通知应用程序使用的事件编号*/
    #define EventID 10
    
    //运行循环的次数*/
    #define NUMLOOPS 5
    
    uint32 times=0;
    uint16 recvnumes=0;
    
    #define masterProc 0
    #define sloverProc1
    #define sloverProc2
    #define sloverNum 2
    
    /*
    === cbFxn =====
    *此函数已向 Notify 注册。
    将任何事件*发送到该处理器时调用该函数。
    //
    void cbFxn (uint16 ProcID、uint16 lineId、
    uint32 EventID、uArgarg、uint32有效载荷)
    {
    /*有效载荷是序列号。 //
    
    if (ProcID!= masterProc)
    {
    recvnumes++;
    if (recvnumes=sloverNum)
    {
    recvnumes=0;
    Semaphore_post (semHandle);
    }
    }
    否则{
    时间=有效载荷;
    Semaphore_post (semHandle);
    }
    }
    
    
    //*
    === tsk0_func ====
    *向下一个处理器发送一个事件,然后在信标上挂起。
    *信标由回调函数发布。
    //
    void tsk0_func (UArg0、UArg0 arg1)
    {
    int i = 1;
    INT 状态;
    status = IPC_START();
    如果(状态< 0){
    system_abort ("IPC_start failed\n");
    }
    
    if (MultiProc_self ()=masterProc)
    {
    while (IPC_Attach (sloverProc1)){
    Task_sleep(1);
    }
    while (IPC_Attach (sloverProc2)){
    Task_sleep(1);
    }
    
    状态= Notify_registerEvent (sloverProc1、interrupt_line、EventID、
    (notify_FnNotifyCbck) cbFxn、NULL);
    如果(状态< 0){
    system_abort ("Notify_registerEvent for sloverCore1 failed\n");
    }
    
    状态= Notify_registerEvent (sloverProc2、interrupt_line、EventID、
    (notify_FnNotifyCbck) cbFxn、NULL);
    如果(状态< 0){
    System_abort ("Notify_registerEvent for sloverCor2 failed \n");
    }
    
    }
    否则{
    
    while (IPC_Attach (masterProc)){
    Task_sleep(1);
    }
    
    状态= Notify_registerEvent (masterProc、interrupt_line、EventID、
    (notify_FnNotifyCbck) cbFxn、NULL);
    如果(状态< 0){
    system_abort ("Notify_registerEvent for masterCore0 failed\n");
    }
    
    }
    
    if (MultiProc_self ()=masterProc){
    while (i <= NUMLOOPS){
    
    /*将事件发送到下一个处理器*/
    状态= Notify_sendEvent (sloverProc1、interrupt_line、EventID、I、
    true);
    状态= Notify_sendEvent (sloverProc2、interrupt_line、EventID、I、
    true);
    
    /*继续,直至远程侧朝上*/
    如果(状态< 0){
    继续;
    }
    
    System_printf ("MasterCore 已将事件发送到%d\n"、i 中的 SloverCores);
    
    /*等待 cbFxn 发布信标来释放*/
    Semaphore_pend (semHandle、BIOS_wait_forever);
    
    System_printf ("MasterCore 从%d\n",i 中的所有 SloverCores 接收到的事件);
    
    下一次迭代的/*增量*/
    i++;
    }
    }
    否则{
    while (times < NUMLOOPS){
    
    /*在信标上永远等待、信标在回调中发布*/
    Semaphore_pend (semHandle、BIOS_wait_forever);
    
    System_printf ("SloverCore%d 在%d\n"中从 MasterCore 接收到事件、MultiProc_self ()、时间);
    
    
    /*将事件发送到下一个处理器*/
    状态= Notify_sendEvent (masterProc、interrupt_line、EventID、Times、
    true);
    如果(状态< 0){
    System_abort ("sendEvent to MasterCore Failed\n");
    }
    
    System_printf ("SloverCore%d 在%d\n"中从 MasterCore 发送事件、MultiProc_self ()、时间);
    }
    }
    
    System_printf ("测试完成\n");
    BIOS_exit (0);
    }
    
    /*
    === main ====
    *同步所有处理器(在 IPC_START 中)、调用 BIOS_START 和寄存器
    *以接收事件
    */
    int main (int argc、Char* argv[])
    {
    
    BIOS_start();
    
    返回(0);
    } 

    请告诉我、我的论点是否正确?

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

    您好、Michael、

    正确! 如果执行 IPC.ProcSync_All、则可以在 cfg 文件中指定要附加到的内核。

    此外,我当时没有意识到它,但导致断言失败的原因是任务调度程序被禁用,直到在 main 末尾由 BIOS_start()启用。 请参阅: