CCS+C6678LE开发记录11:多核协作(IPC)入门

Posted 六月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCS+C6678LE开发记录11:多核协作(IPC)入门相关的知识,希望对你有一定的参考价值。

为更好地发挥C6678的多核性能,需要用到多核协作。幸运的是,我们可以使用官方提供的IPC模块。

IPC=Inter-Processor Communication, 核间通信,粗略来说就是多核之间进行信息、数据交换。

作为入门篇,本文不打算深入讨论IPC,仅仅列出自带的两个简单示例:Notify和MessageQ.

"通知"(Notify)模型

"消息队列"(MessageQ)模型

 

以下介绍Notify示例的创建过程以及测试结果。

首先新建一个项目,取名demo_ipcNotify,项目类型从模板中选择

选择"IPC and I/O Examples"分支下的"C6678 Examples"

然后【Next】,在XDCtools version选择3.23.4.60(不带"core"后缀的那一个)

创建并编译链接无错误之后执行Debug

建议勾选下方的"Create a debug group for selected cores"

如果没有选,可以在稍后执行如下操作

分组的好处是,当有多个核心加载时,不必一一启动,只需要在组别上点击启动(分组下所有核心全部启动)

这样做虽然不是必要的,但建议这样做。

如果勾选了分组,将会是如下这个样子,测试的时候只需在"Group 1"上点击一次【Step On(继续将执行)】

 

以下是测试示例的输出(中间有部分省略)

[plain] view plain copy

 print?

  1. [C66xx_6] main: MultiProc id = 6  
  2. main: MultiProc name = CORE6  
  3. [C66xx_7] main: MultiProc id = 7  
  4. main: MultiProc name = CORE7  
  5. [C66xx_0] main: MultiProc id = 0  
  6. [C66xx_1] main: MultiProc id = 1  
  7. [C66xx_2] main: MultiProc id = 2  
  8. [C66xx_3] main: MultiProc id = 3  
  9. [C66xx_4] main: MultiProc id = 4  
  10. [C66xx_5] main: MultiProc id = 5  
  11. [C66xx_0] main: MultiProc name = CORE0  
  12. [C66xx_1] main: MultiProc name = CORE1  
  13. [C66xx_2] main: MultiProc name = CORE2  
  14. [C66xx_3] main: MultiProc name = CORE3  
  15. [C66xx_4] main: MultiProc name = CORE4  
  16. [C66xx_5] main: MultiProc name = CORE5  
  17. [C66xx_0] tsk1_func: Sent request #0 to CORE1  
  18. [C66xx_1] tsk1_func: Received request #1 from CORE0  
  19. tsk1_func: Sent request #1 to CORE2  
  20. [C66xx_2] tsk1_func: Received request #1 from CORE1  
  21. tsk1_func: Sent request #1 to CORE3  
  22. [C66xx_3] tsk1_func: Received request #1 from CORE2  
  23. tsk1_func: Sent request #1 to CORE4  
  24. ///省略///  
  25. [C66xx_3] tsk1_func: Received request #10 from CORE2  
  26. tsk1_func: Sent request #10 to CORE4  
  27. Test completed  
  28. [C66xx_4] tsk1_func: Received request #10 from CORE3  
  29. tsk1_func: Sent request #10 to CORE5  
  30. Test completed  
  31. [C66xx_5] tsk1_func: Received request #10 from CORE4  
  32. tsk1_func: Sent request #10 to CORE6  
  33. Test completed  
  34. [C66xx_6] tsk1_func: Received request #10 from CORE5  
  35. tsk1_func: Sent request #10 to CORE7  
  36. Test completed  
  37. [C66xx_7] tsk1_func: Received request #10 from CORE6  
  38. tsk1_func: Sent request #10 to CORE0  
  39. Test completed  
  40. [C66xx_0] tsk1_func: Received request #10 from CORE7  
  41. Test completed  

 

类似的可以新建一个MessageQ示例项目

后续步骤同上,测试的输出如下(中间有部分省略)

