《基于S3C2440的嵌入式Linux开发实例》课件第7章_第1页
《基于S3C2440的嵌入式Linux开发实例》课件第7章_第2页
《基于S3C2440的嵌入式Linux开发实例》课件第7章_第3页
《基于S3C2440的嵌入式Linux开发实例》课件第7章_第4页
《基于S3C2440的嵌入式Linux开发实例》课件第7章_第5页
已阅读5页,还剩96页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

7.1S3C2440SPI接口及CAN总线基础

7.2SPI寄存器7.3SPI接口CAN协议驱动函数分析7.1.1SPI接口基础

SPI(SerialPeripheralInterface,串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备通过串行方式进行通信交换信息,如外围设备FLASH、RAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。7.1S3C2440SPI接口及CAN总线基础

SPI接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从器件,其接口包括以下四种信号:

(1) MOSI:主器件数据输出,从器件数据输入。

(2) MISO:主器件数据输入,从器件数据输出。

(3) SCK:时钟信号,由主器件产生。

(4) /SS:从器件使能信号,由主器件控制。

S3C2440SPI接口特性如下:

支持2个通道SPI;与SPI接口协议V2.11兼容;8位用于发送的移位寄存器;8位用于接收的移位寄存器;8位预分频逻辑;查询、中断和DMA传送模式。

SPI接口结构图如图7-1所示。图7-1SPI接口结构图

1.编程步骤

编程步骤如下:

(1)如果ENSCK和SPCONn中的MSTR位都被置位,向SPDATn寄存器写入一个字节的数据,就启动一次发送,也可以使用典型的编程步骤来操作SPI卡。

(2)设置波特率预分频寄存器(SPPREn)。

(3)设置SPCONn配置SPI模块。

(4)向SPIDATn中写入10次0xFF来初始化MMC或SD卡。

(5)把一个GPIO(当作nSS)清零来激活MMC或SD卡。

(6)发送数据→核查发送准备好标志(REDY = 1),然后向SPDATn中写数据。

(7)接收数据(1),禁止SPCONn的TAGD位,正常模式→向SPDAT中写0Xff,确定REDY被置位后,从读缓冲区中读出数据。

(8)接收数据(2),使能SPCONn的TAGD位,自动发送虚拟数据模式→确定REDY被置位后,从读缓冲区中读出数据,然后自动开始数据传输。

(9)置位GPIO引脚(当作nSS的那个引脚),停止MMC或SD卡。

2.SPI从设备FormatB接收数据模式

如果SPI从设备接收模式激活,并且SPI格式被选为B,当SPI操作将会失败时,内部的READY信号在SPI_CNT减为0前变成高电平。因此,DMA模式的DATA_READ信号在最后一位被锁存之前置位。SPI从设备FormatB接收数据模式如图7-2所示。图7-2数据传输格式

3.三种SPI通信模式

SPI通信模式有以下三种:

(1) DMA模式:该模式不能用于从设备FormatB格式。

(2)查询模式:如果接收从设备采用FormatB格式,则DATA_READ信号应该比SPICLK延迟一个相位。

(3)中断模式:如果接收从设备采用FormatB格式,有FIR和IRQ两种模式,中断请求的过程采用的模式由中断源决定。7.1.2CAN总线基础

1. CAN总线基本概念

CAN(ControllerAreaNetwork)属于现场总线的范畴,是一种有效支持分布式控制或实时控制的串行通信网络,是ISO国际标准化的串行通信协议。

2. CAN总线技术基础

1)位仲裁

要对数据进行实时处理,就必须将数据快速传送,这就要求数据的物理传输通路有较高的速度。在几个站同时需要发送数据时,要求快速地进行总线分配。实时处理通过网络交换的紧急数据有较大的不同。

2) CAN与其他通信方案的比较

在实践中,有两种重要的总线分配方法:按时间表分配和按需要分配。

CAN实现总线分配的方法,可保证当不同的站申请总线存取时,明确地进行总线分配。这种位仲裁的方法可以解决当两个站同时发送数据时产生的碰撞问题。

3) CAN的报文格式

在总线中传送的报文,每帧由7部分组成。

4) CAN总线基本特点

CAN总线的基本特点如下:

●弃用传统的站地址编码,代之以对通信数据块进行编码,可以多主方式工作;

