怀疑是总线上其它设备发送数据发送了一半,d133才开始接收,结果报错。关键是,一次报错后,接下来所有的接收数据都报错。
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Other Error, [E] hal_can_bus_error_msg()335 Tolerate dominant bits
有什么解决办法好呢?一旦进入can错误处理这里就进行重启操作?
离线
也是准备用can,但没测试过。最好不要有啥问题。
离线
irqreturn_t hal_can_isr_handler(int irq_num, void *arg)
{
u32 int_status;
can_handle *phandle = (can_handle *)arg;
int_status = readl(phandle->can_base + CAN_INTR_REG);
if (int_status & (CAN_INTR_ERRB | CAN_INTR_ARBLOST | CAN_INTR_ERRP |
CAN_INTR_WAKEUP | CAN_INTR_OVF | CAN_INTR_ERRW))
hal_can_error_handle(phandle, int_status);
if (int_status & CAN_INTR_TX) {
phandle->status.sndpkgcnt++;
if (phandle->callback)
phandle->callback(phandle, (void *)CAN_EVENT_TX_DONE);
}
if ((int_status & CAN_INTR_RX) && !(int_status & CAN_INTR_OVF)) {
hal_can_rx_frame(phandle->can_base, &phandle->msg);
if (phandle->callback)
phandle->callback(phandle, (void *)CAN_EVENT_RX_IND);
}
writel(int_status, phandle->can_base + CAN_INTR_REG);
return IRQ_HANDLED;
}
aic_hal_can.c文件里,can中断函数中,是先看状态寄存器,一旦出现错误,就先去进行错误处理。
如果d133先上电,而总线上其它设备还没上电,则也会报can发送错误,这是可以理解的,can总线上没有其它can设备是发送不成功的。但其它can设备一上电,这个发送错误就会立刻消除了。
而接收错误这里,大部分情况下会一直错下去。
离线
这是can错误处理函数,直接CAN_INTR_ERRB错误,进hal_can_bus_error_msg()函数。
看到里边有对发送错误计数寄存器的读取staus.txerr,超过阈值后,将can设置为复位模式。
虽然有对接收错误计数寄存器stauts.rxerr的读取,但是没看到有其它地方调用到。
另有对溢出错误的累加计数。
而看错误提示,应该是:
ERRB_INT:Bus Error Interrupt,总线错误中断(节点检测到总线上发生了错误)。
错误信息里提到的是,接收方向错误,Tolerate dominant bits错误。
static void hal_can_error_handle(can_handle *phandle, u32 err_status)
{
u32 can_status;
u8 errcode;
errcode = readb(phandle->can_base + CAN_ERRCODE_REG) &
CAN_ERRCODE_SEGCODE_MASK;
can_status = readl(phandle->can_base + CAN_STAT_REG);
phandle->status.rxerr = readl(phandle->can_base + CAN_RXERR_REG);
phandle->status.txerr = readl(phandle->can_base + CAN_TXERR_REG);
if (err_status & CAN_INTR_ERRB) {
hal_can_bus_error_msg(phandle);
}
if (err_status & CAN_INTR_ARBLOST) {
hal_can_arblost_msg(phandle);
}
if (err_status & CAN_INTR_ERRP) {
if (phandle->status.current_state == PASSIVE_STATUS)
phandle->status.current_state = WARNING_STATUS;
else
phandle->status.current_state = PASSIVE_STATUS;
}
if (err_status & CAN_INTR_OVF) {
phandle->status.othererrcnt++;
phandle->status.recverrcnt++;
hal_can_set_mode(phandle, CAN_MODE_RST);
hal_can_mode_release(phandle, CAN_MODE_RST);
if (phandle->callback)
phandle->callback(phandle, (void *)CAN_EVENT_RXOF_IND);
/* clear bit */
writel(CAN_MCR_CLR_OVF, phandle->can_base + CAN_MCR_REG);
}
if (err_status & CAN_INTR_ERRW) {
if (can_status & CAN_STAT_BUS)
phandle->status.current_state = BUS_OFF;
else if (can_status & CAN_STAT_ERR)
phandle->status.current_state = WARNING_STATUS;
else
phandle->status.current_state = ACTIVE_STATUS;
}
if (phandle->status.current_state == BUS_OFF)
hal_can_mode_release(phandle, CAN_MODE_RST);
if (phandle->status.txerr > CAN_ERRP_THRESHOLD &&
errcode == CAN_ERRCODE_ACK_SLOT)
{
writel(CAN_MCR_ABORTREQ, phandle->can_base + CAN_MCR_REG);
hal_can_set_mode(phandle, CAN_MODE_RST);
hal_can_mode_release(phandle, CAN_MODE_RST);
}
}
hal_can_bus_error_msg()函数里,打印出了错误的方向、错误的类型、在哪个阶段出的错。
static void hal_can_bus_error_msg(can_handle *phandle)
{
u8 i;
u8 errinfo = readb(phandle->can_base + CAN_ERRCODE_REG);
u8 errtype = (errinfo & CAN_ERRCODE_ERRTYPE_MASK) >> 6;
u8 errdir = (errinfo & CAN_ERRCODE_DIR) >> 5;
u8 errcode = errinfo & CAN_ERRCODE_SEGCODE_MASK;
for (i = 0; i < ARRAY_SIZE(bus_err_dir); i++) {
if (errdir == bus_err_dir[i].code) {
hal_log_err("%s, ", bus_err_dir[i].msg);
if (i)
phandle->status.recverrcnt++;
else
phandle->status.snderrcnt++;
break;
}
}
for (i = 0; i < ARRAY_SIZE(bus_err_type); i++) {
if (errtype == bus_err_type[i].code) {
hal_log_err("%s, ", bus_err_type[i].msg);
switch (i) {
case 0:
phandle->status.biterrcnt++;
break;
case 1:
phandle->status.formaterrcnt++;
break;
case 2:
phandle->status.stufferrcnt++;
break;
default:
phandle->status.othererrcnt++;
break;
}
break;
}
}
for (i = 0; i < ARRAY_SIZE(bus_err_code); i++) {
if (errcode == bus_err_code[i].code) {
hal_log_err("%s\n", bus_err_code[i].msg);
break;
}
}
}
翻了手册,看到这么一段话:
错误报警阈值ERRWT将作为报警功能提示当前发生的总线错误,且在控制器进入被动错误状态之前被触发。在复位模式下,ERRWT数值可在错误报警阈值寄存器(CAN_ERRWT)中进行配置。当TEC和/或REC数值大于等于ERRWT时,ERR_STAT 被置1。当TEC 和REC 数值都小于ERRWT时, ERR_STAT被复位0。只要ERR_STAT或BUS_STAT位值发生变化,便会触发错误报警中断ERRW_INT。
当TEC和/或REC数值大于127 时,节点进入被动错误状态。当TEC和REC数值都小于等于127时,节点重新变为主动错误状态。节点在主动错误和被动错误状态之间切换时,都将触发被动错误中断ERRP_INT。
当TEC 数值大于255 时,节点进入总线关闭离线状态。此时,控制器将REC数值置为0、TEC数值置为127、BUS_STAT位置1、产生错误报警中断ERRW_INT、控制器进入复位模式。
为了返回主动错误状态,必须进行离线恢复。首先需要退出复位模式,进入正常操作模式;然后要求节点在总线上检测到128 次11 个连续隐性位。每一次检测到11 个连续隐性位时,TEC 数值都将减1,当离线恢复完成后(TEC 数值从127 减小到0),BUS_STAT位复位为0,从而触发错误报警中断ERRW_INT。
看can相关寄存器,有个CAN_MODE寄存器,0为复位模式,3为接收过滤。
最近编辑记录 Gentlepig (2024-05-25 14:11:31)
离线
bit4 R/W 0x0 SLEEP_MOD:Sleep Mode,休眠模式,只在复位模式可写
0x0:正常操作。控制器唤醒。
0x1:休眠模式。CAN无总线活动和无中断发生。
bit3 R/W 0x0 FILTER_MOD:Acceptance Filter Mode,接收过滤器模式
0x0:双过滤模式。使用两个过滤器。
0x1:单过滤模式。使用一个4字节过滤器。
bit2 R/W 0x0 SELFTEST_MOD:Self Test Mode,自测模式
0x0:正常操作。发送成功需有应答。
0x1:自测模式。在SELF_REQ自接收请求指令下,无需其它节点
参与也能完成整个节点测试,发送成功无需应答。
bit1 R/W 0x0 LISTEN_MOD:Listen Only Mode,只听模式
0x0:正常操作。错误计数停止于当前值 。
0x1:只听模式。只接收总线上数据,不产生应答信号,
也不更新接收错误计数。
bit0 R/W 0x1 RST_MOD:Reset Mode,复位模式
0x0:正常操作。控制器返回正常操作模式。
0x1:复位模式。发送或接收中止,控制器处于可配置状态。
这是can状态寄存器的描述。
程序里出错时打印了状态寄存器的值,我看是0xA2和0xF3差不多交替出现。这么看,像是在自动切换复位模式和正常模式。
[E] hal_can_bus_error_msg()340 0xA2
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Stuff Error, [E] hal_can_bus_error_msg()335 ID28~21
[E] hal_can_bus_error_msg()340 0xF3
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Other Error, [E] hal_can_bus_error_msg()335 Tolerate dominant bits
[E] hal_can_bus_error_msg()340 0xA2
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Other Error, [E] hal_can_bus_error_msg()335 Tolerate dominant bits
[E] hal_can_bus_error_msg()340 0xF3
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Other Error, [E] hal_can_bus_error_msg()335 Tolerate dominant bits
[E] hal_can_bus_error_msg()340 0xA2
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Stuff Error, [E] hal_can_bus_error_msg()335 ID28~21
[E] hal_can_bus_error_msg()340 0xA2
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Other Error, [E] hal_can_bus_error_msg()335 Tolerate dominant bits
[E] hal_can_bus_error_msg()340 0xF3
[E] hal_can_bus_error_msg()303 error in RX direction, [E] hal_can_bus_error_msg()314 Stuff Error, [E] hal_can_bus_error_msg()335 ID28~21
最近编辑记录 Gentlepig (2024-05-28 15:43:19)
离线
更新1.0.5版本的sdk后,上电时can容易进错误中断的现象消除了。
对比新旧两版test_can例程,发现新例程在打开并配置好can后,增加了句打开can中断的语句。
//enable CAN TX interrupt
rt_device_control(can_tx_dev, RT_DEVICE_CTRL_SET_INT, NULL);
上一版的例程里没这么一句,但是却能进can中断。奇怪。
另,新版的sdk,lvgl的rtp使能后正常了,但是旋转屏幕却变得不正常了。
在lv_port_disp.c里的lv_port_disp_init()函数里,增加这一句:
// disp_drv.rotated = LV_DISP_ROT_180;
画面视觉效果没有旋转,但是点击按钮没反映,而按旋转后的位值虚空点击,却出现了点击效果。
感觉是,画面貌似旋转了,但是呈现没旋转。
--------------------------------------------------------
比较下了,两版sdk,打开can时,参数里都带有中断方式参数,新版的,在设置完波特率等后,又通过ctrl命令打开中断。
于是对比了两版sdk里rtt_kernel里的can驱动部分,的rt_can_open(),发现给的参数里有中断方式,那么就在函数结尾处直接调用contrl命令打开中断。而新版里注释了这部分。
那么问题应该就是就板过早的打开了can接收中断,波特率还未配置,滤波器组也未配置,结果总线上有信息,于是就报错进错误中断了。
----------------------
lvgl屏幕旋转的问题是,忘了使能USE_DRAW_BUF这个宏定义。
最近编辑记录 Gentlepig (2024-06-24 15:40:30)
离线