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.

[参考译文] TMS320F28379D:无法在 TMS320F28379D 中调试双核工程

Guru**** 2856470 points

Other Parts Discussed in Thread: TMS320F28379D, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1635308/tms320f28379d-unable-to-debug-dual-core-projects-in-tms320f28379d

部件号: TMS320F28379D
主题: C2000WARE 中讨论的其他器件

我们正在尝试调试一个双核 IPC 示例程序、该程序为 RAM 上的 CPU1 和 CPU2 都包含 2 个单独的工程。

以下是用于加载.out 文件和调试已编译工程的步骤。

  1. 启动 TMS320F28379D 的所选配置。
  2. 连接到目标至 CPU1 内核并加载 CPU1.out 文件。
  3. CPU1 程序在 main 停止。
  4. 连接到目标到 CPU2 内核并加载 CPU2.out 文件。
  5. CPU2 程序会立即执行..!

由于 CPU2 没有在 main () 停止、因此两个内核之间的同步不会正确发生、因此数据不会从 CPU1 共享到 CPU2。

我们尝试了以下替代方案、但它们似乎不起作用-

  1. 在 CPU2 的 main() 处设置断点。
  2. 在 CPU2 程序的属性中启用 run to main() 选项。
  3. 在 CPU2 中添加 IPC_WaitforFlag()。
  4. 在 main() 之后立即在 CPU2 代码中添加一些延迟。

在 RAM 上运行时、相同的程序在不同的系统中似乎可以正常工作。 此外、如果程序在闪存上执行、则在加载.out 文件后、CPU1 和 CPU2 代码都会在 main () 处停止。

附加的 CPU1 程序 — 1.txt 和 CPU2 程序 — 2.txt

