外设使能
C6455有两个外设配置寄存器,PERCFG0和PERCFG1,大部分外设都由PERCFG0控制;PERCFG1只控制EMIFA和DDR,这个基本上在启动代码中就已经使能了。
PERCFG0中对应的外设的使能需要先往PERLOCK寄存器中写特定的值解锁后才能对PERCFG0的值进行修改,而且是有时间限制的,需要在16个SYSCLK3的周期内完成,也就是一般解锁后都紧跟着对PERCFG0的修改。修改后通过查询PERSTAT0寄存器来确认修改完成。
Bool enable = FALSE;
/* Unlock the control register */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK, DEV_PERLOCK_LOCKVAL, UNLOCK);
/* Enable the Powersaver clock for TIMER */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_TIMER0CTL, ENABLE);
do {
enable = (Bool) CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0, DEV_PERSTAT0_TIMER0STAT);
} while (enable != TRUE);
今天遇到了很奇怪的现象。我发现我的程序可以在调试的时候偶尔会出现无法修改PERCFG0的情况,也就是一直陷在上面的do…while的死循环里。经过多次尝试发现,如果把代码放在L2上就不会出现那种情况,但如果把代码放到DDR上就容易出现这种情况。而且把代码固化后,令代码在DDR上运行,程序无法正常运行;但是固化后,令代码在L2上运行则是正常的。
仔细查看手册后发现了这样一条:
也就是说把这部分配置代码放到DDR上的确是容易出问题的,那么怎样把这两条代码放到一个fetch packet里面呢?我没找到办法,因此最后的解决办法是把这部分使能外设的配置放到L2上。
下面的代码是对GPIO和TIMER0外设的使能
#pragma CODE_SECTION(PerConfig, ".percfg");
void PerConfig(void)
{
Bool enable = FALSE;
/* Unlock the control register */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK, DEV_PERLOCK_LOCKVAL, UNLOCK);
/* Enable the Powersaver clock for TIMER */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_TIMER0CTL, ENABLE);
do {
enable = (Bool) CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0, DEV_PERSTAT0_TIMER0STAT);
} while (enable != TRUE);
enable = FALSE;
/* Unlock the control register */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK, DEV_PERLOCK_LOCKVAL, UNLOCK);
/* Enable the GPIO */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_GPIOCTL, ENABLE);
do {
enable = (Bool) CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0, DEV_PERSTAT0_GPIOSTAT);
} while (enable != TRUE);
}
然后在cmd文件中将.percfg段放到L2上。
Flash查询ID
C6455的CE3片选区域连接的异步NOR Flash型号为S29GL064S,在使用的时候遇到一个小问题,就是它在上电后只能进入一次Autoselect Mode。
本来我是想读它的Manufacture ID和三个Device ID,但是只有上电后的第一读能够读到,后面退出Autoselect Mode之后如果不掉电,再次在调试的模式下尝试进Autoselect Mode就进不去了,本来应该读到的ID成了对应地址的具体数据。
这虽然是一个问题,但是并不影响具体的使用,Flash的擦除和烧录都没有问题,可能是这个器件就是这样的。