重新初始化 eCAN 时出现问题、我们在等待 CCE 位在发出 CCR 请求后置位。 它在一个无限循环中挂起。 我们将 CAN 配置为125Kbaud、并尝试与旧器件通信。 如果没有响应、我们将重新配置为500k 波特并尝试与更新的器件通信。 这种配置已经使用了很多年、但现在仍然失败了。 上电后的第一次初始化始终成功、重新初始化现在失败。 原因似乎是由于竞争条件、随着最近代码的更改、我们现在失败了。
远程器件由本地器件供电、因此两个器件同时上电。 远程器件执行上电初始化、然后开始尝试与每1毫秒发送数据包的本地器件通信。 到目前为止、本地器件可以在远程器件开始通信之前完成对老式器件的检查并为新器件进行配置。 但是现在、似乎本地器件正在通信并且 CCE 位永远不会置位时尝试重新初始化。
代码本身已经很旧了。 它从 F2812系统移植到 F28335。 它最初是使用 Code Composer 3开发的、并使用 DSP/BIOS。 下面是初始化函数:
void CAN_init(int kBaud, CAN_pIsr pISR)
{
int mbx;
Uns old;
unsigned long baud = kBaud;
// unsigned long baud = kBaud*2000UL;
unsigned long brp;
unsigned int bt = 15;
unsigned long sam=0;
unsigned long sjw=0;
unsigned int SpPercent = 80;
unsigned long tseg1;
unsigned long tseg2;
Overwrite = ~0;
brp = ((SYSCLKOUT * 500UL)/(baud*bt))-1;
// brp = ((SYSCLKOUT * 1000000UL)/(baud*bt))-1;
bt--;
tseg1 = ((SpPercent*bt)/100);
tseg2 = bt-tseg1;
tseg1--;
tseg2--;
ISR = pISR;
for (mbx = 0; mbx < NUM_MAILBOXES; mbx++){
mbxISR[mbx] = NULL;
}
asm(" EALLOW");
old = DisableInterrupts();
CANMC |= SRES; // master reset
if (kBaud && brp>=1 && brp<=255 && sjw<=3 && sam<=1 && tseg1<=15 && tseg2<=7 && tseg2<=tseg1){
PCLKCR |= ECANENCLK;
GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; // Enable pull-up for GPIO18 (CANRXA)
GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; // Enable pull-up for GPIO19 (CANTXA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch qual for GPIO18 (CANRXA)
GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3; // Configure GPIO18 for CANRXA operation
GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 3; // Configure GPIO19 for CANTXA operation
RestoreInterrupts(old);
CANTIOC |= TXFUNC;
CANRIOC |= RXFUNC;
CANMC |= CCR | SCB | ABO | DBO;
asm(" EDIS");
while(!(CANES & CCE))
Sleep(1);
asm(" EALLOW");
CANBTC = (brp<<16)+(sjw<<8)+(sam<<7)+(tseg1<<3)+tseg2;
CANMC &= ~CCR;
CANMIL = 0xffffffff; // Set all mailbox interrupts to line 1, CAN_isr1()
// CANGIM = 0x00007f03; // Set which conditions will generate an interrupt
CANGIM = 0x00000803; // Set which conditions will generate an interrupt
asm(" EDIS");
while((CANES & CCE))
Sleep(1);
old = HWI_disable();
PIEACK = M_INT9; // Acknowledge INT9 interrupt to PIE
PIEIER9 |= INTx5; // Enable Peripheral Interrupt 9_5
PIEIER9 |= INTx6; // Enable Peripheral Interrupt 9_5
IER |= M_INT9; // Enable CPU Interrupt 9
HWI_restore(old);
}
else{
PCLKCR &= ~ECANENCLK;
RestoreInterrupts(old);
}
}
我在此代码中发现一个错误、其中 ELSE 子句在"禁用"条件(零波特)下不会发出 EDIS、但这不会影响问题。 DisableInterrupts/RestoreInterrupts 函数禁用除最高优先级中断之外的所有中断。 我可以尝试重新调整我们的代码以再次赢得比赛、但我想提出一个不依赖于运气的具体解决方案。 有什么建议吗?