This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28335:eCAN 挂起重新初始化。

Guru**** 2558250 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1340304/tms320f28335-reinitializing-of-ecan-hangs

器件型号:TMS320F28335

重新初始化 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 函数禁用除最高优先级中断之外的所有中断。  我可以尝试重新调整我们的代码以再次赢得比赛、但我想提出一个不依赖于运气的具体解决方案。  有什么建议吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我无法确定您是否在使用32位读取/写入来查看您的代码。 这是 极其 场景。 有关此操作和其他调试提示、请下载我的应用报告 http://www.ti.com/lit/SPRA876。 通过查看此检查清单、可以解决大多数 CAN 问题。  

    一旦你经过了设置 CCR=0 (并且确保 CCE=0)的周期、从那一点开始、就能够看到 CCE 位变为1 (设置 CCR 位后)、CANRX 引脚必须被感测为高电平、这是因为 CANRX 引脚被感测为高电平相当于总线处于空闲状态。 不过、最终 CANRX 引脚* 将会 *由于位填充要求高,所以不知道为什么无限循环发生。 有一个想法是尝试在发生这种情况时使用计时器并对模块进行软复位。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    对寄存器的所有访问都是32位的。  在第33行、我们进行了软复位。  在第45行、我们设置了 CCR 位以及其他一些位。 所以、你建议在等待 CCE 位时尝试软复位、然后定期设置 CCR 位?

    有一件事没有从文档中明确指出、当进入空闲状态后、是否需要设置 CCR 位?  如果可以、如何检测空闲状态?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    加电后的第一次初始化始终成功,

    上电时、CCR 位已经为1 (即、此位的复位值为1)。 所以、在上电时您不会遇到问题、我并不感到奇怪。  

    最终、但是、CANRX 引脚* 将会 *因位填充要求而变为高电平

    让我们多想一想、模块关心的是总线空闲状态、而不仅仅是 CANRX 引脚"变为高电平"(在总线空闲期间 CANRX 引脚将为高电平)。 IOW、只有在总线空闲期间才允许更改位时序。 更重要的是、仅允许节点在总线空闲期间加入总线。  

    所以您建议在等待 CCE 位时尝试软复位,然后定期设置 CCR 位吗?

    可以、虽然目前还不清楚为什么您不能设置 CCE 位。、特别是您提到此代码已经运行很多年了。

    文档中没有明确说明的一点是,进入空闲状态后是否需要设置 CCR 位?

    否。 用户应该能够将 CCR 位异步设置为总线活动。 然而、该节点将一直等到总线空闲、以设置 CCE 并允许您更改位时序。 同样、该节点将一直等到总线空闲、以便清除 CCE、并允许该节点重新加入总线。

    如果是这样,如何检测到空闲状态?

    基于以上几点、我认为没有必要这样做。 我尚未进行尝试、但您可以轮询 CANES 寄存器中的 RM/TM 位。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我使用示波器发现、上电时远程器件静默约2秒、然后开始抖动、以开始通信。  一旦开始通信、就不允许出现空闲条件。  这就是 CCE 位从未被置位的原因。  由于我无法更改远程器件、我将创建某种类型的波特率检测、因此只能初始化一次。  感谢您的意见。