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.

[参考译文] CCS/TMS320F28388D:从 CPU1状态引导 CPU2

Guru**** 2039050 points
Other Parts Discussed in Thread: TMS320F28388D, C2000WARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/950606/ccs-tms320f28388d-cpu2-boot-from-cpu1-status

器件型号:TMS320F28388D
主题中讨论的其他器件: C2000WARE

工具/软件:Code Composer Studio

您好!

我正在使用 TMS320F28388D 控制器并尝试执行以下操作、基本而言、我正在进行编程以确定某个应用是否将使用控制器的2个内核或1个内核(CPU)。

因此、如果程序不使用 CPU2、我将不会将引导加载程序加载到其中、因此它将是单核应用程序。

当连接到 CCS 调试模式时、代码工作正常、并且只能使用单核、 但是、当从 CCS 断开连接时、它无法按预期工作、也就是说、我可以在 CCS 调试模式下执行的操作是、在 CCS 调试模式下、当它未连接时、会出现相同的行为

我的代码在 CPU1和 CPU2中如下所示:

if (cpuid_1 == gu16CpuId)
{

DEVICE_BOOTCPU2 (BOOTMODE_BOOT_TO_FLASH_SECTOR0);

} 
if (cpuid_2 =gu16CpuId)
{

guniIpcRegs.gstrCpu2IpcRegs.CPU2TOCPU1IPCSET.bit.IPC16 = bit_set;

} 
if (cpuid_1 == gu16CpuId)
{
while (!guniIpcRegs.gstrCpu1IpcRegs.CPU2TOCPU1IPCSTS.bit.IPC16){
if (counter_exit > 0){//counter_exit = 1000
COUNTER_EXIT = COUNTER_EXIT - 1;
}
否则{
中断;
}
}

if (guniIpcRegs.gstrCpu1IpcRegs.CPU2TOCPU1IPCSTS.bit.IPC16){
gu16ApplicationType = dual_core;
}
否则{
gu16ApplicationType = single_core;
}

} 

谢谢、

