C6678多核DSP开发——hello world
本篇学习笔记主要记录在C6678实验板上实现打印“hello world”信息功能,主要目的是熟悉CCS开发环境和硬件调试过程。
板子工作需要12V稳定电源,我去拆了一个废弃的电脑主机的电源,还真的挺好使。要将P120P的插座的绿线和任意一条黑线短接,四线插座就会输出+12V电压,黄线为正,黑线为负。最好是在短接的电路上串联一个开关,以方便控制,不然就要一直插拔板卡接头或者电源开关,不很方便。
接下来就是JTAG仿真器,买的是XDS100V2USB,不太稳定,每次板卡掉电之后,仿真器也必须掉电、上电才可以重新连接,不然就cannot connect了。可能是便宜的原因,TI公司有一个XDS560,据说那个要几千块钱,太贵了,能用就将就着用吧。JTAG口接板卡,注意别插反了,有一个针脚是堵着的,会把针插断。另一端是USB接口,接电脑,Win7自己安装了驱动,但是我在设备管理里愣是没找到这个设备,难道是CCS里的驱动?不管了,无关紧要。
硬件连接到此为止,注意使用的时候的上电顺序:所有的接插件都先插好(最好不要上电之后插),然后仿真器先上电(即usb接电脑),板卡后上电,指示灯亮,工作正常,经常摸摸DSP的温度,太热了断电凉快一下。下面是软件部分。
2、建立hello world工程by CCS
a)打开CCS,file->new->project->CCS project
b)在建立CCS project 界面下:
project name:为自己的工程起个名字:hello_world_by_CCS;
output type:默认就好;
device:对于我的板卡(DSP为C6678),family自然是C6000,Variant是C6678(也可以是generic C66xx device),connection建议不选,因为一会儿再工程里会新建一个连接,那个时候再选择比较好。
advanced settings里基本可以默认,但是我觉得有必要将linker command file选上,因为建立好工程之后再去添加特别难找,这里会有默认的路径,当然也还是要因工程而异,有的工程可能要添加适合自己板卡的cmd文件,那当然可以之后再添加。这里,hello world用默认的cmd文件就可以,所以直接添加了。runtime support library :automatic就好,自动识别需要的lib库文件。
project template and example里选择自己要建立的工程,这里选择basicexample ->hello world。点击finish,至此,工程建立完毕。
c)建立连接
file->new->target configuration file,起个跟工程一样的名字,路径就放在工程目录下,便于管理。双击这个文件,会在右面出现设置界面:
connection 选择自己的仿真器类型,xds100v2usb emulator ,device选择C6678,点击save,连接创建成功。可以连上硬件,点击下test connection 看看是否连接成功。最后显示succeed 就是成功了。
d)烧写程序
首先build project :project -> build all
然后debug,直接点绿 {MOD}的小虫子也可以,八个核全选上。点击OK,程序开始烧写。
e)执行
点击F8,直接运行完,显示八个核的结果:
也可以在debug窗口中选择对应的核,按F5一步一步执行:
可以在console 窗口中看到输出结果:
3、几个关键问题:
a)调试技巧:
breakpoint可以设置断点,f8之后运行到断点处;
F5单步执行,F8全部执行,这跟VS不太一样。
在debug窗口选中想要执行的内核,然后右键group cores 就可以新建一个组,组里包括若干个核,对这个组进行F8 就可以几个核一起运行。
在view菜单下可以选择观察寄存器,变量追踪什么的,方便调试。
b)关于工程文件说明:
include 默认链接到了本工程需要的.h文件库,基本不用修改,特殊情况除外。
hello.c是核心代码编写文件,C语言。
CMD文件时硬件设备的地址配置文件,挺重要的,一开始就是因为这个文件没弄懂,走了好大弯路。下面介绍下这个文件。
ccxml是目标配置文件,连接硬件板卡用的。
有的时候可能会遇到gel文件,目前还没搞懂这个gel文件是什么东西,怎么用。后续再研究。
c)CMD文件编写
cmd:链接器配置文件,存放链接器的配置信息,cmd文件使开发者可以通过自己定义的存储器模块来配置系统存储器,说白点也就是cmd是用来分配ROM和RAM空间用的,告诉链接程序怎样计算地址和分配空间。
MEMORY命令:描述系统实际的硬件资源
SECTION命令:描述“段”如何定位
其中比较关键的就是MEMORY和SECTIONS两个伪指令的使用,MEMORY用来建立目标存储器的模型,SECTIONS指令就可以根据这个模型来安排各个段的位置,MEMORY指令可以定义目标系统的各种类型的存储器及容量。
把hello world里的CMD文件拷上来分析一下:
-heap是堆,我这里分出3M是因为我把所有段都分配在了Share RAM(
SHRAM)上,L2一共有4M。
-stack 是栈,一般都是这么大。
memory是L1、L2、SHRAM、EMIF和DDR3的地址范围和大小,一般的应用都会用DDR3,由于我的板卡还没开发DDR3,就只好都用SHRAM了。
section里的字段:
.cinit 存放程序中的变量初值和常量
.const 存放程序中的字符常量、浮点常量和用const声明的常量
.switch 存放程序中switch语句的跳转地址表
.text 存放程序代码
.bss 为程序中的全局和静态变量保留存储空间
.far 为程序中用far声明的全局和静态变量保留空间
.stack 为程序系统堆栈保留存储空间,用于保存返回地址、函数间的参数传递存储局部变量和保存中间结果
.sysmem 用于程序中的malloc 、calloc 、和realoc 函数动态分配存储空间
/*************************************************************************/
-c
-heap 0x300000
/*3MB*/
-stack0x10000
MEMORY
{
LOCAL_L2_SRAM:
o = 0x00800000
l = 0x00080000
/* 512kB LOCAL L2/SRAM */
LOCAL_L1P_SRAM:
o = 0x00E00000
l =0x00008000
/* 32kB LOCAL L1P/SRAM */
LOCAL_L1D_SRAM:
o = 0x00F00000
l =0x00008000
/* 32kB LOCAL L1D/SRAM */
SHRAM: o = 0x0C000000
l = 0x00400000
/* 4MB Multicore shared Memmory */
EMIF16_CS2:
o = 0x70000000
l = 0x04000000
/* 64MB EMIF16 CS2 Data Memory */
EMIF16_CS3:
o = 0x74000000
l = 0x04000000
/* 64MB EMIF16 CS3 Data Memory */
EMIF16_CS4:
o = 0x78000000
l = 0x04000000
/* 64MB EMIF16 CS4 Data Memory */
EMIF16_CS5:
o = 0x7C000000
l = 0x04000000
/* 64MB EMIF16 CS5 Data Memory */
DDR3: o = 0x80000000
l = 0x80000000
/* 2GB CE0 and CE1 external DDR3 SDRAM */
}
SECTIONS
{
.text > SHRAM
.stack > SHRAM
.bss > SHRAM
.cio > SHRAM
.const > SHRAM
.data > SHRAM
.switch > SHRAM
.sysmem > SHRAM
.far > SHRAM
.args > SHRAM
.ppinfo > SHRAM
.ppdata > SHRAM
/* COFF sections */
.pinit > SHRAM
.cinit > SHRAM
/* EABI sections */
.binit > SHRAM
.init_array > SHRAM
.neardata > SHRAM
.fardata > SHRAM
.rodata > SHRAM
.c6xabi.exidx > SHRAM
.c6xabi.extab > SHRAM
}