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.

TMS320F28377D: 双核离线烧写问题

Part Number: TMS320F28377D
Other Parts Discussed in Thread: C2000WARE

目前程序架构为:CPU1做控制算法和pwm等功能,CPU2专门用来通讯,CPU之间通过IPC进行数据交流

程序需要离线运行,即写入flash中,两个核都需要将部分函数搬入ram中运行以提高运行速度,其中CPU1搬入的函数如下:

//需要搬入ram中运行的函数
#ifdef _FLASH
#pragma CODE_SECTION(EPWM2_ISR,"ramfuncs");
#pragma CODE_SECTION(Getresult,"ramfuncs");
#pragma CODE_SECTION(set_epwmcmp,"ramfuncs");
#pragma CODE_SECTION(PI_stop,"ramfuncs");
#endif

#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
Getresult();
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
set_epwmcmp();
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
PI_stop();
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
EPWM2_ISR();//中断函数
#endif

CPU2中搬入ram中的函数如下:

#ifdef _FLASH
// These are defined by the linker (see device linker command file)
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;
#pragma CODE_SECTION(IPC11_RX,"ramfuncs");
#pragma CODE_SECTION(CPU01toCPU02IPC1IntHandler,"ramfuncs");
#endif

#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
IPC11_RX();
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
CPU01toCPU02IPC1IntHandler();//中断函数
#endif

问题在于当我将CPU2中的接收函数和IPC中断函数搬入ram中时,程序卡死在CPU2的中断函数当中,CPU1中的程序正常运行。目前有以下具体的问题:

1.CPU1程序完全在flash中运行和完全在ram中运行速度差别不大,而CPU2中差别会比较大,请问这是否正常?如果将中断函数搬入ram中,那么中断函数中所用到的子函数是否也需要搬入ram中?

2.CPU2中的程序完全在flash中程序可以正常运行,一旦我将中断函数搬入ram中程序就会卡死在IPC中断函数中,请问两个核是否可以同时将函数搬入ram中运行?是否需要修改cmd文件?

3.我仔细看了例程中CPU1和CPU2的cmd文件,发现每个分区的地址都是一样的,datasheet中说每个CPU都有独立的ram区和flash区,双核程序flash初始化之后两个CPU的ram区和flash区在地址上都是重合的,这是否与datasheet的描述相矛盾?还是说需要在cmd文件中定义每个ram和flash的归属权?

CPU1中的发送函数如下:

/* 数据发送 */
void IPC11_TX(Uint16 *AMBFB)
{
Uint16 i;
if(IPCRtoLFlagBusy(IPC_FLAG11) == 1)//如果CPU2设置了标志位
{
if((MemCfgRegs.GSxMSEL.bit.MSEL_GS0) == 1)//设置CPU1作为GS0 RAM 的主控
{
EALLOW;
MemCfgRegs.GSxMSEL.bit.MSEL_GS0 = 0;
EDIS;
}
for(i=0;i<10;i++)//将数据写入共享ram
{
pusCPU01BufferPt[i] = AMBFB[i];
}
//将共享ram中的数据写入CPU2-1的消息ram所指定的位置
IPCLtoRBlockWrite(&g_sIpcController2, pulMsgRam2[1],(uint32_t)pusCPU01BufferPt,10,IPC_LENGTH_16_BITS,ENABLE_BLOCKING);
IPCRtoLFlagAcknowledge(IPC_FLAG11);
//IPCLtoRFlagClear(IPC_FLAG11);
}
}

CPU2中的IPC中断程序如下:

__interrupt void
CPU01toCPU02IPC1IntHandler (void)
{

tIpcMessage sMessage;
GPIO_WritePin(37,1);
IPCLtoRFlagSet(IPC_FLAG11);
// Continue processing messages as long as CPU01toCPU02 GetBuffer2 is full
while (IpcGet (&g_sIpcController2, &sMessage,
DISABLE_BLOCKING)!= STATUS_FAIL)
{
switch (sMessage.ulcommand)
{
case IPC_BLOCK_WRITE://CPU1将数据写进共享ram
IPCRtoLBlockWrite(&sMessage);
IPC11_RX();
break;
case IPC_BLOCK_READ:
IPCRtoLBlockRead(&sMessage);//CPU2将指定地址的数据写入共享ram
break;
default:
//ErrorFlag = 1;
break;
}

}

// Acknowledge IPC INT1 Flag and PIE to receive more interrupts
IpcRegs.IPCACK.bit.IPC1 = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
GPIO_WritePin(37,0);
}

第一次做双核的程序,问题比较多,希望有前辈能抽出宝贵的时间帮我解答一下疑惑,如果能留下联系方式就更好了,不胜感激。

  • 您好我们已收到您的问题并升级到英文论坛寻求帮助,如有答复将尽快回复您。谢谢!

  • 您好,

    您试下使用 C2000Ware IPC 示例并从闪存运行?

    CPU1_FLASH 和 CPU2_FLASH 编译配置。

    在 CPU1上,在预定义符号中定义_standalone。

    看下这个应用程序是否有用?

  • 仅仅是离线运行的话是没问题的,但一旦将函数入ramfuncs程序就会卡死在中断程序中

  • 好的,我们跟进给工程师看下,应该会在下周工作日内给到您答复。

  • 您好,

    您可以参考以下两个 C2000Ware SDK 中使用两个 CPU 的示例,工程师在设置中进行过验证:

    #1 - Dual Core LED example

    路径: C:/ti/c2000/C2000Ware_4_01_00_00/driverlib/f2837xd/examples/dual/led/CCS

    在CPU1上,选择 CPU1_FLASH_STANDALONE构建配置

    在CPU2上,选择 CPU2_FLASH 构建配置

    一旦刷写了映像,请断开目标并重启。应该可以正常工作,两个 LED 应该都可以闪烁。 此示例不使用中断,只取决于内核之间的 IPC 标志状态。 

    #2 C2000Ware Academy Solution:

    路径:C/ti/c2000/C2000Ware_4_01_00_00/training/device/f2837xd/module11_inter_processor_communications

    在CPU1上,选择 CPU1_FLASH构建配置,打开 module11_cpu1_main.c 文件,并按照以下方式来更新参数:

    在项目设置中添加_standalone 预定义解决方案并打开文件:

    In the project setting, add _STANDALONE predefined solution and also open file 

    #ifdef _STANDALONE
    #ifdef _FLASH
    // TODO check to see if this breaks.
    Device_bootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
    #else
    // TODO this breaks the RAM build.
    Device_bootCPU2(BOOTMODE_BOOT_TO_M0RAM);
    #endif

    在CPU2上,选择 CPU2_FLASH构建配置

    一旦刷写了映像,断开目标并重启。应该可以正常工作,两个 LED 都应该闪烁。 本示例使用 IPC 中断。

    对于该实验,请访问 C2000 Academy 中的 IPC 实验页面:

    https://dev.ti.com/tirex/explore/node?node=A__Adlf59dR9TRikXjOlRRRsg__c2000Academy__jEBbtmC__LATEST

    LED 闪烁速率可修改为: 

    // Toggle LED1 at a rate 
    if (LedCtr1++ >= 5000) {
    GPIO_togglePin(DEVICE_GPIO_PIN_LED1);
    LedCtr1 = 0;
    } 

  • 你好,我想您还没有理解我真正想要询问的问题,我目前的问题是CPU1和CPU2都可以离线运行(结果是没问题的)。但是CPU2中程序运行的速度很慢,因此我想要把CPU2里面的中断程序搬到ram中运行,但搬到ram中之后程序运行时就会卡在中断程序中,还请帮忙解答一下。

  • 我们跟进给工程师看下,您也可以多多关注英文论坛工程师的答复哈:

    e2e.ti.com/.../tms320f28377d-dual-core-offline-burning-issue

  • 能分享下CPU2中的代码吗?是卡在 ISR 中了吗? PC 在哪里?

  • 目前来看确实卡死在了ISR中,代码如下:

    void InitIPC(void)//初始化ipc
    {
    IPCInitialize(&g_sIpcController1, IPC_INT0, IPC_INT0);
    IPCInitialize(&g_sIpcController2, IPC_INT1, IPC_INT1);//调用IPC实例,配置为IPC1中断
    Uint16 counter;
    pulMsgRam = (void *)CPU01TOCPU02_PASSMSG;//CPU1-2的消息ram
    pulMsgRam2 = (void *)CPU02TOCPU01_PASSMSG;//CPU2-1的消息ram
    pusCPU02BufferPt = (void *)(GS0SARAM_START + 15);//发送地址指针,指向共享ram gs0
    pusCPU02BufferPt_B = (void *)(GS0SARAM_START + 45);
    pulMsgRam2[1] = (Uint32)&usCPU02Buffer[0];//将接收buf的地址放在CPU2-1的消息ram中
    pulMsgRam2[3] = (Uint32)&usCPU02Buffer_B[0];
    for(counter = 0; counter <15; counter++)
    {
    usCPU02Buffer[counter] = 0;
    usCPU02Buffer_B[counter] = 0;
    }
    }

    __interrupt void
    CPU01toCPU02IPC1IntHandler (void)
    {

    tIpcMessage sMessage;
    GPIO_WritePin(37,1);
    IPCLtoRFlagSet(IPC_FLAG11);
    // Continue processing messages as long as CPU01toCPU02 GetBuffer2 is full
    while (IpcGet (&g_sIpcController2, &sMessage,
    DISABLE_BLOCKING)!= STATUS_FAIL)
    {
    switch (sMessage.ulcommand)
    {
    case IPC_BLOCK_WRITE://CPU1将数据写进共享ram
    IPCRtoLBlockWrite(&sMessage);
    IPC11_RX();
    break;
    case IPC_BLOCK_READ:
    IPCRtoLBlockRead(&sMessage);//CPU2将指定地址的数据写入共享ram
    break;
    default:
    //ErrorFlag = 1;
    break;
    }

    }

    // Acknowledge IPC INT1 Flag and PIE to receive more interrupts
    IpcRegs.IPCACK.bit.IPC1 = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    GPIO_WritePin(37,0);
    }

    main函数中的配置:

    InitPieVectTable();
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    EALLOW; // This is needed to write to EALLOW protected registers
    //PieVectTable.IPC0_INT = &CPU01toCPU02IPC0IntHandler;
    PieVectTable.IPC1_INT = &CPU01toCPU02IPC1IntHandler;
    EDIS; // This is needed to disable write to EALLOW protected registers

    InitIPC();

    EALLOW;
    CpuSysRegs.PCLKCR8.bit.SPI_B = 1;//启用spib时钟
    EDIS;
    //复位5500芯片
    Reset_5500();
    spi_init();
    //设置网络信息
    set_network();
    //开启服务器
    TCP_server();
    //设置IPC标志位
    if(IPCRtoLFlagBusy(IPC_FLAG11) == 0)
    {
    IPCLtoRFlagSet(IPC_FLAG11);
    }

    一旦我将中断函数和RX函数搬入ram中运行,程序就会卡死在ISR中

  • 好的我们跟进给工程师看下哈。

  • 您好,

    您给出的的代码是用于 CPU1的对吗?是卡在 IPC ISR 函数 CPU01toCPU02IPC1IntHandler()中吗?

    您试下将断点放在 ISR 的开头,然后当它卡住的时候,缩小其范围来定位具体的位置?

    看下是不是卡在这一行:

    while (IpcGet (&g_sIpcController2, &sMessage,DISABLE_BLOCKING)!= STATUS_FAIL)

    {
    }

    此外,有没有可能提供下能够显示该行为的项目? 如果您能用 C2000Ware IPC 示例之一来进行重现会更好。