Nagesh

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

    你好

    您看到了什么行为? 是否通过引导 GPIO 正确设置了 CPU1引导模式? 您的 CPU2应用程序入口地址(CODE_START)是否位于0x80000地址?

    在每个 LED 中闪烁、以便您可以查看它们是否到达其应用程序。

    此致

    Chris

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

    您好 Chris、

    是的、我已经使用 LED 闪烁模式来了解流速、我观察到的是、当仅选择单个内核时、控制器将得到复位。  

    即在 CPU1中执行语句之后。

    DEVICE_BOOTCPU2 (BOOTMODE_BOOT_TO_FLASH_SECTOR0);

    您能告诉我 为什么它可以得到复位、有什么调试建议吗?

    谢谢、

    Nagesh  

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

    你好

    您是否正在禁用看门狗? 这在引导后启用、并在通过 CCS 连接时禁用。

    此致

    Chris

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

    尊敬的 Chris:

    是的、看门狗已禁用、我尝试在其中一个示例代码中模拟行为、我可以看到类似的行为、试图弄清楚它为什么会被复位。

    情况是、输出文件应仅加载到 CPU1上。 在启动 CPU2和启动 CPU2之前、我有不同的 Keet LED 闪烁模式。

    我正在使用 C28x_DUAL 中为 F2838xD 提供的示例代码、我无法在此处附加完整项目、因此无法附加更新的代码。

    我已经对某些 IPC 进行了评论、因为在这里、示例代码不需要该 IPC。 并以粗体突出显示了新代码。 选择闪存。

    //文件:ipc_ex1_basic_c28x1.c
    
    int gu16ApplicationType = dual_core;
    void main (void)
    {
    int i;
    int k = 0;
    //初始化设备时钟和外设
    device_init();
    
    DEVICE_initGPIO();
    GPIO_setPadConfig (DEVICE_GPIO_PIN_LED1、GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode (DEVICE_GPIO_PIN_LED1、GPIO_DIR_MODE_OUT);
    
    for (k=0;k<20;k++)
    {
    //打开 LED
    GPIO_writePin (DEVICE_GPIO_PIN_LED1、0);
    DEVICE_DELAY_US (100000);
    GPIO_writePin (DEVICE_GPIO_PIN_LED1、1);
    DEVICE_DELAY_US (100000);
    } 
    //启动 CPU2内核
    #ifdef _flash
    DEVICE_BOOTCPU2 (BOOTMODE_BOOT_TO_FLASH_SECTOR0);
    #else
    DEVICE_BOOTCPU2 (BOOTMODE_BOOT_TO_M0RAM);
    #endif
    
    //清除任何 IPC 标志(如果已设置)
    IPC_clearFlagLtoR (IPC_CPU1_L_CPU2_R、IPC_FLAG_ALL);
    if (dual_core =gu16ApplicationType)
    {
    GPIO_setPadConfig (DEVICE_GPIO_PIN_LED2、GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode (DEVICE_GPIO_PIN_LED2、GPIO_DIR_MODE_OUT);
    //配置 CPU2以控制 LED GPIO
    GPIO_setMasterCore (DEVICE_GPIO_PIN_LED2、GPIO_CORE_CPU2);
    }
    for (;;)
    {
    //打开 LED
    GPIO_writePin (DEVICE_GPIO_PIN_LED1、0);
    DEVICE_DELAY_US (50000);
    GPIO_writePin (DEVICE_GPIO_PIN_LED1、1);
    DEVICE_DELAY_US (50000);
    }
    

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

    您好 Chris、

    我从进一步调试中还有一个观察结果。

    我想知道在什么情况下 CPU2会导致控制器(F28388D)上的复位、包括 CPU1。

    这仅在控制卡未连接到 CCS 时发生。

    在执行"Device_bootCPU2 (bootmode_boot_boot_TO_flash_SECTOR0);"之后、它恰好发生;  

    谢谢、

    Nagesh

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

    Nagesh、

    我将尝试在明天结束时重复并返回给您。

    目前、我只能想到 CPU2具有可触发 CPU2上 NMI 的看门狗复位。 否则、CPU2无法复位整个器件。 如果 CPU1未进行复位、则有几个不同的 CPU2复位源。 请查看 TRM 章节"C28x 系统控制"->"Resets"。

    我还建议独立运行后、使用删除了 GEL 的目标配置重新连接到器件。 在目标配置中、转到"Advanced"选项卡、选择"CPU1"、"CPU2"等、然后清除 GEL 的路径。 这样、当您连接时、它不会重置器件、然后您可以加载符号以查看其当前在代码中的位置。 您还可以观察 IPC 状态寄存器和其他可提供更多调试信息的寄存器。

    此致

    Chris

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

    您好 Chris、  

    我发现它恰好在何处获得复位、我正在重复使用示例代码中的函数'void sysctl_controlCPU2Reset (sysctl_CoreReset control)'。

    在它下面  

    if (CONTROL!= 0x0U)
    {
    
    }
    其他
    {
    
    EALLOW;
    clearvalue = HWREG (DEVCFG_base + SYSCTL_O_CPU2RESCTL);
    clearvalue &=~SYSCTL_CPU2RESCTL_RESET;
    
    
    HWREG (DEVCFG_BASE + SYSCTL_O_CPU2RESCTL)=(SYSCTL_REG_KEY 和
    SYSCTL_CPU2RESCTL_KEY_M)| clearvalue;//在该宏尝试了解该宏的功能后导致复位,我可以替换它
    //will a register 
    
    (i=10;i>0;i--)
    {
    strGpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    DGenerateMicroSecDelay (65535);
    DGenerateMicroSecDelay (65535);
    DGenerateMicroSecDelay (65535);
    }
    
    EDIS;
    } 

    谢谢

    Nagesh

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

    Nagesh

    是的、当 CPU2从复位释放到启动时、您将在此处详述。 该语句将写入 CPU2RESCTL 寄存器。

    我已经获取了您提供的代码并查看了场景。 我已确认 CPU2确实获得了 itrap、然后看门狗在那里触发复位、WD 复位作为 NMI 发送到 CPU1。 由于在示例中未设置 CPU1矢量表、NMI 将进入引导 ROM NMI 处理程序、该处理程序不处理 CPU2 WD NMI、因此 CPU1会由于 NMIWD 超时而复位。

    如果在 Device_init()之后添加以下内容,则可以看到它在 CPU1的 NMI 默认处理程序中遇到 Estop:

    //
    //初始化设备时钟和外设
    //
    device_init();
    
    //
    //初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
    //
    interrupt_initModule();
    
    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //
    interrupt_initVectorTable();
    
    //
    //启用全局中断(INTM)和实时中断(DBGM)
    //
    EINT;
    ERTM; 

    您可以修改该处理程序、以便在您的方案中忽略 CPU2 WD NMI。

    请注意、一种更简单的调试方法是:

    1. 加载 CPU1应用程序
    2. 连接到 CPU2、通过 CCS 复位并运行
    3. 通过 CCS 复位 CPU1
    4. 在 CPU1上的0xD00、写入0xFFFF、在0xD01写入0x5AFF、在0xD04写入0x0003
      1. 这将模拟闪存启动、以便您可以保持调试器连接
    5. 运行 CPU1。 这将使 CPU1能够在引导过程中运行、并且可以轻松地查看 CPU1/2正在执行的操作

    此致

    Chris

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

    您好!  

    感谢您的分析。  

    我正在尝试按照您的建议更新 NMI 处理程序、并使用 C2000Ware_3_03_00_00_Software 中 TI 提供的示例代码

    C:\ti\C2000Ware_3_03_00_00_Software\driverlib\f2838x\examples\C28x_DUAL_NMI

    我已经更新了 NMI_ISR、将 CPU2发送回复位状态、如下所示、但我看不到它按预期工作。

    我没有在 CPU2上加载任何应用、只需通过 CPU2引导而不在其中包含应用程序、我就会收到 NMI 中断、并且在该中断中将 CPU2发送回 CPU1中复位。 您能否检查我所做的工作是否正确?

    void main (void)
    {
    device_init();
    interrupt_initModule();
    interrupt_initVectorTable();
    sysctl_clearAllNMIPls();
    INTERRUPT_REGISTER (INT_NMI、&NMI_ISR);
    SYSCTL_enableNMIPGlobalInterrupt();
    INTERRUPT_ENABLE (INT_NMI);
    EINT;
    ERTM;
    DEVICE_BOOTCPU2 (BOOTMODE_BOOT_TO_FLASH_SECTOR0); 
    while (1)
    {
    while (NMI_ISR_called!= 1);
    if (nmiflagstatus!=(SYSCTL_NMI_CPU2WDRSN | SYSCTL_NMI_NMIINT)) { ESTOP0;}
    NMI_ISR_called = 0;
    NMI_ISR_COUNT++;
    }
    } 

    中断空 NMI_ISR (空)
    {
    NMI_ISR_called = 1;
    unsigned long int 计数器= 0;
    unsigned long int i = 0; 
    //添加以在 LED 进入 NMI 中断时观察 LED 闪烁、但不观察 LED 闪烁模式 while (计数器< 5) { 计数器=计数器+ 1; GPIO_togglePin (DEVICE_GPIO_PIN_LED1); 对于(I = 0;I < 100000;I++) asm (" RPT #255 || NOP"); } nmiflagstatus = sysctl_getNMIFagStatus(); nmisdflagstatus = sysctl_getNMiShadowImage FlagStatus(); sysctl_clearAllNMIPls(); DEVICE_BOOTCPU2 (0x00);
    谢谢、
    Nagesh

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

    Nagesh

    在 NMI 处理程序中、我要在 LED 闪烁之前将 NMI 标志清零、以避免 NMI WD 重置 CPU1。

    DEVICE_BootCPU2 ()不会将 CPU2重新置于复位状态。 您需要调用 API sysctl_controlCPU2Reset()。 相关详细信息、请参见 driverlib 文件 sysctl.h

    此致

    Chris