●采用非破坏性仲裁技术,当两个节点同时向网络上传送数据时,优先级低的节点主动停止数据发送,而优先级高的节点可不受影响继续传输数据,有效避免了总线冲突;●采用短帧结构,每一帧的有效字节数为8个,数据传输时间短,受干扰的概率低,重新发送的时间短;

●每帧数据都有CRC校验及其他检错措施,保证了数据传输的高可靠性,适于在高干扰环境下使用;

●节点在错误严重的情况下,具有自动关闭总线的功能,切断它与总线的联系,可使总线上其他操作不受影响;

●可以点对点,一对多及广播集中方式传送和接收数据。7.1.3SPI接口CAN协议实现硬件电路

MCP2510是美国微芯科技(MICROCHIP)生产的一款CAN总线协议控制器,完全支持CAN总线V2.0A/B技术规范。

基于MCP2510芯片的CAN总线协议控制硬件电路如图7-3所示。图7-3基于MCP2510芯片的CAN总线协议控制硬件电路7.2.1SPI寄存器基础(SPCONn)

1. SPI接口控制寄存器

SPI接口控制寄存器的各位定义如表7-1和表7-2所示。7.2SPI寄存器表7-1SPI接口控制寄存器表7-2SPI接口控制寄存器位定义2. SPI状态寄存器(SPSTAn)

SPI状态寄存器的各位定义如表7-3和表7-4所示。

3. SPI引脚控制寄存器(SPPINn)

SPI引脚控制寄存器的各位定义如表7-5和表7-6所示。表7-3SPI状态寄存器表7-4SPI状态寄存器位定义表7-5SPI引脚控制寄存器表7-6SPI引脚控制寄存器位定义4. SPI波特率预分频寄存器(SPIPREn)

SPI波特率预分频寄存器的各位定义如表7-7和表7-8所示。

5. SPI发送数据寄存器(SPTDATEn)

SPI发送数据寄存器的各位定义如表7-9和表7-10所示。表7-7SPI波特率预分频寄存器表7-8SPI波特率预分频寄存器位定义表7-9SPI发送数据寄存器表7-10SPI发送数据寄存器位定义6. SPI接收数据寄存器(SPRDATEn)

SPI接收数据寄存器的各位定义如表7-11和表7-12所示。表7-11SPI接收数据寄存器表7-12SPI接收数据寄存器位定义7.2.2SPI寄存器地址和相关功能

S3C2440SPI控制器相关寄存器地址及初始值定义如下:

#defineCHIP_SELECT_nSS0 0xFFFFFFFB

#defineCHIP_DESELECT_nSS0 0x00000004

#defineSPI_INTERNAL_CLOCK_ENABLE(1<<18)//EnableCPUclocktoSPIcontroller

//GPIO配置Masks

#defineCLEAR_GPG2_MASK 0xFFFFFFCF

#defineENABLE_GPG2_OUTPUT 0x00000010

#defineENABLE_GPG2_PULLUP 0x0000FFFB#defineENABLE_SPICLK0 0x08000000

#defineENABLE_SPIMSIO 0x02800000 //SPI输出和输入

#defineDISABLE_SPICLK_SPIMSIO_PULLUP 0x00003800

#defineTEST 0x00003800

#defineSPI_MODE_POLLING 0x00000000 //Datatransfermodes

#defineSPI_MODE_DMA 0x00000040

#defineSPI_MODE_INTERRUPT 0x00000020

#defineSPI_CLOCK_ENABLE 0x00000010 //EnableSPIclock(inmastermode)#defineSPI_SELECT_MASTER 0x00000008 //Selectmastermode

#defineSPI_CLOCK_POLARITY_HIGH0x00000000 //Determinesactiveclocktype(highorlow)

#defineSPI_CLOCK_POLARITY_LOW 0x00000004

#defineSPI_CLOCK_PHASE_FORMAT_A 0x00000000 //Determinestransferformat(AorB)

#defineSPI_CLOCK_PHASE_FORMAT_B 0x00000002

#defineSPI_TX_AUTO_GARBAGE

0x00000001 //Usedwhenonlyreceivingdata

#defineSPI_DATA_COLLISION 0x00000004//IndicatesI/Otimingerror(seedatasheet)#defineSPI_MULTI_MASTER_ERROR 0x00000002

//Indicatesbothsender/recieverconfiguredasMaster