在不同系统中出现这种行为的原因可能是什么。 是否需要进行任何系统级设置/配置才能解决问题?

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

    尊敬的 Gautham:

    您能检查以下内容吗?

    1. CPU1 代码中是否有任何 CPU2 调用? 例如 IPCBootCPU2 ()、Device_bootCPU2 () 等

    2.您是否可以尝试使用多核启动,而不是手动顺序加载到 CPU1 和 CPU2 ? 您可以参阅 C2000Ware_6_00_01_00\driverlib\f2837xd\examples\dual\ipc 中的示例。 请注意、这涉及创建一个包含多核配置的 system.xml 文件。 您还可以从  C2000Ware_6_00_01_00\driverlib\f2837xd\examples\dual 中的空工程开始、然后根据您的工程编辑 CPU1 和 CPU2 的.c 和 syscfg 文件。

    3.始终确保首先加载 CPU1(您已经在执行此操作)

    您可以尝试一下、让我知道它是否适合您吗?

    谢谢、

    IRA

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

    尊敬的 Gautham:

    刚刚看到、在 CPU1 代码中有以下行

     

    这将导致 RAM 构建肯定中断。

    这是因为_standalone 宏未在 CCS 调试会话期间定义、它仅为生产编译定义。 因此、从不在 RAM 构建中调用 Device_bootCPU2 (0)。  

    标准映射 (+已定义)_STANDALONE_FLASH:CPU2 的引导 ROM 等待 CPU1 通过发送引导命令Device_bootCPU2()。 JTAG 调试器拦截此切换并可以在 main() 处暂停 CPU2。 这就是闪存可靠工作的原因。

    RAM 调试模式 :没有引导 ROM 等待机制。 当调试器连接到 CPU2 并加载 CPU2.out 时、它会直接写入 RAM 并释放 CPU2 的执行功能。 如果目标配置中未配置“连接时停止“或“复位和暂停“、CPU2 仅需运行。

    IPC_sync()两个内核都可以对其进行调用 游标 (或在短窗口内)。 当 CPU2 提前运行时、同步基元以特定方式中断:

    CPU2 首先运行:

    1. CPU2 调用IPC_sync(IPC_CPU2_L_CPU1_R, IPC_FLAG17)

      • 设置 CPU2→CPU1 FLAG17
      • 检查 while(IPC_isFlagBusyRtoL(..., IPC_FLAG17)) →Ω 检查是否设置了 CPU1→CPU2 FLAG17
      • CPU1 尚未设置任何内容、因此这个标志是  未设置  →条件为 false →Ω  循环立即退出
      • CPU2 无需等待 CPU1 即可传递同步
    2. CPU2 进入for(;;) { NOP; }—等待 IPC 中断。

    CPU1 稍后启动(从调试器): 3. CPU1 调用IPC_sync(IPC_CPU1_L_CPU2_R, IPC_FLAG17):

    • 设置 CPU1→CPU2 FLAG17
    • 检查 while(IPC_isFlagBusyRtoL(..., IPC_FLAG17)) →Ω 检查是否设置了 CPU2→CPU1 FLAG17
    • CPU2 在步骤 1 和中设置此标志  它仍处于置位状态  →条件为 true →Ω  CPU1 将永远等待

    您能否在代码中进行以下更改并尝试?

    CPU1 代码 Device_init()在后面和前面添加此项IPC_sync()

    Device_init();
    // ...
    IPC_clearFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG_ALL);
    
    // Signal CPU2 that CPU1 is initialized and ready
    IPC_setFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG31);
    
    // Now proceed to sync
    IPC_sync(IPC_CPU1_L_CPU2_R, IPC_FLAG17);
    

    CPU2 代码 —在中添加此项 第一行 在 main() 之前Device_init()

    void main(void)
    {
        // Wait for CPU1 to finish its init before proceeding
        // Must be first — before Device_init(), before IPC_clearFlagLtoR()
        while(!IPC_isFlagBusyRtoL(IPC_CPU2_L_CPU1_R, IPC_FLAG31));
        IPC_ackFlagRtoL(IPC_CPU2_L_CPU1_R, IPC_FLAG31);
    
        // Normal init follows
        Device_init();
        ...
        IPC_clearFlagLtoR(IPC_CPU2_L_CPU1_R, IPC_FLAG_ALL);
        ...
        IPC_sync(IPC_CPU2_L_CPU1_R, IPC_FLAG17);

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

    尊敬的 Ira Thete :

    我进行了上述修改和测试、但问题仍然存在。  

    当闪存的构建配置设置为活动状态时、工作正常。 但是、当 RAM 的编译配置设置为活动状态时、CPU2 代码会在加载后立即自动开始执行。

    我还对双核工程实现了调试配置 (.XML)、可同时将 CPU1 和 CPU2 工程加载到 core1 和 core2 中。 当 CPU2 已在运行时、CPU1 会在 main() 处停止。

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

    尊敬的 Gautham:

    您可以尝试使用这个 CPU1 代码吗? 我已将 CPU2 保持在复位状态、直到 CPU1 就绪。

    #include “driverlib.h"</s>“
    #include “device.h"</s>“
    #include “ipc.h"</s>“
    #include “struct.h"</s>“

    pragma DATA_SECTION (data1、“MSGRAM_CPU1_TO_CPU2")“)
    shared_t data1;
    //uint32_t data1;

    void main (void)

    //初始化设备(基本系统设置)
    设备初始化 ();

    //立即将 CPU2 保持在复位状态
    SysCtl_resetPeripheral (SYSCTL_PERIPH_RES_CPU2);

    uint16_t i = 0;

    #ifdef _standalone
    #ifdef _flash
    //从闪存引导 CPU2 — 但仍将保持在复位状态
    DEVICE_BOOTCPU2 (BOOT_BOOT_TO_FLASH_SECTOR0);
    #else
    //从 RAM 引导 CPU2 — 但仍将保持复位状态
    DEVICE_BOOTCPU2 (BOOT_BOOT_TO_M0RAM);
    #endif
    #endif

    //初始化 PIE 模块和矢量表
    interrupt_initModule();
    Interrupt_initVectorTable();

    //清除所有 IPC 标志(如果已设置)
    IPC_clearFlagLtoR (IPC_CPU1_L_CPU2_R、IPC_FLAG_ALL);

    //现在将 CPU2 从复位状态释放 — 它将开始执行
    SysCtl_releasePeripheral (SYSCTL_PERIPH_RES_CPU2);

    //在尝试同步之前给 CPU2 留出一些时间进行初始化
    DEVICE_DELAY_US (1000);

    //同步两个内核
    IPC_SYNC (IPC_CPU1_L_CPU2_R、IPC_FLAG17);

    //启用全局中断
    EINT;
    //启用实时调试
    ERTM;

    对于 (;;){
    IF(!IPC_isFlagBusyLtoR (IPC_CPU1_L_CPU2_R、IPC_FLAG0))

    I++;
    Data1.id = i;
    Data1.Value = 10.5 * I;
    IPC_SendCommand (IPC_CPU1_L_CPU2_R、IPC_FLAG0、IPC_ADDR_CORRECTION_ENABLE、0、(uint32_t)&data1、
    sizeof (data1));
    DEVICE_DELAY_US (200000);
    }
    }
    }

    谢谢、

    IRA

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

    1.初始设置:
    -首先连接到 CPU1 并加载 CPU1.out
    - CPU1 将在 main() 处停止
    2.首次运行:
    -让 CPU1 运行、直至 CPU2 从复位状态释放
    -您可以根据需要在 SysCtl_releasePeripheral(SysCtl_Periph_Res_CPU2) 行之后设置断点
    3. CPU2 连接:
    -连接到 CPU2 并加载 CPU2.out
    -有了这个解决方案,CPU2 应该在 main () 正确停止,因为 CPU1 正在控制其复位状态
    4、同步:
    -恢复两个内核
    -他们现在应该在各自的 ipc_sync 调用中正确同步
    - CPU1 将开始向 CPU2 发送数据、CPU2 将通过其中断处理程序接收数据

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

    此外、确保为两个 CPU 均启用了 Run to Symbol -> main on a program load or restart 选项

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

    你好、 Ira Thete 

    我未看到 头文件中的 SysCtl_Periph_Res_CPU2 常量和 SysCtl_releasePeripheral (SysCtl_Periph_Res_CPU2) 函数。 因此、我无法更改建议的代码。 如果要将其更改为某个其他变量/常量、以便手动复位 CPU2、您能帮帮我吗? 我使用的是 CCS 版本 12.8.1。

    此外、还 为 CPU2 启用了 run to main 的选项。

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

    尊敬的 Gautham:

    您可以使用直接硬件寄存器写入来复位 CPU2。 您可以尝试一下吗?  

    #include “driverlib.h"</s>“
    #include “device.h"</s>“
    #include “ipc.h"</s>“
    #include “struct.h"</s>“

    //直接寄存器访问需要
    #include “inc/hw_memmap.h"</s>“
    #include “inc/hw_types.h"</s>“
    #include “inc/hw_sysctl.h"</s>“

    pragma DATA_SECTION (data1、“MSGRAM_CPU1_TO_CPU2")“)
    shared_t data1;
    //uint32_t data1;

    void main (void)

    //初始化设备(基本系统设置)
    设备初始化 ();

    //通过设置 CPU2RESCTL.RESET 位将 CPU2 置于复位状态
    //需要写入该寄存器的密钥值 (0xA5A5)
    EALLOW;
    HWREG (DEVCFG_BASE + SYSCTL_O_CPU2RESCTL)=((HWREG (DEVCFG_BASE + SYSCTL_O_CPU2RESCTL)
    &Δ V SYSCTL_CPU2RESCTL_RESET)~0x1)//将 RESET 位设置为 1
    |(0xA5A5 << SysCtl_CPU2RESCTL_KEY_S);//设置 KEY 字段
    EDIS;

    uint16_t i = 0;

    //初始化 PIE 模块和矢量表
    interrupt_initModule();
    Interrupt_initVectorTable();

    //清除所有 IPC 标志(如果已设置)
    IPC_clearFlagLtoR (IPC_CPU1_L_CPU2_R、IPC_FLAG_ALL);

    #ifdef _standalone
    #ifdef _flash
    //从闪存引导 CPU2
    DEVICE_BOOTCPU2 (BOOT_BOOT_TO_FLASH_SECTOR0);
    #else
    //从 RAM 引导 CPU2
    DEVICE_BOOTCPU2 (BOOT_BOOT_TO_M0RAM);
    #endif
    #endif

    //通过清除 CPU2RESCTL.RESET 位将 CPU2 释放为复位状态
    EALLOW;
    HWREG (DEVCFG_BASE + SYSCTL_O_CPU2RESCTL)=((HWREG (DEVCFG_BASE + SYSCTL_O_CPU2RESCTL)
    &Δ V SysCtl_CPU2RESCTL_RESET)~//清除复位位
    |(0xA5A5 << SysCtl_CPU2RESCTL_KEY_S);//设置 KEY 字段
    EDIS;

    //在尝试同步之前给 CPU2 留出一些时间进行初始化
    DEVICE_DELAY_US (1000);

    //同步两个内核
    IPC_SYNC (IPC_CPU1_L_CPU2_R、IPC_FLAG17);

    //启用全局中断
    EINT;
    //启用实时调试
    ERTM;

    对于 (;;){
    IF(!IPC_isFlagBusyLtoR (IPC_CPU1_L_CPU2_R、IPC_FLAG0))

    I++;
    Data1.id = i;
    Data1.Value = 10.5 * I;
    IPC_SendCommand (IPC_CPU1_L_CPU2_R、IPC_FLAG0、IPC_ADDR_CORRECTION_ENABLE、0、(uint32_t)&data1、
    sizeof (data1));
    DEVICE_DELAY_US (200000);
    }
    }
    }

    这基于 C2000Ware 6.00.01.00 SDK。  
    这不是最干净的方法、但您是否仍能暂时尝试一下、看看它是否能解决问题?  

    谢谢、

    IRA

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

    你好、 Ira Thete 

    在我构建代码时,会抛出错误 — 未定义标识符“YSCTL_O_CPU2RESCTL"。“。 我观察到,当构建在不同笔记本电脑的 RAM 上时,程序工作正常。 在 PC 的 RAM 上构建相同的代码时、其行为有所不同。 是否需要在系统级别或环境变量中进行任何更改、以便无论系统如何、都能正常工作。

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

    尊敬的 Gautham:

    我希望你包括:
    #include “inc/hw_sysctl.h"</s>“

    并使用 C2000Ware 6.00.01.00 SDK、因为这里清楚地定义了寄存器。

    因此不会收到未定义的错误。

    您能否确保也将其包括在项目的包含选项中?

    谢谢、

    IRA

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

    你好、 Ira Thete 

    库已正确包含。 我使用的 C2000 版本是 C2000Ware 5.02.00.00 SDK。 这可能是个问题吗? 我现在正在尝试下载最新版本。

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

    你好、 Ira Thete 

    库已正确包含。 我使用的 C2000 版本是 C2000Ware 5.02.00.00 SDK。 这可能是个问题吗? 我现在正在尝试下载最新版本。

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

    尊敬的 Gautham:

    是的、我建议尝试使用较新的 C2000Ware、因为  5.02.00.00 非常旧、此后修复了很多错误。 请尝试使用 6.00.01.00 SDK 或更高版本。

    谢谢、

    IRA

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

    我已使用  6.00.01.00 SDK 进行验证 、但仍未解决问题。

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

    好的、所以您可以进行寄存器写入、但 CPU2 仍然没有在 main 处停止。 是这样吗?

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

    是的,代码正在编译,但 CPU2 仍然没有在 main () 停止。

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

    您将在行后加载 CPU2 程序  
    //在尝试同步之前给 CPU2 留出一些时间进行初始化
    DEVICE_DELAY_US (1000);
    对吗?

    在将程序加载到 CPU2 之前、CPU1 需要执行到此处、以确保同步正确发生。