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           */  
  7. #include <ti/ipc/Ipc.h>  
  8. #include <ti/ipc/MessageQ.h>  
  9. #include <ti/ipc/HeapBufMP.h>  
  10. #include <ti/ipc/MultiProc.h>  
  11. /*  BIOS6 module Headers         */  
  12. #include <ti/sysbios/BIOS.h>  
  13. #include <ti/sysbios/knl/Task.h>  
  14. /*  To get globals from .cfg Header */  
  15. #include <xdc/cfg/global.h>  
  16.   
     
  17. #define HEAP_NAME   "myHeapBuf"  
  18. #define HEAPID      0  
  19. #define NUMLOOPS    10  
  20. Char localQueueName[10];  
  21. Char nextQueueName[10];  
  22. UInt16 nextProcId;  
  23.   
     
  24. /* 
  25.  *  ======== tsk0_func ======== 
  26.  *  Allocates a message and ping-pongs the message around the processors. 
  27.  *  A local message queue is created and a remote message queue is opened. 
  28.  *  Messages are sent to the remote message queue and retrieved from the 
  29.  *  local MessageQ. 
  30.  */  
  31. Void tsk0_func(UArg arg0, UArg arg1)  
  32. {  
  33.     MessageQ_Msg msg;  
  34.     MessageQ_Handle messageQ;  
  35.     MessageQ_QueueId remoteQueueId;  
  36.     Int status;  
  37.     UInt16 msgId = 0;  
  38.     HeapBufMP_Handle heapHandle;  
  39.     HeapBufMP_Params heapBufParams;  
  40.   
     
  41.     if (MultiProc_self() == 0)  
  42.     {  
  43.         /* 
  44.          *  Create the heap that will be used to allocate messages. 
  45.          */  
  46.         HeapBufMP_Params_init(&heapBufParams);  
  47.         heapBufParams.regionId = 0;  
  48.         heapBufParams.name = HEAP_NAME;  
  49.         heapBufParams.numBlocks = 1;  
  50.         heapBufParams.blockSize = sizeof(MessageQ_MsgHeader);  
  51.         heapHandle = HeapBufMP_create(&heapBufParams);  
  52.         if (heapHandle == NULL)  
  53.         {  
  54.             System_abort("HeapBufMP_create failed\n");  
  55.         }  
  56.     }  
  57.     else  
  58.     {  
  59.         /* Open the heap created by the other processor. Loop until opened. */  
  60.         do  
  61.         {  
  62.             status = HeapBufMP_open(HEAP_NAME, &heapHandle);  
  63.             /* 
  64.              *  Sleep for 1 clock tick to avoid inundating remote processor 
  65.              *  with interrupts if open failed 
  66.              */  
  67.             if (status < 0)  
  68.             {  
  69.                 Task_sleep(1);  
  70.             }  
  71.         } while (status < 0);  
  72.     }  
  73.   
     
  74.     /* Register this heap with MessageQ */  
  75.     MessageQ_registerHeap((IHeap_Handle) heapHandle, HEAPID);  
  76.   
     
  77.     /* Create the local message queue */  
  78.     messageQ = MessageQ_create(localQueueName, NULL);  
  79.     if (messageQ == NULL)  
  80.     {  
  81.         System_abort("MessageQ_create failed\n");  
  82.     }  
  83.   
     
  84.     /* Open the remote message queue. Spin until it is ready. */  
  85.     do  
  86.     {  
  87.         status = MessageQ_open(nextQueueName, &remoteQueueId);  
  88.         /* 
  89.          *  Sleep for 1 clock tick to avoid inundating remote processor 
  90.          *  with interrupts if open failed 
  91.          */  
  92.         if (status < 0)  
  93.         {  
  94.             Task_sleep(1);  
  95.         }  
  96.     } while (status < 0);  
  97.   
     
  98.     if (MultiProc_self() == 0)  
  99.     {  
  100.         /* Allocate a message to be ping-ponged around the processors */  
  101.         msg = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));  
  102.         if (msg == NULL)  
  103.         {  
  104.             System_abort("MessageQ_alloc failed\n");  
  105.         }  
  106.   
     
  107.         /* 
  108.          *  Send the message to the next processor and wait for a message 
  109.          *  from the previous processor. 
  110.          */  
  111.         System_printf("Start the main loop\n");  
  112.         while (msgId < NUMLOOPS)  
  113.         {  
  114.             /* Increment...the remote side will check this */  
  115.             msgId++;  
  116.             MessageQ_setMsgId(msg, msgId);  
  117.   
     
  118.             System_printf("Sending a message #%d to %s\n", msgId,nextQueueName);  
  119.   
     
  120.             /* send the message to the remote processor */  
  121.             status = MessageQ_put(remoteQueueId, msg);  
  122.             if (status < 0)  
  123.             {  
  124.                 System_abort("MessageQ_put had a failure/error\n");  
  125.             }  
  126.   
     
  127.             /* Get a message */  
  128.             status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);  
  129.             if (status < 0)  
  130.             {  
  131.                 System_abort("This should not happen since timeout is forever\n");  
  132.             }  
  133.         }  
  134.     }  
  135.     else  
  136.     {  
  137.         /* 
  138.          *  Wait for a message from the previous processor and 
  139.          *  send it to the next processor 
  140.          */  
  141.         System_printf("Start the main loop\n");  
  142.         while (TRUE)  
  143.         {  
  144.             /* Get a message */  
  145.             status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);  
  146.             if (status < 0)  
  147.             {  
  148.                 System_abort("This should not happen since timeout is forever\n");  
  149.             }  
  150.   
     
  151.             System_printf("Sending a message #%d to %s\n",MessageQ_getMsgId(msg),   
  152.                 nextQueueName);  
  153.   
     
  154.             /* Get the message id */  
  155.             msgId = MessageQ_getMsgId(msg);  
  156.   
     
  157.             /* send the message to the remote processor */  
  158.             status = MessageQ_put(remoteQueueId, msg);  
  159.             if (status < 0)  
  160.             {  
  161.                 System_abort("MessageQ_put had a failure/error\n");  
  162.             }  
  163.   
     
  164.             /* test done */  
  165.             if (msgId >= NUMLOOPS)  
  166.             {  
  167.                 break;  
  168.             }  
  169.         }  
  170.     }  
  171.   
     
  172.     System_printf("The test is complete\n");  
  173.     BIOS_exit(0);  
  174. }  
  175.   
     
  176. /* 
  177.  *  ======== main ======== 
  178.  *  Synchronizes all processors (in Ipc_start) and calls BIOS_start 
  179.  */  
  180. Int main(Int argc, Char* argv[])  
  181. {  
  182.     Int status;  
  183.   
     
  184.     nextProcId = (MultiProc_self() + 1) % MultiProc_getNumProcessors();  
  185.   
     
  186.     /* Generate queue names based on own proc ID and total number of procs */  
  187.     System_sprintf(localQueueName, "%s", MultiProc_getName(MultiProc_self()));  
  188.     System_sprintf(nextQueueName, "%s", MultiProc_getName(nextProcId));  
  189.   
     
  190.     /* 
  191.      *  Ipc_start() calls Ipc_attach() to synchronize all remote processors 
  192.      *  because ‘Ipc.procSync‘ is set to ‘Ipc.ProcSync_ALL‘ in *.cfg 
  193.      */  
  194.     status = Ipc_start();  
  195.     if (status < 0)  
  196.     {  
  197.         System_abort("Ipc_start failed\n");  
  198.     }  
  199.   
     
  200.     BIOS_start();  
  201.   
     
  202.     return (0);  
  203. }  

