DSP在CCS中实现双核在线仿真调试及下载的方法(以TMS320F28x为例)
DSP在CCS中实现双核在线仿真调试及下载的方法
- 介绍
- 使用的软硬件
- 双核项目结构及工程配置
- 工程建立
- 配置在线调试和离线烧写
- 双核程序在线调试
- 双核程序离线下载
- 后续
介绍
现在DSP的双核芯片已经越来越普遍,尤其是在TI推出的TMS320F2837xD、F2838x系列中,双核(CPU1 + CPU2)的架构成为了性能提升的重要手段。双核DSP不仅提高了系统的实时性和并行处理能力,还为复杂的控制、通信、算法运算等场景提供了更灵活的资源调度方式。
然而,双核带来的性能提升的同时,也使得程序开发和调试变得更加复杂。在CCS(Code Composer Studio)中,如果不能掌握正确的双核调试方法,往往会遇到程序不运行、Flash下载失败、两个CPU间无法通信等问题。
本篇文章将详细介绍如何在CCS中实现双核DSP的在线仿真调试与程序下载,涵盖以下几个方面:
- 双核项目结构及工程配置
- 如何配置和切换在线调试/离线下载
- 如何进行双核程序在线调试
- 如何进行双核程序下载
无论你是初次接触双核DSP的开发者,还是在项目中遇到多核调试困难的工程师,相信通过本文的讲解都能对你有所帮助。
使用的软硬件
- Code Composer Studio™ 集成式开发环境 (IDE)
- XDS100v3 USB Debug Probe
- UniFlash
- TMS320F28X芯片的开发板
双核项目结构及工程配置
工程建立
TMS320F28X芯片双核结构虽然使用上CPU占据主导权,但是两个CPU的工程是分开的,也就是完全独立的两个工程。
图中的两个工程led_ex1_blinky_cpu1和led_ex1_blinky_cpu2分别是CPU1和CPU2的工程。
配置在线调试和离线烧写
- 在CPU1工程中增加:
#ifdef _STANDALONE
#ifdef _FLASH//// Send boot command to allow the CPU2 application to begin execution//Device_bootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
#else//// Send boot command to allow the CPU2 application to begin execution//Device_bootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);#endif // _FLASH
#endif // _STANDALONE
这段代码的含义为,当定义_STANDALONE和_FLASH时,启用 Device_bootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
在 TI 的 dual-core 设备 中,CPU1 是主核,它控制整个设备的启动过程。CPU2 默认上电是处于复位或等待状态,需要由 CPU1 启动。
从数据手册可以看到:CPU2需要CPU1选择引导,Device_bootCPU2函数其实就是干这个的。
函数原型:void Device_bootCPU2(uint32_t bootMode);
bootMode 是启动方式参数,比如:
- C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH → 从 Flash 启动
- C1C2_BROM_BOOTMODE_BOOT_FROM_RAM → 从 RAM 启动
- C1C2_BROM_BOOTMODE_BOOT_FROM_SCI → 从 SCI(串口)启动
- C1C2_BROM_BOOTMODE_BOOT_FROM_I2C → 从 I2C 启动
- C1C2_BROM_BOOTMODE_BOOT_WAIT → 不启动,等待指令
- 增加定义
CPU1和CPU2都需要设置一个 Predefined Symbols,右键工程文件->Properties->在Predefined Symbols进行添加。
- 对于CPU2定义是一样的,因为不需要区分在线调试和离线烧写,所以定义都是一样的。
- 对于CPU1则不同,离线烧写时,选择CPU1_FLASH,只需要定义_CPU1和_FLASH即可。
- 对于在线调试,首先需要建立一个编译配置。点击管理配置然后新建一个CPU1_FLASH_STANDALONE(继承CPU1_FLASH)。
然后额外添加一个_STANDALONE。
之后我们编译的时候根据编译配置就可以选择是在线调试还是离线烧写了。
- 下面放一个官方的双核程序供大家测试。
CPU1
//
// Included Files
//
#include "driverlib.h"
#include "device.h"//
// Main
//
void main(void)
{//// Initialize device clock and peripherals//Device_init();#ifdef _STANDALONE
#ifdef _FLASH//// Send boot command to allow the CPU2 application to begin execution//Device_bootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
#else//// Send boot command to allow the CPU2 application to begin execution//Device_bootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);#endif // _FLASH
#endif // _STANDALONE//// Initialize GPIO and configure the GPIO pin as a push-pull output//Device_initGPIO();GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);GPIO_setPadConfig(DEVICE_GPIO_PIN_LED2, GPIO_PIN_TYPE_STD);GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED2, GPIO_DIR_MODE_OUT);//// Configure CPU2 to control the LED GPIO//GPIO_setMasterCore(DEVICE_GPIO_PIN_LED2, GPIO_CORE_CPU2);//// Initialize PIE and clear PIE registers. Disables CPU interrupts.//Interrupt_initModule();//// Initialize the PIE vector table with pointers to the shell Interrupt// Service Routines (ISR).//Interrupt_initVectorTable();//// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)//EINT;ERTM;//// Loop Forever//for(;;){//// Turn on LED//GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);//// Delay for a bit.//DEVICE_DELAY_US(500000);//// Turn off LED//GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);//// Delay for a bit.//DEVICE_DELAY_US(500000);}
}//
// End of File
//
CPU2
//
// Included Files
//
#include "driverlib.h"
#include "device.h"//
// Main
//
void main(void)
{//// Initialize device clock and peripherals//Device_init();//// Initialize GPIO and configure the GPIO pin as a push-pull output//// This is configured by CPU1//// Initialize PIE and clear PIE registers. Disables CPU interrupts.//Interrupt_initModule();//// Initialize the PIE vector table with pointers to the shell Interrupt// Service Routines (ISR).//Interrupt_initVectorTable();//// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)//EINT;ERTM;//// Loop Forever//for(;;){//// Turn on LED//GPIO_writePin(DEVICE_GPIO_PIN_LED2, 0);//// Delay for a bit.//DEVICE_DELAY_US(500000);//// Turn off LED//GPIO_writePin(DEVICE_GPIO_PIN_LED2, 1);//// Delay for a bit.//DEVICE_DELAY_US(500000);}
}//
// End of File
//
双核程序在线调试
- 编译两个工程,CPU1和CPU2均使用_FLASH。
- 点击debug
- 在debug中选定CPU1,然后选择固件。
- 然后选择CPU2进行更改固件。
- 选择CPU1和CPU2,然后分别点击运行。
- 运行后
- 此时CPU1,CPU2一起运行。
双核程序离线下载
- 离线下载和在线调试的区别就是,在第1步时,CPU1选择CPU1_FLASH_STANDALONE进行编译。后面2-6完全一样。然后关机重启。
- 还有一种离线下载方式,直接通过UniFlash进行下载。
分别通过点击CPU1和CPU2,然后选择工程生成的.out进行下载。