#defineSPI_TRANSFER_READY 0x00000001//IndicatesSPIisreadytotransfer/receive

#defineSPI_MULTI_MASTER_ERROR_ENABLE 0x00000006

//Enablescheckingformulti-mastererror

#defineSPI_MASTER_OUT_KEEP0x00000003//DeterminesMOSIdriveorrelease(seedatasheet)

#defineCLK_RATE_FULL 0x00 //FullMasterclock

#defineCLK_RATE_HALF 0x01 //1/2Masterclock#defineCLK_RATE_FOUR 0x02 //1/4Masterclock

#defineCLK_RATE_EIGHT 0x03 //1/8Masterclock

#defineCLK_RATE_SIXTEEN 0x04 //1/16Masterclock

#defineCLK_RATE_THIRTY2 0x05 //1/32Masterclock

#defineCLK_RATE_SIXTY4 0x06 //1/64Masterclock

#defineCLK_RATE_SLOW 0x07 基于SPI接口的CAN总线协议控制驱动程序结构如图7-4所示。7.3SPI接口CAN协议驱动函数分析图7-4SPI接口CAN协议驱动架构7.3.1SPI接口CAN协议驱动数据结构与相关变量

1. MCP_device结构体

MCP_device描述了CAN驱动相关属性,代码描述如下:

structMCP_device

{

volatileunsignedlongRecvBuf;

volatileunsignedlongRecvHead;

volatileunsignedlongRecvTail;

volatileunsignedlongRecvNum;

wait_queue_head_tinq;//oruseasaglobalvariable

structsemaphoresem;//semaphoreusedformutex

unsignedintIrqNum;

unsignedintMinorNum;/*deviceminornumber*/

unsignedintBaudRate;

unsignedchar*SendBuf;

unsignedintSendNum;

volatileunsignedlongSendHead;

volatileunsignedlongSendTail;

};

2.驱动文件操作遍历Fops

Fops主要完成对CAN驱动的字符类型驱动的上层调用操作,代码描述如下:

structfile_operationsFops=

{

.open=device_open, //open

.release=device_release, //release

.read=device_read,

.write=device_write

};7.3.2驱动程序结构与主要函数

1.模块初始化函数mcpcan_init_module

mcpcan_init_module函数主要完成CAN驱动的注册,代码描述如下:

staticint_initmcpcan_init_module(void)

{

intres;

res=register_chrdev(MCP_major,“MCPCAN”,&Fops);

if(res<0){

printk(“deviceregisterfailedwith%d.\n”,res);

returnres;

}

if(MCP_major==0)MCP_major=res;

MCP_device_init();//mapspiregsforspi.c

spcon0=ioremap(0x59000000,4);

spsta0=ioremap(0x59000004,4);

sppin0=ioremap(0x59000008,4);

sppre0=ioremap(0x5900000c,4);

sptdat0=ioremap(0x59000010,4);

sprdat0=ioremap(0x59000014,4);

spcon1=ioremap(0x59000020,4);

spsta1=ioremap(0x59000024,4);

sppin1=ioremap(0x59000028,4);

sppre1=ioremap(0x5900002c,4);

sptdat1=ioremap(0x59000030,4);

sprdat1=ioremap(0x59000034,4);

return0;

}

2.驱动卸载函数mcpcan_cleanup_module

mcpcan_cleanup_module函数主要完成驱动的卸载,代码描述如下:

staticvoid_exitmcpcan_cleanup_module(void)

{

inti;

unregister_chrdev(MCP_major,“MCPCAN”);

for(i=0;i<2;i++){

kfree((void*)Device[i]->RecvBuf);

kfree(Device[i]->SendBuf);

kfree(Device[i]);

}

}

3.驱动设置初始化函数MCP_device_init

MCP_device_init函数主要用来对structMCP_device进行初始化,代码描述如下:

staticintMCP_device_init(void)