本文原创,博文地址
http://blog.csdn.net/fengyhack/article/details/44034941

时间: 2024-11-05 11:58:08

CCS+C6678LE开发记录11:多核协作(IPC)入门的相关文章

CCS+C6678LE开发记录12:UIA组件的安装

在安装了CCS 6.0版本的IDE和最新版的MCSDK后似乎一切都很完美,但事实并非如此. 当我试图编译SDK附带的image_processing (IPC based) demo时出现如下错误: 实际上在导入(Import)这个demo的时候就提示错误 这个错误表明需要安装UIA组件,但是CCSv6+MCSDK目录下均没有UIA相关内容. 如此判断应该是UIA组件缺失,需要另行安装. 以下介绍在CCSv6中如何安装UIA组件. 首先打开应用中心[View]-->[CCS App Center

个人知识管理系统Version1.0开发记录(11)

关 键 字 搜 索 (1)匹配单个属性的关键字:(2)匹配单个对象的关键字:(3)匹配对象集合的关键字:(4)基于事件驱动的:(5)实时搜索,参考win7的搜索功能. 1.备份,java代码,数据库数据. 2.oracle数据库,用户操作. (1)查看数据库默认表空间. select * from database_properties;(2)创建用户create user 用户名 identified by 密码 默认表空间 临时表空间create user dyl identified by

Android艺术开发探索——第二章:IPC机制(下)

Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvider ContentProvider是Android中提供的专门用来不同应用之间数据共享的方式,从这一点来看,他天生就是适合进程间通信,和Messenger一样,ContentProvider的底层实现同样也是Binder,由此可见,Binder在Android系统中是何等的重要,虽然Conten

LNMP系列网站零基础开发记录(三)

[目录] 扯淡吹逼之开发前奏 Django 开发环境搭建及配置 web 页面开发 Django app开发 Django 站点管理 Python 简易爬虫开发 Nginx&uWSGI 服务器配置 ... 三.web页面开发 好吧,本来想单独写一章bootstrap的,但是前端确实没什么好写的,这里我们直接结合实际直接开搞吧.做WEB我习惯先把想要的页面模板做完,然后再根据razar或者这里要用到的django template修改.美工确实不太好,P得一手烂图,所以一般都用现成的开源框架,这里我

phpcms程序二次开发记录

1. phpcms/base.php 中的 pc_base 类 静态类,主要加载各个文件使用.2. pc_base 中 load_sys_func 等带 sys的函数,基本都是加载 lib下文件. func加载functions下: class 加载 class下3. pc_base 中 函数一般第一个参数为文件名,第二个参数为路径,第3个参数有一般为:加载类是否实体化4. pc_base 中 load_app开头则为加载modules下的 functions和class等5. 网站开始入口控制

个人知识管理系统Version1.0开发记录(10)

物理分页 这次我们运用Mybatis拦截器来实现物理分页,后面会运用动态sql来实现,或者运用Map/CollectionUtils/StringUtils编写工具类来实现.oracle是运用的rownum,mysql是运用的limit offset,pagesize.代码中有大量注释,可以参考Mybatis基本原理一起阅读.后面,我们会根据一些实际开发需要,把物理分页功能的代码封装成jar包,以后直接调用就好了,比如Mybatis+Spring3的运行环境,可以采用Mybatis动态sql来实

Android开发记录18-集成极光推送的一点说明

Android开发记录18-集成推送服务的一点说明 关于推送服务,国内有很多选择,笔者也对它们进行了一个详细的对比,一般我们产品选择推送服务主要考量以下几个要素: 1.是否收费,如何收费? 2.推送内容是是什么(是否包含通知.消息.富媒体等等) 3.稳定性.及时性如何? 4.集成难度是否简单 5.支持平台有哪些(主流Android.IOS) 6.服务端支持语言(Java.C#.PHP.Python等) 下面笔者例举国内主要的一些推送服务: 来自Devstore的统计,共收录了国内21家推送服务,

2135亿背后的双11项目协作怎么玩?

摘要: 2018天猫双11已经收官,2135亿元的成交额再度刷新纪录,这是一场阿里巴巴经济体的深度协作. 在这个大协作项目中,项目协作难题难以想象:如何保证众多部门.百个核心产品.千个垂直项目.几千人的的高效协作?如何在双11之前,让所有的产品.技术.项目准备就绪? 这背后,离不开阿里巴巴一站式企业协同研发平台--云效的支持. 2018天猫双11已经收官,2135亿元的成交额再度刷新纪录,这是一场阿里巴巴经济体的深度协作. 在这个大协作项目中,项目协作难题难以想象:如何保证众多部门.百个核心产品

CozyRSS开发记录5-订阅列表栏里的项

CozyRSS开发记录5-订阅列表栏里的项 1.订阅列表栏里的项的原型图 这里列表项依然参考傲游的RSS阅读器,以后可能会微调. 2.使用ControlTemplate来定制ListBoxItem 给展示RSS源名称的TextBlock设置MaxWidth和ToolTip,是为了优化名称过长的情况. 这里暂时把内容都写死,后面会使用MVVM和bindling来处理. 3.ListBox效果展示 最后,我们修改ListBox的xaml,用上我们的模版. 效果还行