fstab 自动挂载_bios进入flash模式黑屏

(88) 2024-06-16 10:01:01

TMS320C6657挂载SPI Nor Flash自启动

    • 一.源程序修改
    • 二.单核启动
    • 三.从核启动

首先声明本文仅适用于TMS320C6657芯片,多核单镜像的SPI启动。TI C66X系列的资料比较零散,不系统,这无疑给像我这样的DSP初学者带来了极大的困难。因工作需要,将原有的EMIF启动的一个DSP程序改成SPI启动模式的程序,由于DSP烧写的不可观性,一直没找到问题所在,只能一步一步的摸索修改。在CSDN以及TI的官方论坛上查阅了大量的资料,站在巨人的肩膀上,好歹成功实现了。感慨DSP烧写的困难,特殊此文,希望能帮到跟我一样的DSP初学者。如有不严谨的地方还望大佬指教。
理论上的东西可以参考《TMS320C66x KeyStone架构多核DSP入门与实例精解》P314基于Nor Flash SPI的多核Boot实例这一节。本文主要是根据我调试过程编写的,比较粗显。

一.源程序修改

原有的程序是基于EMIF启动模式设计的,首先需要去掉一段用汇编语言编写的EMIFboot程序,他的功能是将Flash中的代码搬移到core0的L2SRAM中(flash运行速度低)并跳转到起始地址开始执行。但由于板子的设计问题,需要改成 SPI启动模式,所以把这一段汇编去掉了。

二.单核启动

正常生成.out文件后,通过TI公司提供的工具链转成dat(bin):
fstab 自动挂载_bios进入flash模式黑屏 (https://mushiming.com/)  第1张

hex6x 配合.rmd文件(有几个.out文件就需要几个.rmd文件,描述输出控制、引导选项、存储器选项等内容)生成片上引导加载器加载程序所需的引导表,输出文件为*.btbl

mergebtbl将*.btbl按照一定的顺序链接起来

b2i2c 将*.btbl转换成i2c/spi格式,把boot表划分成0x80字节块并附加长度(length)和校验码(checksum)

b2ccs将*.btbl.i2c转换成.i2c.ccs,CCSV5 IDE接收的.dat格式,加载到DDR3中去。并手动将i2crom.ccs中的第9行51改为00。

romparse 合并boot表和boot参数表,参数配置表文件*.map作为输入。

byteswapccs将.dat转换成ROM Bootloader代码能够识别的大端模式

生成的.bin文件通过flash烧写工具,这个是我自己写的,需要参考flash芯片的数据手册,跟型号有关,如果是开发板的话,开发版光盘里有烧写工具的镜像,这个不难。烧进去之后DSP复位,控制bootmode[15:0]=0001 0010 0000 1101,SPI启动模式,参数设置参考《TMS320C6657》BOOTMODE这一节,各个GPIO引脚设置与初设化外设相关。启动后并没有捕捉到DSP工作的信号,但不清楚问题出在哪。然后接了FLASH芯片的输入输出与时钟信号到示波器上,我们用的FLASH芯片地址位宽为24位,数据位宽为16位。通过时钟可以看到,输入信号前8位为指令,后24位为地址,再查看输出。通过比对bin文件发现,前1k的数据正常输出,但读完1k后,输入读取的地址为0x,超出了bin文件的长度所以DSP没有正常的工作。猜测这个地址应该是0x000400,刚好是1K与bin文件能对得上,因此我去查了固化在ROM里RBL源代码,验证了我的猜想。

typedef struct boot_params_spi_s { 
    /* common portion of the Boot parameters */ UINT16 length; UINT16 checksum; UINT16 boot_mode; UINT16 portNum; UINT16 swPllCfg_msw; /* CPU PLL configuration, MSW */ UINT16 swPllCfg_lsw; /* CPU PLL configuration, LSW */ UINT16 options; UINT16 addrWidth; /* 16 or 24 are the only valid values */ UINT16 nPins; /* 4 or 5 pins are the only valid values */ UINT16 csel; /* only values 0b10 (cs0 low) or 0b01 (cs1 low) are valid */ UINT16 mode; /* Clock phase/polarity. These are the standard SPI modes 0-3 */ UINT16 c2tdelay; /* Setup time between chip select assert and the transaction */ UINT16 cpuFreqMhz; /* Speed the CPU is running after PLL configuration */ UINT16 busFreqMhz; /* The speed of the SPI bus, the megahertz portion */ UINT16 busFreqKhz; /* The KHz portion of the bus frequency. A frequency of 1.5 MHz would have the value 5 here */ UINT16 read_addr_msw; /* The base address to read from the SPI, upper 16 bits */ UINT16 read_addr_lsw; /* The base address to read from the SPI, lower 16 bits */ UINT16 next_csel; /* The next chip select to use if in boot config mode, when the config is complete */ UINT16 next_read_addr_msw; /* The next read address to use if in boot config mode */ UINT16 next_read_addr_lsw; /* The next read address to use if in boot config mode */ } BOOT_PARAMS_SPI_T; 

fstab 自动挂载_bios进入flash模式黑屏 (https://mushiming.com/)  第2张
比对源代码和参数表以及bin文件发现,bin文件中offset30-32的地址上为0x,所以一直在读0x。也有看到相关的博客上说需要将50改成00,更加验证了我的这个想法,不知道原工具链的为50的目的,但确实改成00后单核启动成功了。

三.从核启动

我的源程序是双核单镜像的,程序不是特别复杂,但单镜像中通过DNUM寄存器让两个核执行不同的代码。刚开始我认为从核的启动只需要核0启动后,给核1的magicaddr写入_c_int00地址,再给IPC中断即可,尝试了N次之后发现从核一直起不来。分析原因:一是不是核1的代码没有从flash搬到内存里来?但核0的代码通过ROM里面的boot代码自动搬运了,核1和核0共用相同的代码,应该不需要再去搬运核1的代码。二是不是IPC中断没有给到,是不是需要初始化IPC中断,注册中断事件?最后发现都不是。我最后观看了x龙的DSP教学视频关于DSP6678多核架构的共享内存,想到我程序的cmd文件配置的代码和数据都是放在核内的L2SRAM中,ROM里的bootloader搬运也只有0核的,核1的L2SRAM
里并没有程序,所以一直起不来。我参考了x龙C6678光盘提供的MultiCore_SingleIamge源程序中的cmd文件,将.text,.cinit,.const等存入MSMCSRAM共享内存中。注意此时的_c_int00入口地址发生变化,重新赋值给核1 的magicaddr。再重新生成.out文件,再用工具链生成.bin文件烧写进去即可。后续就跟单核的一样了。

虽然现在写出来很轻松,但当时调试的时候是真的掉头发。特意写下来,仅供参考。

THE END

发表回复