{

intres,i;

//printk(KERN_ERR“hello,enter%s\n”,__FUNCTION__);

for(i=0;i<MCP_NUM;i++)

{

Device[i]=kmalloc(sizeof(structMCP_device),GFP_KERNEL); //mallocthedevicestruct

if(Device[i]==NULL)

{

printk(KERN_ALERT“allocatedevicememoryfailed.\n”);

return(-ENOMEM);

}

memset((char*)Device[i],0,sizeof(structMCP_device));//Device[i]->RecvBuf=(unsignedchar*)get_free_page(GFP_KERNEL);//malloctherecvbuffer

Device[i]->RecvBuf=(unsignedlong)kmalloc(sizeof(structMCP_device)*100,GFP_KERNEL);

//malloctherecvbuffer

if(Device[i]->RecvBuf==0)

{

printk(KERN_ALERT“allocateRecvmemoryfailed.\n”);

return(-ENOMEM);

}

memset((char*)Device[i]->RecvBuf,0,sizeof(structMCP_device)*100);Device[i]->RecvHead=Device[i]->RecvBuf;

Device[i]->RecvTail=Device[i]->RecvBuf;

Device[i]->RecvNum=0;

//Device[i]->RecvQueue=NULL;

//Device[i]->SendBuf=(unsignedchar*)get_free_page(GFP_KERNEL);

//mallocthesendbuffer

Device[i]->SendBuf=kmalloc(sizeof(structMCP_device)*100,GFP_KERNEL);

//mallocthesendbufferif(Device[i]->SendBuf==NULL)

{

printk(KERN_ALERT“allocateSendmemoryfailed.\n”);

return(-ENOMEM);

}

memset((char*)Device[i]->SendBuf,0,sizeof(structMCP_device)*100);

Device[i]->MinorNum=i;

//Device[i]->FrameMode=1;

Device[i]->IrqNum=MCP_irq[i];

//Device[i]->BaudRate=MCP_baudrate[i];

init_waitqueue_head(&(Device[i]->inq));

//init_waitqueue_head(&(Device[i]->outq));

init_MUTEX(&(Device[i]->sem));

}

return0;

}

4.寄存器初始化函数MCP2510_Init

MCP2510_Init函数用来调用SPI接口的相关函数,完成2510的初始化,代码描述如下:

voidMCP2510_Init(intMinorNum)

{

SPI_Init();

/*复位控制器*/

CAN_SPI_CMD(SPI_CMD_RESET,ARG_UNUSED,ARG_UNUSED,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANCTRL)),

0xe0,0x80); //CONFIGMODE//直到进入配置模式

while((CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->

CANSTAT)),ARG_UNUSED,ARG_UNUSED)>>5)!=0x04);

//开始配置

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->BFPCTRL)),

BFPCTRL_INIT_VAL,ARG_UNUSED);CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXRTSCTRL)),

TXRTSCTRL_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,

TOLONG(&(MCP2510_MAP->CNF3)),

CNF3_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->CNF2)),

CNF2_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->CNF1)),

CNF1_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->CANINTE)),

CANINTE_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->CANINTF)),

CANINTF_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->EFLG)),

EFLG_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0CTRL)),

TXBnCTRL_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB1CTRL)),

TXBnCTRL_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB2CTRL)),

TXBnCTRL_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->RXB0CTRL)),

RXB1CTRL_INIT_VAL,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->RXB1CTRL)),

RXB1CTRL_INIT_VAL,ARG_UNUSED);//切换到一般模式和loopback模式

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANCTRL)),

0xe0,0x40);while!

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANCTRL)),

0xe0,0x00);

CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->CANSTAT)),

ARG_UNUSED,ARG_UNUSED);

5. 2510数据发送函数MCP2510_TX

MCP2510_TX函数主要完成2510的数据发送,代码描述如下:

oidMCP2510_TX(intTxBuf,intIdType,unsignedintid,intDataLen,char*data)

{

inti,offset;

switch(TxBuf)

{

caseTXBUF0:

offset=0;

break;caseTXBUF1:

offset=0x10;

break;

caseTXBUF2:

offset=0x20;

break;

}

/*设置帧定义*/

if(IdType==STANDID)

{

//printk(KERN_ERR"STANDID,line%dpassed!\n",__LINE__);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0SIDL))+offset,

(id&0x7)<<5,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0SIDH))+offset,

(id>>3)&0xff,ARG_UNUSED);}

elseif(IdType==EXTID)

{

//printk(KERN_ERR“EXTID,line%dpassed!\n”,_LINE_);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0EID0))+offset,

id&0xff,ARG_UNUSED);

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0EID8))+offset,

(id>>8)&0xff,ARG_UNUSED);CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0SIDL)),

((id>>16)&0x3)|0x08,ARG_UNUSED);

}