[plain] view plain copy

 print?

  1. [C66xx_1] Start the main loop  
  2. [C66xx_5] Start the main loop  
  3. [C66xx_7] Start the main loop  
  4. [C66xx_6] Start the main loop  
  5. [C66xx_0] Start the main loop  
  6. [C66xx_2] Start the main loop  
  7. [C66xx_3] Start the main loop  
  8. [C66xx_4] Start the main loop  
  9. [C66xx_0] Sending a message #1 to CORE1  
  10. [C66xx_1] Sending a message #1 to CORE2  
  11. [C66xx_2] Sending a message #1 to CORE3  
  12. [C66xx_3] Sending a message #1 to CORE4  
  13. [C66xx_4] Sending a message #1 to CORE5  
  14. [C66xx_5] Sending a message #1 to CORE6  
  15. [C66xx_6] Sending a message #1 to CORE7  
  16. [C66xx_7] Sending a message #1 to CORE0  
  17. ///省略///  
  18. [C66xx_5] Sending a message #9 to CORE6  
  19. [C66xx_6] Sending a message #9 to CORE7  
  20. [C66xx_7] Sending a message #9 to CORE0  
  21. [C66xx_0] Sending a message #10 to CORE1  
  22. [C66xx_1] Sending a message #10 to CORE2  
  23. The test is complete  
  24. [C66xx_2] Sending a message #10 to CORE3  
  25. The test is complete  
  26. [C66xx_3] Sending a message #10 to CORE4  
  27. The test is complete  
  28. [C66xx_4] Sending a message #10 to CORE5  
  29. The test is complete  
  30. [C66xx_5] Sending a message #10 to CORE6  
  31. The test is complete  
  32. [C66xx_6] Sending a message #10 to CORE7  
  33. The test is complete  
  34. [C66xx_7] Sending a message #10 to CORE0  
  35. The test is complete  
  36. [C66xx_0] The test is complete  


最后附上示例代码(模板生成的,仅删除部分注释,其他未做改动)

示例Notify的主要代码

