• 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 ", 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 ", 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 ", 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 ");  
    91.             }  
    92.     
    93.             System_printf("tsk1_func: Sent request #%d to %s ", seq,  
    94.                     MultiProc_getName(dstProc));  
    95.         }  
    96.     }  
    97.     
    98.     System_printf("Test completed ");  
    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 ", MultiProc_self());  
    120.     System_printf("main: MultiProc name = %s ",  
    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 ");  
    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 ");  
    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 ");  
    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 ");  
    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 ");  
    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 ");  
    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 ", 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 ");  
    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 ");  
    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 ");  
    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 ");  
    149.             }  
    150.     
    151.             System_printf("Sending a message #%d to %s ",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 ");  
    162.             }  
    163.     
    164.             /* test done */  
    165.             if (msgId >= NUMLOOPS)  
    166.             {  
    167.                 break;  
    168.             }  
    169.         }  
    170.     }  
    171.     
    172.     System_printf("The test is complete ");  
    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 ");  
    198.     }  
    199.     
    200.     BIOS_start();  
    201.     
    202.     return (0);  
    203. }  



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

    我走遍轮回,只为与你相遇!
  • 相关阅读:
    selenium
    python第三方模块的安装
    程序员学习网站
    python 数据较大 性能分析
    linux ~/ 和 /
    VMWare虚拟机 window文件传递
    vi命令
    os.system
    win10系统进入BIOS
    pyinstaller将python脚本生成exe
  • 原文地址:https://www.cnblogs.com/layout/p/7169741.html
Copyright © 2020-2023  润新知