/*设置数据长度*/

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0DLC))

+offset,DataLen,ARG_UNUSED);

//fillthedata

if(DataLen>8)

DataLen=8;

for(i=0;i<DataLen;i++)

{

CAN_SPI_CMD(SPI_CMD_WRITE,TOLONG(&(MCP2510_MAP->TXB0D0))

+offset+i,data[i],ARG_UNUSED);

}

/*初始化传输*/

i=0;

while(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->TXB0CTRL))+offset,

ARG_UNUSED,ARG_UNUSED)&0x08)

{

i++;

if(i==1000)printk(“PleaseconnecttheCANPORTwithwire.”);

}

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->

TXB0CTRL))+offset,0x08,0x08);

}

6. CAN数据接收函数

MCP2510_RX函数主要完成CAN的数据接收,代码描述如下:

voidMCP2510_RX(intRxBuf,int*IdType,unsignedint*id,int*DataLen,char*data)

{

unsignedintflag;

intoffset,i;

//printk(KERN_ERR“hello,enter%s\n”,FUNCTION__);

switch(RxBuf)

{caseRXBUF0:

flag=0x1;

offset=0x00;

break;

caseRXBUF1:

flag=0x2;

offset=0x10;

break;

}/*等待数据帧的到来*/

while(!(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->CANINTF)),

ARG_UNUSED,ARG_UNUSED)&flag));

/*得到标志*/

if(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->RXB0SIDL))+offset,

ARG_UNUSED,ARG_UNUSED)&0x08)

{//Extendedidentifier

if(IdType)

*IdType=EXTID;

if(id)

{*id=(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->RXB0SIDL))+offset,

ARG_UNUSED,ARG_UNUSED)&0x3)<<16;

*id|=(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->RXB0EID8))+offset,

ARG_UNUSED,ARG_UNUSED))<<8;

*id|=(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->RXB0EID0))+offset,

ARG_UNUSED,ARG_UNUSED));

}

}

else

{

//Standardidentifier

if(IdType)

*IdType=STANDID;

if(id)

{*id=(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->

RXB0SIDH))+offset,ARG_UNUSED,ARG_UNUSED))<<3;

*id|=(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->

RXB0SIDL))+offset,ARG_UNUSED,ARG_UNUSED))>>5;

}

}

/*得到数据帧的长度*/

if(DataLen)*DataLen=(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->

RXB0DLC))+offset,ARG_UNUSED,ARG_UNUSED)&0xf);

/*得到数据*/

for(i=0;DataLen&&(i<*DataLen)&&data;i++)

{

data[i]=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->

RXB0D0))+offset+i,ARG_UNUSED,ARG_UNUSED);

}

//clearthereceiveintflag

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANINTF)),flag,0x00);

}7. CAN中断处理函数mcpcan0_handler

mcpcan0_handler()函数主要完成CAN总线的中断处理,代码描述如下:

staticirqreturn_tmcpcan0_handler(intirq,void*dev_id,structpt_regs*reg)

{

structMCP_device*dev=dev_id;

structmcpcan_datadatagram;

intwritten;

charregvalue,regvalue2;

//structmcpcan_data*datagramptr;//printk(KERN_ERR“hello,finallyenter%s!!!!!!!!!!!!!!!!!!!!!!!!\n”,__FUNCTION__);

//printk(KERN_ERR“\rexternirq8handled\n”);

regvalue=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->CANINTE)),

ARG_UNUSED,ARG_UNUSED);

//printk(“CANINTE=0x%02x\n”,regvalue);

regvalue=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->CANINTF)),

ARG_UNUSED,ARG_UNUSED);//printk("CANINTF=0x%02x\n",regvalue);

if(regvalue&0x01)