[cpp] view plain copy

 print?

  1. #include <xdc/std.h>  
  2. /*  XDC.RUNTIME module Headers    */  
  3. #include <xdc/runtime/System.h>  
  4. /*  IPC module Headers           */  
  5. #include <ti/ipc/MultiProc.h>  
  6. #include <ti/ipc/Notify.h>  
  7. #include <ti/ipc/Ipc.h>  
  8. /*  Bios6 module Headers         */  
  9. #include <ti/sysbios/knl/Semaphore.h>  
  10. #include <ti/sysbios/knl/Task.h>  
  11. #include <ti/sysbios/BIOS.h>  
  12. /*  To get globals from .cfg Header */  
  13. #include <xdc/cfg/global.h>  
  14. #define INTERRUPT_LINE  0  
  15. /* Notify event number that the app uses */  
  16. #define EVENTID         10  
  17. /* Number of times to run the loop */  
  18. #define NUMLOOPS        10   
  19.     
  20. UInt32 seq = 0;  
  21. UInt16 recvProcId;  
  22. UInt16 srcProc, dstProc;  
  23.     
  24. /* 
  25.  *  ======== cbFxn ======== 
  26.  *  This function was registered with Notify. It is called when any event is 
  27.  *  sent to this processor. 
  28.  */  
  29. Void cbFxn(UInt16 procId, UInt16 lineId, UInt32 eventId, UArg arg,  
  30.         UInt32 payload)  
  31. {  
  32.     /* The payload is a sequence number. */  
  33.     recvProcId = procId;  
  34.     seq = payload;  
  35.     Semaphore_post(semHandle);  
  36. }  
  37.     
  38. /* 
  39.  *  ======== tsk0_func ======== 
  40.  *  Sends an event to the next processor then pends on a semaphore. 
  41.  *  The semaphore is posted by the callback function. 
  42.  */  
  43. Void tsk0_func(UArg arg0, UArg arg1)  
  44. {  
  45.     Int i = 1;  
  46.     Int status;  
  47.     
  48.     if (MultiProc_self() == 0)  
  49.     {  
  50.         while (i <= NUMLOOPS)  
  51.         {  
  52.             /* Send an event to the next processor */  
  53.             status = Notify_sendEvent(dstProc, INTERRUPT_LINE, EVENTID, i,  
  54.             TRUE);  
  55.     
  56.             /* Continue until remote side is up */  
  57.             if (status < 0)  
  58.             {  
  59.                 continue;  
  60.             }  
  61.     
  62.             System_printf("tsk1_func: Sent request #%d to %s\\n", seq,  
  63.                     MultiProc_getName(dstProc));  
  64.     
  65.             /* Wait to be released by the cbFxn posting the semaphore */  
  66.             Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);  
  67.     
  68.             System_printf("tsk1_func: Received request #%d from %s\\n", seq,  
  69.                     MultiProc_getName(recvProcId));  
  70.     
  71.             /* increment for next iteration */  
  72.             i++;  
  73.         }  
  74.     }  
  75.     else  
  76.     {  
  77.         while (seq < NUMLOOPS)  
  78.         {  
  79.             /* wait forever on a semaphore, semaphore is posted in callback */  
  80.             Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);  
  81.     
  82.             System_printf("tsk1_func: Received request #%d from %s\\n", seq,  
  83.                     MultiProc_getName(recvProcId));  
  84.     
  85.             /* Send an event to the next processor */  
  86.             status = Notify_sendEvent(dstProc, INTERRUPT_LINE, EVENTID, seq,  
  87.             TRUE);  
  88.             if (status < 0)  
  89.             {  
  90.                 System_abort("sendEvent failed\\n");  
  91.             }  
  92.     
  93.             System_printf("tsk1_func: Sent request #%d to %s\\n", seq,  
  94.                     MultiProc_getName(dstProc));  
  95.         }  
  96.     }  
  97.     
  98.     System_printf("Test completed\\n");  
  99.     BIOS_exit(0);  
  100. }  
  101.     
  102. /* 
  103.  *  ======== main ======== 
  104.  *  Synchronizes all processors (in Ipc_start), calls BIOS_start, and registers  
  105.  *  for an incoming event 
  106.  */  
  107. Int main(Int argc, Char* argv[])  
  108. {  
  109.     Int status;  
  110.     UInt numProcs = MultiProc_getNumProcessors();  
  111.     
  112.     /* 
  113.      *  Determine which processors Notify will communicate with based on the 
  114.      *  local MultiProc id.  Also, create a processor-specific Task. 
  115.      */  
  116.     srcProc = ((MultiProc_self() - 1 + numProcs) % numProcs);  
  117.     dstProc = ((MultiProc_self() + 1) % numProcs);  
  118.     
  119.     System_printf("main: MultiProc id = %d\\n", MultiProc_self());  
  120.     System_printf("main: MultiProc name = %s\\n",  
  121.             MultiProc_getName(MultiProc_self()));  
  122.     
  123.     /* 
  124.      *  Ipc_start() calls Ipc_attach() to synchronize all remote processors 
  125.      *  because \'Ipc.procSync\' is set to \'Ipc.ProcSync_ALL\' in *.cfg 
  126.      */  
  127.     status = Ipc_start();  
  128.     if (status < 0)  
  129.     {  
  130.         System_abort("Ipc_start failed\\n");  
  131.     }  
  132.     
  133.     /* 
  134.      *  Register call back with Notify. It will be called when the processor 
  135.      *  with id = srcProc sends event number EVENTID to this processor. 
  136.      */  
  137.     status = Notify_registerEvent(srcProc, INTERRUPT_LINE, EVENTID,  
  138.             (Notify_FnNotifyCbck) cbFxn, NULL);  
  139.     if (status < 0)  
  140.     {  
  141.         System_abort("Notify_registerEvent failed\\n");  
  142.     }  
  143.     
  144.     BIOS_start();  
  145.     
  146.     return (0);  
  147. }  

 

示例MessageQ的主要代码

[cpp] view plain copy

 print?

  1. #include <xdc/std.h>  
  2. #include <string.h>  
  3. /*  XDC.RUNTIME module Headers    */  
  4. #include <xdc/runtime/System.h>  
  5. #include <xdc/runtime/IHeap.h>  
  6. /*  IPC module Headers         

    以上是关于CCS+C6678LE开发记录11:多核协作(IPC)入门的主要内容,如果未能解决你的问题,请参考以下文章

    DSP6678 多核导航器

    DSP篇--C6678功能调试系列之网络调试

    pru ccs开发如何制作bin文件给内核加载

    SylixOS DSP upgrade命令解析

    TMS320F28335项目开发记录1_CCS的使用介绍

    DSP篇--C6678功能调试系列之DDR3调试