主题中讨论的其他器件: TMS320F2810、 CCStudio
由于公司不再存在、并且 SDFlash 实用程序在 Windows 11中停止工作、因此一直在尝试为 SDFlash 创建替代产品。 在"TMS320F281x 引导 ROM 串行闪存编程"中、发现 CKFA 必须上传到引导 ROM、然后固件才能上载。 我从 http://www.ti.com/lit/zip/SPRAAQ2获得了 CKFA 源代码。 我意识到 zip 文件中提供的 theCKFA.bin 适用于 TMS320F2810 DSP、但我们使用的是 TMS320F2811 DSP。 我按照指示将 CKFA 用于 TMS320F2811 DSP、但当我运行代码时、我在 SDFlash 替换软件中遇到组帧错误、代码被卡住、发送几个换行符、并返回几个回车。 我已经在 VB.NET 中编写了代码来替换 SDFlash 软件。 如果需要,我愿意提供这一来源。 我还修改了 main 函数、但只显示了 textloadstart、textloadend 和 textRunStart 的地址、以验证其位置是否符合 Memcopy 调用中的预期。 我怀疑 CKFA.cmd 链接器命令文件中可能存在错误。 我同时使用 CKFA.cmd 文件和 DSP281x_Headers_nonBIOS.cmd 链接器命令文件。 我必须修改 CKFA.cmd 文件、以便它与 DSP281x_Headers_nonBIOS.cmd 一起工作。
这是我正在使用的 CKFA.cmd 文件。
/*
//######################################################################################################################
//
//文件:example_Flash2810_api.cmd
//
//标题:F2810闪存 API 示例的链接器命令文件
//
//######################################################################################################################
//$TI 发行版:Flash281x API v2.10 $
//$Release Date:2005年8月4日$
//######################################################################################################################
*
/*定义 F2812的内存块开始/长度
PAGE 0将用于组织程序段
第1页将用于组织数据段
注:
F281x 上的存储器块是一致的(也是相同的
物理存储器)。
不应该是相同的存储器区域
同时为 PAGE 0和 PAGE 1定义。
这样做将导致程序损坏
和/或数据。
*
#define objects_path C:\PathToSource\Debug\source
#define RTS_LIB_PATH C:\ti\ccsv5\tools\compiler\c2000_6.2.11\lib
#define FLASH2811_API_LIB_PATH C:\PathTo2811API_Library\API_Libraries
存储器
{
第0页:/*程序内存*/
/*内存(RAM/FLASH/OTP)块可移动到第1页进行数据分配*/
// RAMM0M1:origin = 0x000100,length = 0x000200 //片上 RAM 块 M0 */
// RAMM0M1:origin = 0x000040,length = 0x0003C0 //片上 RAM 块 M0 */
RAMM0M1:origin = 0x000000,length = 0x000400 //片上 RAM 块 M0 */
// RAMM2:origin = 0x000400,length = 0x000400
OTP:origin = 0x3D7800,length = 0x000800 //片上 OTP */
FLASHJ:origin = 0x3D8000,length = 0x002000 //片上闪存*/
FLASHI:origin = 0x3DA000、length = 0x002000 //片上闪存*/
FLASHH:origin = 0x3DC000、length = 0x004000 //片上闪存*/
FLASHG:origin = 0x3E0000,length = 0x004000 //片上闪存*/
FLASHF:origin = 0x3E4000、length = 0x004000 //片上闪存*/
FLASHE:origin = 0x3E8000、length = 0x004000 //片上闪存*/
FLASHD:origin = 0x3EC000、length = 0x004000 //片上闪存*/
FLASHC:origin = 0x3F0000,length = 0x004000 //片上闪存*/
FLASHB:origin = 0x3F4000,length = 0x002000 //片上闪存*/
FLASHA:origin = 0x3F6000,length = 0x001F80 //片上闪存*/
csm_RSVD:origin = 0x3F7F80,length = 0x000076 // FLASHA 的一部分。 当 CSM 正在使用时、使用所有0x0000进行编程。 *
begin:origin = 0x3F7FF6,length = 0x000002/* FLASHA 的一部分。 用于"引导至闪存"引导加载程序模式。 *
CSM_PWL:origin = 0x3F7FF8,length = 0x000008 // FLASHA 的一部分。 FLASHA 中的 CSM 密码位置*/
ROM:origin = 0x3FF000,length = 0x000FC0 //如果 MP/MCN=0,引导 ROM 可用
复位:origin = 0x3FFFC0,length = 0x000002 //引导 ROM 的一部分(MP/MCN=0)或 XINTF 区域7 (MP/MCN=1)*/
向量:origin = 0x3FFFC2,length = 0x00003E //引导 ROM 的部分(MP/MCN=0)或 XINTF 区域7 (MP/MCN=1)*/
第1页:
SCIA:origin = 0x007050、length = 0x000010 //* SCI-A 寄存器*/
RAML0L1:origin = 0x008000、length = 0x002000 //片上 RAM 块 L0 & L1 */
// RAMM0M1:origin = 0x000300,length = 0x000500 //片上 RAM 块 M0 */
RAMH0_1:origin = 0x3F8000、length = 0x001000 //片上 RAM 块 H0 */
RAMH0_2:origin = 0x3F9000,length = 0x001000 //片上 RAM 块 H0 */
第2页:
RAMH0_1:origin = 0x3F8000、length = 0x001000 //片上 RAM 块 H0 */
RAMH0_2:origin = 0x3F9000,length = 0x001000 //片上 RAM 块 H0 */
}
部分
{
//.text_unsecured:> RAMM0 | RAMM2 page = 0
text_unsecured:> RAMM0M1 PAGE = 0
{
objects_path\Unlock_main.obj (.text)
objects_path\DSP281x_CodeStartBranch.obj (.text)
objects_path\example_Flash281x_CsmKeys.obj (.text)
//objects_path\example_Flash281x_api.obj (.text)
//objects_path\HexToASCII.obj (.text)
//objects_path\SCI.obj (.text)
objects_path\DSP281x_Memcopy.obj (.text)
rts_lib_path\rts2800_ml.lib (.text)
// FLASH2811_API_LIB_path\Flash2811_API_V210.lib (.text)
//*(.text)
}
econst_unsecured:> RAMM0M1 PAGE = 0
/*.econst_unsecured:> RAMMEMOM2 page = 0 */
{
objects_path\unlock_main.obj (.econst)
}
.text:load = RAMH0_1、
运行= RAML0L1、
load_start (_textLoadStart)、
load_end (_textLoadEnd)、
run_start (_textRunStart)、
PAGE = 1.
econst:load = RAMH0_1,
运行= RAML0L1、
load_start (_econstLoadStart)、
load_end (_econstLoadEnd)、
run_start (_econstRunStart)、
PAGE = 1.
.cinit:> RAMM0M1 PAGE = 0
/*.cinit:> RAMMOM3 page = 0 */
/*用户定义的段*/
// codestart:> RAMM0M1 page = 0
BlockTransferBuffer1:>RAMH0_1 PAGE = 2
BlockTransferBuffer2:>RAMH0_2 PAGE = 2
csmpasswds:>csm_PWL page = 0
csm_rsvd:>csm_RSVD page = 0
/*分配未初始化的数据段:*/
//.stack:> RAMM0M1 page = 1.
.ebss:> RAML0L1 PAGE = 1.
/*.reset 是编译器使用的标准段。 它包含*/
/* C 代码_c_int00起始地址。 /*
/*当使用引导 ROM 时,此部分和 CPU 矢量*/
/*不需要表。 因此、默认类型设置为*/
/* DSECT */
.reset:> reset,page = 0,type = DSECT
VECTORS:> VECTORS PAGE = 0,TYPE = DSECT
SCIARegs :>SCIA PAGE = 1.
}
这是我正在使用的 DSP281x_Header_nonBIOS.cmd 文件
/*
//######################################################################################################################
//
//文件:DSP281x_Headers_nonBIOS.cmd
//
//标题:DSP281x 外设寄存器链接器命令文件
//
//描述:
//
//此文件用于非 BIOS 应用程序。
//
//链接器命令文件以放置外设结构
//在 DSP28头文件中使用到正确的内存中
//映射的位置。
//
//该版本的文件包括 PieVectorTable 结构。
//对于 BIOS 应用程序,请使用 DSP281x_Headers_BIOS.cmd 文件
//其中不包括 PieVectorTable 结构。
//
//######################################################################################################################
//
// Ver| dd mmm yyyy | WER |更改说明
//=== =================== =========== ================================================================================================
//| 2003年3月5日| A.A. |基于 DSP28 v0.58的原始版本
//1.00| 2003年9月11日| L.H. |集成到 DSP28头文件中
//||||添加了缺失的 eCAN 文件段
//---- |--- |---- |--------------------------------------------------
//######################################################################################################################
*
存储器
{
第0页:/*程序内存*/
第1页:/*数据存储器*/
DEV_EMU:origin = 0x000880,length = 0x000180 //器件仿真寄存器*/
PIE_VECT:origin = 0x000D00,length = 0x000100 // PIE 矢量表*/
flash_regs:origin = 0x000A80,length = 0x000060 //闪存寄存器*/
CSM:origin = 0x000AE0,length = 0x000010 //代码安全模块寄存器*/
XINTF:origin = 0x000B20,length = 0x000020 //外部接口寄存器*/
CPU_TIMER0:origin = 0x000C00,length = 0x000008 // CPU Timer0寄存器(CPU Timer1和 Timer2为 BIOS 保留)*/
PIE_CTRL:origin = 0x000CE0,length = 0x000020 // PIE 控制寄存器*/
ECANA:origin = 0x006000,length = 0x000040 // eCAN 控制和状态寄存器*/
ECANA_LAM:origin = 0x006040,length = 0x000040 // eCAN 本地接受屏蔽*/
ECANA_MOTS:origin = 0x006080,length = 0x000040 // eCAN 消息对象时间戳*/
ECANA_MOTO:origin = 0x0060C0,length = 0x000040 // eCAN 对象超时寄存器*/
ECANA_MBOX:origin = 0x006100,length = 0x000100 // eCAN 邮箱*/
系统:origin = 0x007010,length = 0x000020 //系统控制寄存器*/
SPIA:origin = 0x007040,length = 0x000010 // SPI 寄存器*/
// SCIA:origin = 0x007050,length = 0x000010 //* SCI-A 寄存器*/
XINTRUPT:origin = 0x007070,length = 0x000010 //外部中断寄存器*/
GPIOMUX:origin = 0x0070C0,length = 0x000020 // GPIO 复用寄存器*/
GPIODAT:origin = 0x0070E0,length = 0x000020 // GPIO 数据寄存器*/
ADC:origin = 0x007100,length = 0x000020 // ADC 寄存器*/
EVA:origin = 0x007400,length = 0x000040 // Event Manager A register *
EVB:origin = 0x007500、length = 0x000040 // Event Manager B 寄存器*/
SCIB:origin = 0x007750、length = 0x000010 //* SCI-B 寄存器*/
MCBSPA:origin = 0x007800,length = 0x000040 // McBSP 寄存器*/
CSM_PWL:origin = 0x3F7FF8,length = 0x000008 // FLASHA 的一部分。 CSM 密码位置。 *
}
部分
{
PieVectTableFile :> PIE_VECT,PAGE = 1.
/***外设帧0寄存器结构***/
DevEmuRegsFile :>DEV_EMU,PAGE = 1.
FlashRegsFile:> flash_regs,page = 1.
CsmRegsFile :>CSM,page = 1.
XintfRegsFile :>XINTF,PAGE = 1
CpuTimer0RegsFile:>CPU_TIMER0,PAGE = 1
PieCtrlRegsFile :> PIE_CTRL,PAGE = 1.
/***外设帧1寄存器结构***/
SysCtrlRegsFile:>系统,PAGE = 1.
SpiaRegsFile :>SPIA,page = 1.
// SciaRegsFile:>SCIA,page = 1.
XIntertRegsFile :>XINTRUPT,PAGE = 1.
GpioMuxRegsFile:> GPIOMUX,PAGE = 1
GpioDataRegsFile:> GPIODAT 页= 1.
AdcRegsFile:> ADC,PAGE = 1.
EvaRegsFile:>EVA,PAGE = 1
EvbRegsFile:> EVB,PAGE = 1
ScibRegsFile:>SCIB,page = 1.
McbspaRegsFile :>MCBSPA,page = 1.
/***外设帧2寄存器结构***/
ECanaRegsFile:> ECANA,PAGE = 1.
ECanaLAMRegsFile:> ECANA_LAM PAGE = 1.
ECanaMboxesFile:> ECANA_MBOX PAGE = 1.
ECANaMOTSRegsFile:> ECANA_MOTS PAGE = 1.
ECANaMOTOMESH 文件:> ECANA_MOTO PAGE = 1.
/***代码安全模块注册结构***/
CsmPwlFile:>csm_PWL,page = 1.
}
/******* 文件结束******** /
我正在使用 unlock_main.c
#include "SCI_Boot.h"
#include "Flash281x_API_Library.h"
#include "example_Flash281x_api.h"
extern void main2 (void);
uint16 example_CsmUnlock (void);
void SCI_SendStatus (char *);
extern void example_Error (uint16);
extern void Memcopy (uint16 *、uint16 *、uint16 *);
extern volatile struct SCI_regs SCIARegs;
//这些由链接器定义
extern uint16 textLoadStart;
extern uint16 textLoadEnd;
extern uint16 textRunStart;
extern uint16 econstLoadStart;
extern uint16 econstLoadEnd;
extern uint16 econstRunStart;
//空 Memcopy (uint16 * SourceAddr、uint16* SourceEndAddr、uint16* DestAddr)
/* void Memcopy (uint16 * SourceAddr、uint16* SourceEndAddr、uint16* DestAddr)
{
while (SourceAddr < SourceEndAddr)
{
*DestAddr++=*SourceAddr++;
}
返回;
}
*
void ConvertUint32ToHexString (uint32 val、char * ret)
{
字符 curByte;
uint32 temp = val;
uint32 nibbleDivisor = 0x10000000;
uint32 nibbleMask = 0x0FFFFFFF;
int i = 0;
RET[0]='0';RET[1]='x';
for (i = 0;i < 8;i++){
curByte = temp / nibbleDivisor;
if (curByte >= 0x0A)
RET[I + 2]= curByte +'A'- 10;
其他
RET[I + 2]= curByte +'0';
nibbleDivisor >=4;
temp = temp & nibbleMask;
nibbleMask = nibbleMask >=4;
}
RET[10]='\0';
}
void ConvertUint16ToHexString (uint16 val、char * ret)
{
字符 curByte;
uint16 temp = val;
uint16 nibbleDivisor = 0x1000;
uint16 nibbleMask = 0x0FFF;
int i = 0;
RET[0]='0';
RET[1]='x';
for (i = 0;i < 4;i++){
curByte = temp / nibbleDivisor;
if (curByte >= 0x0A)
RET[i+2]= curByte +'A'- 10;
其他
RET[i+2]= curByte +'0';
nibbleDivisor >=4;
temp = temp & nibbleMask;
nibbleMask = nibbleMask >=4;
}
RET[6]='\0';
}
void ConvertUint16PointerToHexString (uint16 * val、char * ret)
{
字符 curByte;
uint32 temp =(uint32) val;
uint32 nibbleDivisor = 0x10000000;
uint32 nibbleMask = 0x0FFFFFFF;
int i = 0;
RET[0]='0';RET[1]='x';
for (i = 0;i < 8;i++){
curByte = temp / nibbleDivisor;
if (curByte >= 0x0A)
RET[I + 2]= curByte +'A'- 10;
其他
RET[I + 2]= curByte +'0';
nibbleDivisor >=4;
temp = temp & nibbleMask;
nibbleMask = nibbleMask >=4;
}
RET[10]='\0';
}
//CKFA 的入口点代码是 main(),由 Boot-ROM 代码传输
//到不安全的 RAM。 它从此处尝试解锁 CSM。
void main (void)
{
uint16状态;
字符 addr[7];
字符 addr32[11];
//清除超级终端屏幕
// SCIARegs.SCIFFCT.bit.CDC = 0;
// SCIARegs.SCIHBAUD = 0x00;
// SCIARegs.SCILBAUD = 0x07;
SCIARegs.SCIFFTX.bit.SCIFFENA=1;
SCIARegs.SCIFFTX.bit.TXFIFOXRESET = 0;
SCIARegs.SCIFFTX.bit.TXFIFOXRESET = 1;
// uint16 oneWord;
// oneWord =*((UINT16 *)(0x3f8000));
// Memcopy ((uint16 *)(0x3f8000)、(uint16 *)(0x3f84eb)、(uint16 *)(0x008000));
// ConvertUint16ToHexString (oneWord、&addr[0]);
// SCI_SendStatus ("第一个字:");
// SCI_SendStatus (addr);
// SCI_SendStatus ("\n\n");
// oneWord =*(((uint16 *) 0x3f8010);
// ConvertUint16ToHexString (oneWord、&addr[0]);
// SCI_SendStatus ("第三十二个字:");
// SCI_SendStatus (addr);
// SCI_SendStatus ("\n\n");
// oneWord =*(((uint16 *) 0x3f8030);
// ConvertUint16ToHexString (oneWord、&addr[0]);
// SCI_SendStatus ("第四 十八个字:");
// SCI_SendStatus (addr);
// SCI_SendStatus ("\n\n");
// Memcopy (&textLoadStart、&textLoadEnd、&textRunStart);
// Memcopy (&econstLoadStart、&econstLoadEnd、&econstRunStart);
// main2();
// uint32k = 0;
// while (k < 900)
//{
// k++;
// if ((k % 300)==0){
//SCI_SendStatus (".");
//SCI_SendStatus ("\n\n");
//}
//}
// SCI_SendStatus ("PMCopy\n\r");
addr32[0]='\0';
ConvertUint16PointerToHexString (&textLoadStart、&addr32[0]);
SCI_SendStatus ("TLS:");
SCI_SendStatus (addr32);
SCI_SendStatus ("\n\n");
addr32[0]='\0';
ConvertUint16PointerToHexString (&textLoadEnd、&addr32[0]);
SCI_SendStatus (" tle:");
SCI_SendStatus (addr32);
SCI_SendStatus ("\n\n");
// SCIA_Init()
addr32[0]='\0';
ConvertUint16PointerToHexString (&textRunStart、&addr32[0]);
SCI_SendStatus ("TRS:");
SCI_SendStatus (addr32);
SCI_SendStatus ("\n\n");
/*
while (k < 900)
{
K++;
}
*
/*
SCIARegs.SCIHBAUD = 0x00;
SCIARegs.SCILBAUD = 0x07;
while (k < 900)
{
K++;
}
*
SCI_SendStatus ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
SCI_SendStatus ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
/* while (1)
{
int j = 0;
J++;
}
*
//尝试 CSM 解锁
status = example_CsmUnlock();
if (状态!= STATUS_SUCCESS)
{
SCI_SendStatus ("密码错误、解锁处理器失败。\n\n");
asm (" ESTOP0");
asm (" SB 0、UNC");
}
// SCI_SendStatus ("PIU\n\r");
// SCI_SendStatus ("处理器已解锁。\n\n");
/* while (1)
{
int j = 0;
J++;
}
*
//将 main2()和其余的 CKFA 代码复制到安全 RAM
//为应用程序代码传输到 RAM 腾出空间。
Memcopy (&textLoadStart、&textLoadEnd、&textRunStart);
Memcopy (econstLoadStart、econstLoadEnd、econstRunStart);
// SCI_SendStatus ("PMCopy\n\r");
Main2();
}
//####################################
// void SCI_SendStatus (void)
//------------------------------------
//此例程通过 SCIA 发送一系列字符
//
//------------------------------------
//this 函数需要位于该文件中、因为链接器关联了代码
//从该文件在不安全的 RAM 中具有加载地址
void SCI_SendStatus (char *msg)
{
while (* msg)
{
while (((SCIARegs.SCIFFTX.bit.TXFFST<16)&&*msg)
SCIARegs.SCITXBUF =* msg++;
while (SCIARegs.SCIFFTX.bit.TXFFST);//TX FIFO 为空?
}
返回;
}
/*-----------------
示例_CsmUnlock
解锁代码安全模块(CSM)
参数:
返回值:
STATUS_SUCCESS CSM 已解锁
STATUS_FAIL_UNLOCK CSM 未解锁
注:
---------------------------------------- *
uint16 example_CsmUnlock()
{
易失性 uint16温度;
//使用当前密码加载密钥寄存器
//这些是在 Example_Flash281x_CsmKeys.asm 中定义的
EALLOW;
*KEY0 = PRG_key0;
*key1 = PRG_key1;
*key2 = PRG_key2;
*key3 = PRG_key3;
*KEY4=PRG_key4;
*KEY5=PRG_key5;
*KEY6=PRG_key6;
*KEY7=PRG_key7;
EDIS;
//执行密码位置的虚拟读取
//如果它们与密钥值匹配,CSM 将解锁
temp =* PWL0;
温度=* PWL1;
temp =* PWL2;
temp =* PWL3;
温度=* PWL4;
温度=* PWL5;
温度=* PWL6;
温度=* PWL7;
//如果 CSM 未锁定,则返回成功,否则返回
//失败。
如果(* CSMSCR & 0x0001)=0)返回 STATUS_SUCCESS;
否则返回 STATUS_FAIL_CSM_LOCKED;
}
Device Monitor studio 显示最后几个传输到引导 ROM 的字节、后跟文本 LoadStart、文本 LoadEnd 和文本 RunStart 的地址。 这些地址来自行
addr32[0]='\0';
ConvertUint16PointerToHexString (&textLoadStart、&addr32[0]);
SCI_SendStatus ("TLS:");
SCI_SendStatus (addr32);
SCI_SendStatus ("\n\n");
addr32[0]='\0';
ConvertUint16PointerToHexString (&textLoadEnd、&addr32[0]);
SCI_SendStatus (" tle:");
SCI_SendStatus (addr32);
SCI_SendStatus ("\n\n");
// SCIA_Init()
addr32[0]='\0';
ConvertUint16PointerToHexString (&textRunStart、&addr32[0]);
SCI_SendStatus ("TRS:");
SCI_SendStatus (addr32);
SCI_SendStatus ("\n\n");
代码永远不会对以下行进行编程:
SCI_SendStatus ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
SCI_SendStatus ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
感谢您的任何帮助。