主题: controlSUITE中讨论的其他部件
正如标题所示,我使用的是TMS320F2.8069万 MCU。
我的代码大致描述如下:当设备通电时,它将直接进入GetMode。 从那里,它会闪存。 在闪存开始时,辅助引导加载程序(我编写的) 确定是将代码加载到其他闪存扇区(此辅助引导加载程序保存在从未擦除的扇区中),还是继续使用已在闪存中的代码。 如果需要加载新代码,它将进入SCI引导模式。 从那里, C2000串行固件升级器的修改版本用于将f2.8069万_flash_kernel加载到RAM。 f2.8069万_flash_kernel将新代码加载到闪存中。 C2000串行固件升级器和f2.8069万_flash_kernel都是从controlSUITE获得的。
在测试辅助引导加载程序时,我想 在f2.8069万_flash_kernel尝试加载到闪存时物理断开计算机和MCU之间的串行电缆。 这样做是因为我的辅助引导加载程序在引导时必须始终可用,以便将代码加载到闪存。 因此,应该没有办法阻止将代码加载到闪存中。 我的辅助引导加载程序仅位于扇区A,其余代码位于其他闪存扇区。
我能够反复执行此测试,没有问题。 但是, 在最近的一次测试中,MCU进入了低功耗模式。 我尝试使用Code Composer和JTAG 端口下载代码。 但是,当我 尝试这样做时,它说它处于低功耗模式,不允许我重新下载代码。
我尝试重启主板,但它仍然进入低功耗模式。 这表示闪存中一定有某个东西会将其设置为低功耗模式。
基于所有这些,我有以下问题:
1.当处于低功耗模式时,我是否应该只强制GPIO引脚处于特定状态,关闭电源再打开,然后尝试使用JTAG重新加载? 或者只需将XRS引脚拉高就足够了吗?
2.我的辅助引导加载程序代码中没有处理低功耗模式寄存器的内容。 请参阅下面我的main.c。 同样,这完全是在A区(在发生此问题之前,我检查了拆卸过程,以验证是否发生了此问题)。 但是,正如我所提到的,如果它在一个电源循环后仍进入低功耗模式,则闪存中一定会有某种东西将它设置为低功耗模式之一。 这怎么可能? 如有任何建议,我们将不胜感激。
/****************************************************************
*文件:main.c.
*器件:TMS320F2806x
*************** /
#define main_C
#include "main.h"//主include文件
#include <F2806X_Device.h>// F2806x头文件外围设备地址定义
#include "DynaLinkBegin.h"
#include <Flash2806X_API_Library.h>
#pragma code_section (bootloaderStart,"bootStart")
#pragma code_section (CsmUnlock_Bootloader,"bootStart")
#pragma code_section (SCI_Init_Bootloader,"bootStart")
#pragma code_section (SCI_Autobaud_Bootloader,"bootStart")
#pragma code_section (main,"bootStart")
#pragma code_section (sci_msg_boot,"bootStart")
#pragma code_section (sci_xmit_boot,"bootStart")
void bootloaderStart(void);
UINT16 CsmUnlock_Bootloader(void);
void SCI_Init_Bootloader(void);
UINT16 SCI_Autobaud_Bootloader(void);
void sci_msg_boot(UINT16 p, unsigned char *msg);
void sci_xmit_boot(UINT16 p, unsigned char a);
extern void SciBoot(void);
//在Passwords.asm中定义
// CSM键值
UINT16 PRG_KEY0;
UINT16 PRG_KEY1;
UINT16 PRG_KEY2;
UINT16 PRG_KEY3;
UINT16 PRG_KEY4;
UINT16 PRG_KEY5;
UINT16 PRG_KEY6;
UINT16 PRG_KEY7;
Void主(void)
{
bootloaderStart();
DynalinkMain();
}//main()的结尾
/*------------------
CsmUnlock_Bootloader
解锁代码安全模块(CSM)
参数:
返回值:
STATUS_SUCCESS CSM已解锁
STATUS_FAIL_UNLOCK CSM未解锁
注:
---------------------------------- */
UINT16 CsmUnlock_Bootloader()
{
易失性UINT16温度;
//使用当前密码加载密钥寄存器
//这些在example_Flash2806x_CsmKeys.asm中定义
ASM (" EALLOW");
CsmRegs.KEY0 = PRG_KEY0;
CsmRegs.key1 = PRG_key1;
CsmRegs.key2 = PRG_key2;
CsmRegs.key3 = PRG_key3;
CsmRegs.KEY4 = PRG_KEY4;
CsmRegs.KEY5 = PRG_KEY5;
CsmRegs.KEY6 = PRG_KEY6;
CsmRegs.KEY7 = PRG_KEY7;
ASM (" EDIS");
//执行密码位置的虚拟读取
//如果它们与密钥值匹配,CSM将解锁
TEMP = CsmPwl.PSWD0;
TEMP = CsmPwl.PSWD1;
TEMP = CsmPwl.PSWD2;
TEMP = CsmPwl.PSWD3;
TEMP = CsmPwl.PSWD4;
TEMP = CsmPwl.PSWD5;
TEMP = CsmPwl.PSWD6;
TEMP = CsmPwl.PSWD7;
//如果CSM已解锁,则返回成功,否则返回
//失败。
如果((CsmRegs.CSMSCR.ALL & 0x0001)== 0)
返回STATUS_SUCCESS;
否则
返回STATUS_FAIL_CSM_LOCKED;
}
/*------------------
SCI_Init_Bootloader
SCI初始化。
参数:
返回值:
注:
自定义SCI初始化,其内嵌以确保
可以进行自动波特率和脱字符传输。 在中也需要它
以便在ROM中成功分支到SCI引导模式。
---------------------------------- */
void SCI_Init_Bootloader()
{
ASM (" EALLOW");
//启用SCI-A时钟。
SysCtrlRegs.PCLKCR0.bit.SCIANCLK=1;
SysCtrlRegs.LOSPPCN.ALL = 0x0002;
//重置SCI FIFO传输寄存器。
SciaRegs.SCIFFTX.ALL = 0x8000;
// 1个停止位,无奇偶校验,8位字符
SciaRegs.SCICCR.ALL = 0x0007;
//启用TX和RX。
SciaRegs.SCICTL1.all = 0x0003;
//禁用TX和RX中断和标志。
SciaRegs.SCICT2.all = 0x0000;
//SCI复位,同时保持TX和RX启用。
SciaRegs.SCICTL1.all = 0x0023;
//启用SCI-A引脚上的上拉
// GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0;
// GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0;
gpioCtrlRegs.gpapud.all &= 0xCFFFFFFF;
//启用SCI-A引脚
// GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1;
// GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1;
gpioCtrlRegs.GPAMUX2.all |= 0x500万;
// SCI-A RX的输入qual为异步
GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3;
SciaRegs.SCIHBAUD = 0x0000;
SciaRegs.SCILBAUD = 0x0000;
SciaRegs.SCIFFRX.ALL = 0x201F;
SciaRegs.SCIFFCT.ALL = 0x0000;
SysCtrlRegs.WDCR = 0x0068;//禁用监视程序。
SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 0;//打开内部振荡器1
SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 0;// Clk src = INTOSC1
SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1;//关闭XCLKIN
SysCtrlRegs.CLKCTL.bit.XTALLOSCOFF = 1;//关闭XTALOSC
SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1;//关闭INTOSC2
//确保PLL未在跛行模式下运行。
如果(SysCtrlRegs.PLLSTS.bit.MCLKSTS !=0){
EALLOW;
//检测到OSCCLKSRC1故障。 PLL在跛行模式下运行。
//重新启用缺少的时钟逻辑。
SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;
EDIS;
//将此线路替换为呼叫适当的
// SystemShutdown();函数。
_ASM (" ESTOP0");
//为调试目的取消注释
}
// DIVSEL必须为0,然后才能更改PLLCR
// 0x0000。 通过外部重置XRSn将其设置为0
//这让我们进入1/4
SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
//更改PLLCR
如果(SysCtrlRegs.PLLCR.bit.DIV !=18){
//在设置PLLCR之前,请关闭缺少时钟检测逻辑
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
SysCtrlRegs.PLLCR.bit.DIV = 18;
//可选:等待PLL锁定。
//在此期间,CPU将切换到OSCCLK/2,直到
// PLL稳定。 PLL稳定后,CPU将保持稳定
//切换到新的PLL值。
//
//此锁定时间由PLL锁定计数器监控。
//
//等待PLL锁定时不需要密码。
//但是,如果代码执行任何对时间至关重要的操作,
//并要求锁定正确的时钟,则最好是
//等待此切换完成。
//等待PLL锁定位设置。
同时(SysCtrlRegs.PLLSTS.bit.PLLLOCKS !=1){
//取消注释以服务监视程序
// ServiceDog ();
}
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;
}
SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
ASM (" EDIS");
}
/*------------------
SCI_Autobaud_Bootloader
参数:
返回值:
注:
这将确定SCI传输的波特率
发生。 这是必需的,因为需要先传送脱字符
进入ROM中的SCI引导模式。
---------------------------------- */
UINT16 SCI_Autobaud_Bootloader()
{
UINT16字节数据;
UINT16超时;
UINT32 j;
UINT32 timePeriodBL = 6000万;
//必须使用>=1进行初始波特寄存器
SciaRegs.SCILBAUD = 1;
//准备自动波特率检测
//设置CDC位以启用自动波特检测
//并清除Abd位
SciaRegs.SCIFFCT.bit.CDC = 1;
SciaRegs.SCIFFCT.Bit.ABDCLR = 1;
//等待我们正确读取
//'A'或'A'并锁定
超时= 0;
while ((SiaRegs.SCIFFCT.bit.Abd !=1)&&(timeout == 0))
{
用于(j=0;(j<timePeriodBL)&&(SiaRegs.SCIFFCT.bit.Abd !=1);j++){};
如果(j >= timePeriodBL){timeout = 1;}
}
//自动波特锁后,清除Abd和CDC位
SciaRegs.SCIFFCT.Bit.ABDCLR = 1;
SciaRegs.SCIFFCT.bit.CDC = 0;
IF (超时== 0)
{
while ((SiaRegs.SCIRXST.bit.RXRDY !=1)&&(timeout ==0))
{
用于(j=0;(j<timePeriodBL)&&(SiaRegs.SCIRXST.bit.RXRDY !=1);j++){};
如果(j >= timePeriodBL){timeout = 1;}
}
IF (超时== 0)
{
byteData = SciaRegs.SCIRXBUF.bit.RXDT;
SciaRegs.SCITXBUF =字节数据;
}
}
返回超时;
}
void bootloaderStart()
{
UINT16状态;
UINT16字节数据;
UINT16 autoBaudStatus =1;
UINT16超时;
UINT32 j;
UINT32 timePeriodBLS = 6000万;
状态= CsmUnlock_Bootloader();
如果(状态== status_success){
// SCI_Boot之前的初始化
SCI_Init_Bootloader();
//执行自动波特率。
AutoBaudStatus = SCI_Autobaud_Bootloader();
IF (autoBaudStatus == 0)
{
字节数据= 0x0000;
//等待插入记号。 如果在特定时间内收到
//of time,然后转至引导ROM中的SCI_Boot。
sci_msg_boot(0),"^";
超时= 0;
while ((SiaRegs.SCIRXST.bit.RXRDY !=1)&&(timeout ==0))
{
用于(j=0;(j<timePeriodBLS)&&(SiaRegs.SCIRXST.bit.RXRDY!=1);j++)
{
sci_msg_boot(0),"^";
};
如果(j >= timePeriodBLS){timeout = 1;}
}
如果(超时== 0)
{
byteData = SciaRegs.SCIRXBUF.bit.RXDT;
//如果收到插入记号,请转至Boot ROM中的SCI_Boot。
IF (字节数据== 0x005E)
{
SciBoot();
ASM (" EDIS");
}
}
}
}
}
void sci_msg_boot(UINT16 p, unsigned char *msg)
{
unsigned char *ptr;
PTR =消息;
while (*ptr !='\0')
{
sci_xmit_boot(p,*ptR);
PTR++;
}
}
void sci_xmit_boot(UINT16 p, unsigned char A)
{
如果(p == 0)
{
// while (SiaRegs.SCICTL2.bit.TXRDY ==0)//准备将另一个字符放入传输缓冲区
而(SciaRegs.SCICTL2.bit.TXEMPTY ==0)//准备将另一个字符放入传输缓冲区
{
//等待上一个字符完成传输
//如果这花费的时间太长,则更改为中断驱动
}
SciaRegs.SCITXBUF =(A & 0x00FF);
}
否则,如果(p = 1)
{
// a = 0x55;
// while (ScibRegs.SCICTL2.bit.TXRDY == 0)
While (ScibRegs.SCICTL2.bit.TXEMPTY == 0)(时(ScibRegs.SCICTL2.bit.TXEMPTY == 0))
{
//等待上一个字符完成传输
}
ScibRegs.SCITXBUF =(A和0x00FF);
}
否则
{
//选择了错误的端口
}
}