{

datagram.BufNo=RXBUF0;

MCP2510_RX(datagram.BufNo,&(datagram.IdType),&(datagram.id),

&(datagram.DataLen),datagram.data);

//printk("RXBUF0\n");//printk("datagram.BufNo=%d\n",datagram.BufNo);

//printk("datagram.IdType=%d\n",datagram.IdType);

//printk("datagram.id=%d\n",datagram.id);

//printk("datagram.DataLen=%d\n",datagram.DataLen);

//printk("datagram.data=%s\n",datagram.data);/*Writea16byterecord.AssumeBUF_SIZEisamultipleof16*/

memcpy((void*)dev->RecvHead,&datagram,sizeof(structmcpcan_data));

//datagramptr=(structmcpcan_data*)dev->RecvHead;

//printk("RecvHead->BufNo=%d\n",datagramptr->BufNo);

//printk("RecvHead->IdType=%d\n",datagramptr->IdType);

//printk("RecvHead->id=%d\n",datagramptr->id);

//printk("RecvHead->DataLen=%d\n",datagramptr->DataLen);

//printk("RecvHead->data=%s\n",datagramptr->data);

incr_buffer_pointer(&(dev->RecvHead),sizeof(structmcpcan_data),dev->MinorNum);

wake_up_interruptible(&(dev->inq));/*awakeanyreadingprocess*/

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANINTF)),0x01,0x00);

//infactalreadyclearinterruptbitinRX

}

if(regvalue&0x02)

{

datagram.BufNo=RXBUF1;//thisfunctionshouldberewrittentoreceivedatagramfromRXB1??????????????????

MCP2510_RX(datagram.BufNo,&(datagram.IdType),&(datagram.id),

&(datagram.DataLen),datagram.data);

//printk("RXBUF1\n");

/*Writea16byterecord.AssumeBUF_SIZEisamultipleof16*/

memcpy((void*)dev->RecvHead,&datagram,sizeof(structmcpcan_data));incr_buffer_pointer(&(dev->RecvHead),sizeof(structmcpcan_data),dev->MinorNum);

wake_up_interruptible(&dev->inq);/*awakeanyreadingprocess*/

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANINTF)),

0x02,0x00);//infactalreadyclearinterruptbitinRX

}

if(regvalue&0xe0)

{printk("CANerrorwithCANINTF=0x%02x.\n",regvalue);

if(regvalue&0x80)printk("MERRF:messageerror.\n");

if(regvalue&0x40)printk("WAKIF:wakeupinterrupt.\n");

if(regvalue&0x20)printk("ERRIF:CANbuserrorinterrupt.\n");

regvalue2=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->EFLG)),

ARG_UNUSED,ARG_UNUSED);printk(“EFLG=0x%02x.\n”,regvalue2);

regvalue2=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->TEC)),

ARG_UNUSED,ARG_UNUSED);

printk(“TEC=0x%02x.\n”,regvalue2);

regvalue2=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->REC)),

ARG_UNUSED,ARG_UNUSED);

printk(“REC=0x%02x.\n”,regvalue2);

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANINTF)),0xe0,0x00);

}if(CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->CANINTF)),

ARG_UNUSED,ARG_UNUSED)&0x1c)

{//didn'topenthe3sendinterrupts

CAN_SPI_CMD(SPI_CMD_BITMOD,TOLONG(&(MCP2510_MAP->CANINTF)),

0x1c,0x00); //clearTXbitsdirectly(itwillset1,butnoint)

}regvalue=CAN_SPI_CMD(SPI_CMD_READ,TOLONG(&(MCP2510_MAP->CANINTF)),

ARG_UNUSED,ARG_UNUSED);

//printk("afterinterruptprocessing,CANINTF=0x%02x\n",regvalue);

returnIRQ_HANDLED;//fla

}8. SPI接口处理函数CAN_SPI_CMD

CAN_SPI_CMD函数主要完成基于SPI接口MCP2510数据的发送和接收,代码描述如下:

unsignedcharCAN_SPI_CMD(unsignedcharcmd,unsignedlongaddr,unsignedchararg1,

unsignedchararg2)

{

unsignedcharret=0;

unsignedchardata=0; //Emptythespi'stransferandreceivebuffer

//SPI_TXFlush(CAN_SPI_MODULE);

//SPI_RXFlush(CAN_SPI_MODULE);

//StartSPIClock();

//printk("inCAN_SPI_CMD,line%dpassed!\n",__LINE__);

//*(unsignedint*)rGPGDAT=(*(unsignedint*)rGPGDAT)&CHIP_SELECT_nSS0;

writel(readl(rGPGDAT)&CHIP_SELECT_nSS0,rGPGDAT);//setcs:gpg2to0

//printk("inCAN_SPI_CMD,havesetcseffect!\n");switch(cmd)

{

caseSPI_CMD_READ:

//printk(“SPI_CMD_READ\n”

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论