IIC挂死原因探究

12 篇文章 0 订阅
1 篇文章 0 订阅

项目场景:

在炮台机器人项目中使用S3C244的IIC外设通讯时,频繁出现IIC挂死问题


问题描述:

在炮台机器人项目中使用S3C244的IIC外设中断方式通讯时,频繁出现IIC挂死问题,而且IIC数据线和时钟线都为零。IIC数据线和始终线都挂死的情况和以往不同。

IIC中断服务函数:

void Iic_ISP(void)
{
		static U8 RxData;
		U8 buf;
		U8 iicstate=rIICSTAT;
		OSIntEnter();  //进入中断服务函数,记录嵌套深度
	  buf=rIICDS;//读取iic数据寄存器以清除中断
		switch(iicstate)    //0x34->0x30->0x74->0x71
		{
			case 0x30:
				RxData=buf;
			  OSMboxPost(IicBox,&RxData);
			break;
			case 0x74:
					rIICDS=_iicTxData;
				break;
			case 0x71:
				rIICSTAT&=~0xcf;  //rIICSTAT = 0x10;
				break;
			default:
				break;
    }
		rIICCON=0xaf;
		ClearPending(BIT_IIC);
		OSIntExit();  //退出中断服务函数,实现“抢占式”任务调度
}

原因分析:

在S3C2440外设中有两个挂起寄存器:中断挂起寄存器(INTPND)和中断源挂起寄存器(SRCPND)。当中断源向CPU申请中断时,SRCPND寄存器的相应位被置1,表明哪个中断源向CPU申请了中断;如果当前优先级与此中断源相等或更高的中断服务在执行,并且改中断位会被响应,INTPND相应位会被置1。因此一旦响应中断,要在中断服务函数中清除上面两个寄存器的置位,清除方法是向对应位写1。清除置位写1的方式和平时位操作置1的方式有所不同。如下是开发板厂家提供的位清除

void __irq Timer0_ISP(void)
{	
	
	rSRCPND = rSRCPND | (0x1<<10);
    rINTPND = rINTPND | (0x1<<10);
    if(direction)
    	pulse++;
    else
    	pulse--;
    
}
如下是芯片官方提供的挂起位清除

```c
__inline void ClearPending(int bit)
{
//	int i;
	rSRCPND = bit;
	rINTPND = bit;
//	i = rINTPND;
}

对比可以发现,当有一个中断来临时,两段代码无处理无区别。但当有两个以上的中断同时来临时,SRCPND会有两个以上的位被置1,但只有一个中断提前响应,INTPND有1位置1。当提前进入中断服务函数中的那个中断,会做清除挂起位处理。在开发板厂家提供的代码中会将SRCPND的两个以上的中断位清除,那么接下来就不会响应低优先级中断。如果有两个中断,IIC中断来临后,先响应的是另一个中断,则IIC中断就不会响应。

解决方案:

采用芯片厂家提供的代码清除中断位。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值