在线时间0 小时
UID116571
注册时间2009-3-17
NXP金币0
该用户从未签到
新手上路

- 积分
- 7703
- 最后登录
- 1970-1-1
|
最近在做mqx3.6.0的以太网驱动移植
板子上采用mcf51ac128,用spi接口扩展了一片enc28j60 10Mbps的芯片
enc28j60的中断输出引脚接到mcf51ac128的IRQ引脚
在最开始的时候是想用IRQ中断来做,于是写了个isr,用_int_install_isr安装。代码如下:
boolean enc28j60_install_isr(ENET_CONTEXT_STRUCT_PTR enet_ptr)
{
typedef void(*ISR_PTR)(void*);
ENC28J60_MAC_CONTEXT_STRUCT *mac_context_ptr=(ENC28J60_MAC_CONTEXT_STRUCT *)(enet_ptr->MAC_CONTEXT_PTR);
//VMCF51AC_IRQ_STRUCT_PTR irq_ptr=_bsp_get_irq_base_address();
VMCF51AC_STRUCT_PTR reg_ptr = (VMCF51AC_STRUCT_PTR)BSP_IPSBAR;
//uint_8 irqsc=irq_ptr->IRQSC;
uint_32 vector;
vector=_bsp_get_irq_vector();
#if BSPCFG_ENET_RESTORE
mac_context_ptr->OLDISR_PTR=(void *)_int_get_isr(vector);
mac_context_ptr->OLDISR_DATA=_int_get_isr_data(vector);
#endif
if (_int_install_isr(vector, (ISR_PTR)nscf51acr1_irq_isr, (pointer)enet_ptr)==NULL) {
printf("install enc28j60 isr failed\n");
return FALSE;
}
reg_ptr->SIM.SCGC2 |= MCF51XX_SCGC2_IRQ_MASK;
reg_ptr->IRQ.IRQSC=0x56 ;
_int_enable();
return TRUE;
}
结果发现中断服务程序没有被调用过,似乎根本就没触发中断,用示波器看IRQ引脚确实发生跳变,从高电平跳到低电平
后来看mqx手册,发现上面有一段说NMI(不可屏蔽中断)是不能用_int_install_isr来安装中断服务程序的,而应该用_init_install_kernel_isr,但这个中断服务程序中不能调用任何MQX函数,觉得这太麻烦,因为我的中断服务程序总是要调用spi接口的IO函数来操作enc28j60的。
于是,换了个办法:不用IRQ中断,而是在enc28j60初始化的时候,创建一个timer,在定时器的handler周期查询enc28j60各标志位。我尝试了定时周期2ms,5ms,7ms,10ms多种情况,出现这么个问题,网络连接正常,ping没有任何问题(连续ping几千次都正常)。但是运行那个http server例子,却发现不行,抓包分析后发现,似乎mcf51ac128在收到数据包后,要花很长时间处理才能返回应答,结果导致PC客户端超时,抓包可以看到,常常PC端发送了多个请求过去,板子才返回一个请求,导致pc又重发过去的帧。整体感觉是板子好像是来不及处理数据包。
http服务器这个例子,多跑几次,偶尔也可以打开那个网页。但很不稳定,有时候系统会跑飞,似乎是堆栈溢出,而且我发现定时器周期越短,跑飞的概率越大。但定时器周期越长,pc端timeout的概率也就越大。
最后,我想重新使用中断来做,于是把板子跳线,吧enc28j60的中断输出连到mcf51ac128的KBIP7上。修改代码测试,发现与IRQ同样的问题,我的KBI中断服务程序没有被调用,似乎没有正确触发KBI中断。
下面是我的代码:
boolean enc28j60_install_isr(ENET_CONTEXT_STRUCT_PTR enet_ptr)
{
typedef void(*ISR_PTR)(void*);
MQX_FILE_PTR gpiocs;
uint_32 pin[] =
{
BSP_ENC28J60_IRQ_PIN| GPIO_PIN_IRQ_FALLING,
GPIO_LIST_END
};
ENC28J60_MAC_CONTEXT_STRUCT *mac_context_ptr=(ENC28J60_MAC_CONTEXT_STRUCT *)(enet_ptr->MAC_CONTEXT_PTR);
MCF51AC_STRUCT_PTR reg_ptr = _PSP_GET_MBAR();
_int_disable();
gpiocs = fopen ("gpio:read", (char_ptr) &pin);
if (NULL == gpiocs)
{
printf ("Opening GPIO failed.\n");
_time_delay (200L);
return FALSE ;
}
mac_context_ptr->irq_pin=(void*)gpiocs;
if(ioctl(gpiocs,GPIO_IOCTL_SET_IRQ_FUNCTION,enc28j60_isr)==IO_OK){
printf("install isr success\n");
}
else{
printf("install isr failed\n");
return FALSE;
}
reg_ptr->KBI.KBIxPE |=0x80;
reg_ptr->KBI.KBIxSC=0;
reg_ptr->KBI.KBIxSC |= MCF51XX_KBIXSC_KBIE;
_int_enable();
return TRUE;
}
在user_config.h中使能了BSPCFG_ENABLE_GPIODEV
我现在怀疑,最开始IRQ那个不正常和KBI不正常是同一个原因,就是某个地方没有设置对,中断根本没有触发。
同样,我用示波器量过enc28j60的INT引脚,确实在收到数据包后,从高电平跳到低电平
|
|