s3c2440+mcp2510的canbus实现。记录备忘。
将2440引脚配置成spi端口。用spi接口配置mcp2510
-
#define rCLKCON 0x4C00000C
-
-
#define rGPECON 0x56000040
-
#define rGPEDAT 0x56000044
-
#define rGPEUP 0x56000048
-
-
#define rGPGCON 0x56000060
-
#define rGPGDAT 0x56000064
-
#define rGPGUP 0x56000068
-
-
#define rSPCON0 0x59000000
-
#define rSPSTA0 0x59000004
-
#define rSPPIN0 0x59000008
-
#define rSPPRE0 0x5900000C
-
#define rSPTDAT0 0x59000010
-
#define rSPRDAT0 0x59000014
-
-
#define SPI0_READY (ioread8((void *)SPSTA0) & 0x1)
-
-
#define MCP2510_CS_H iowrite32(ioread32((void *)GPGDAT) | (0x1<<14), (void *)GPGDAT)
-
#define MCP2510_CS_L iowrite32(ioread32((void *)GPGDAT) & (~(0x1<<14)), (void *)GPGDAT)
-
-
volatile unsigned int *GPGDAT;
-
volatile u8 *SPTDAT0;
-
volatile u8 *SPRDAT0;
-
volatile u8 *SPSTA0;
-
static unsigned char TXBnCTRL[3] = {0x30, 0x40, 0x50};
-
-
static u8 MCP2510_Read(u8 Addr)
-
{
-
u8 result;
-
MCP2510_CS_L;
-
iowrite8(0x03, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(Addr, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
result = ioread8((void *)SPRDAT0);
-
MCP2510_CS_H;
-
return result;
-
}
-
-
static void MCP2510_Write(u8 Addr, u8 Data)
-
{
-
MCP2510_CS_L;
-
while(!SPI0_READY);
-
iowrite8(0x02, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(Addr, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(Data, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
MCP2510_CS_H;
-
}
-
-
static void MCP2510_BitModi(u8 Addr, u8 Mask, u8 Data)
-
{
-
MCP2510_CS_L;
-
iowrite8(0x05, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(Addr, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(Mask, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(Data, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
MCP2510_CS_H;
-
}
-
-
static void __config_spi(void)
-
{
-
volatile unsigned int *REGISTER;
-
/* GPG(2, 13)*/
-
//设置GPG2为输出(底电平重启), GPG13(外部中断号21)为中断
-
REGISTER = (unsigned int *)ioremap(rGPGCON, 4);
-
PLOG("GPGCON Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32((ioread32((void *)REGISTER) & (~((0x03 << 26) | (0x03 << 4)))) | (0b10 << 26) | (0b01 << 4), (void *)REGISTER);
-
PLOG("GPGCON Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//使能GPG2、13上拉
-
REGISTER = (unsigned int *)ioremap(rGPGUP, 4);
-
PLOG("GPGUP Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32(ioread32((void *)REGISTER) & (~((0x1 << 13) | (0x1 << 2))), (void *)REGISTER);
-
PLOG("GPGUP Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
/* reset mcp2510. Is it necessary ? */
-
//设置GPG2为高电平,GPG2和MCP2510的RST连接
-
REGISTER = (unsigned int *)ioremap(rGPGDAT, 4);
-
PLOG("GPGDAT Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32(ioread32((void *)REGISTER) | (0x1 << 2), (void *)REGISTER);
-
PLOG("GPGDAT Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//设置GPG14为输出,SPI_CS信号
-
REGISTER = (unsigned int *)ioremap(rGPGCON, 4);
-
PLOG("GPBCON Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32((ioread32((void *)REGISTER) & (~(0b11 << 28))) | (0b01 << 28), (void *)REGISTER);
-
PLOG("GPBCON Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//使能GPG14上拉
-
REGISTER = (unsigned int *)ioremap(rGPGUP, 4);
-
PLOG("GPBUP Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32(ioread32((void *)REGISTER) & (~(0x1 << 14)), (void *)REGISTER);
-
PLOG("GPBUP Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
GPGDAT = (unsigned int *)ioremap(rGPGDAT, 4);
-
SPTDAT0 = (u8 *)ioremap(rSPTDAT0, 1);
-
SPRDAT0 = (u8 *)ioremap(rSPRDAT0, 1);
-
SPSTA0 = (u8 *)ioremap(rSPSTA0, 1);
-
-
//上拉GPG14
-
PLOG("GPGDAT Value is %u\n", ioread32((void *)GPGDAT));
-
MCP2510_CS_H;
-
PLOG("GPGDAT Value is %u\n", ioread32((void *)GPGDAT));
-
-
//打开SPI CLK使能
-
REGISTER = (unsigned int *)ioremap(rCLKCON, 4);
-
PLOG("CLKCON Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32((ioread32((void *)REGISTER) | (1 << 18)), (void *)REGISTER);
-
PLOG("CLKCON Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//设置GPE11、12、13为SPI功能
-
REGISTER = (unsigned int *)ioremap(rGPECON, 4);
-
PLOG("GPECON Value is %u\n", ioread32((void *)REGISTER));
-
iowrite32((ioread32((void *)REGISTER) & (0xF03FFFFF)) | (0b10 << 26) | (0b10 << 24) | (0b10 << 22), (void *)REGISTER);
-
PLOG("GPECON Value is %u\n", ioread32((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//设置SPI0波特率
-
REGISTER = (unsigned int *)ioremap(rSPPRE0, 4);
-
PLOG("SPPRE0 Value is %u\n", ioread8((void *)REGISTER));
-
iowrite8(0x9, (void *)REGISTER);
-
PLOG("SPPRE0 Value is %u\n", ioread8((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//设置SPCON0
-
REGISTER = (unsigned int *)ioremap(rSPCON0, 4);
-
PLOG("SPCON0 Value is %u\n", ioread8((void *)REGISTER));
-
iowrite8((0 << 6)|(0 << 5)|(1 << 4)|(1 << 3)|(0 << 2)|(0 << 1)|(0 << 0), (void *)REGISTER);
-
PLOG("SPCON0 Value is %u\n", ioread8((void *)REGISTER));
-
iounmap(REGISTER);
-
-
//设置SPPIN0
-
REGISTER = (unsigned int *)ioremap(rSPPIN0, 4);
-
PLOG("SPPIN0 Value is %u\n", ioread8((void *)REGISTER));
-
iowrite8(0, (void *)REGISTER);
-
PLOG("SPPIN0 Value is %u\n", ioread8((void *)REGISTER));
-
iounmap(REGISTER);
-
}
通过spi接口初始化mcp2510
-
static int __config_mcp2510(void)
-
{
-
int result;
-
u8 tmp;
-
-
//注册接收中断服务程序
-
if(request_irq(IRQ_EINT21, proc_Interrupt, IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_LOW, "MCP2510", &host))
-
{
-
result = -EFAULT;
-
goto err;
-
}
-
-
MCP2510_BitModi(0x0F, 0xE0, 0x80); //设置MCP2510为配置模式
-
-
MCP2510_Write(0x2B, 0x03); //设置(RX1IE, EX0IE)中断使能寄存器, 使能接收缓冲中断
-
/** RXFn**/
-
for(result = 0x0; result <= 0x0B; result++)
-
{
-
MCP2510_Write(result, 0x00);
-
}
-
/** RXFn**/
-
for(result = 0x10; result <= 0x1B; result++)
-
{
-
MCP2510_Write(result, 0x00);
-
}
-
/** RXFn**/
-
MCP2510_Write(0x01, 0x08);
-
MCP2510_Write(0x05, 0x08);
-
MCP2510_Write(0x09, 0x08);
-
MCP2510_Write(0x11, 0x08);
-
MCP2510_Write(0x15, 0x08);
-
MCP2510_Write(0x19, 0x08);
-
/*** 设置RXMn ***/
-
for(result = 0x20; result <= 0x27; result++)
-
{
-
if((result == 0x21) || (result == 0x25))
-
{
-
MCP2510_Write(result, 0xE0); /** SID(2..0), EID(17,16) **/
-
}
-
else if((result == 0x20) || (result == 0x24))
-
{
-
MCP2510_Write(result, 0x0f);
-
}
-
else
-
{
-
MCP2510_Write(result, 0x0);
-
}
-
}
-
-
-
MCP2510_CS_L; //设置接收屏蔽寄存器RXMn都为0
-
iowrite8(0x02, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(0x20, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
for(tmp=0; tmp < 8; tmp++)
-
{
-
iowrite8(0x0, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
}
-
MCP2510_CS_H;
-
-
//设置接收控制寄存器
-
MCP2510_BitModi(TXBnCTRL[0], 0x0B, 0x03); //设置TXB0CTRL -发送缓冲器0有最高优先级
-
MCP2510_BitModi(TXBnCTRL[1], 0x0B, 0x02); //设置TXB1CTRL -发送缓冲器1有次高优先级
-
MCP2510_BitModi(TXBnCTRL[2], 0x0B, 0x01); //设置TXB2CTRL -发送缓冲器2有低优先级
-
-
MCP2510_BitModi(0x60, 0x64, 0x04); //设置RXB0CTRL -接收缓冲器0控制寄存器-
-
//接收符合滤波器条件的所有带扩展标识符或标准标识符的有效报文
-
//如果RXB0 满, RXB0 接收到的报文将被滚存至RXB1
-
MCP2510_BitModi(0x70, 0x60, 0x00); //设置RXB1CTRL -接收缓冲器 1 控制寄存器-
-
//接收符合滤波器条件的所有带扩展标识符或标准标识符的有效报文
-
-
//MCP2510_Write(0x2A, 0x02); //设置CNF1
-
MCP2510_Write(0x2A, 0x03); //设置CNF1
-
MCP2510_Write(0x29, 0x9E); //设置CNF2
-
MCP2510_Write(0x28, 0x03); //设置CNF3,设置波特率为125Kbps/s(1, 7, 4, 4)
-
-
MCP2510_Write(0x2C, 0x0); //清空中断标志
-
MCP2510_BitModi(0x0F, 0xE0, 0x00); //设置MCP2510为正常模式
-
result = 0;
-
err:
-
-
return result;
-
}
下面是向canbus总线写入数据
-
/***********************************************************************
-
*
-
* input: SendMsg
-
* output:
-
* return:
-
*
-
* descript:
-
* send canbus frame via spi interface
-
*
-
***********************************************************************/
-
int __mcp2510Pkt_write(struct CANBus_Message* SendMsg)
-
{
-
int i = 0;
-
unsigned char reg;
-
-
if(host.iEnable == 0) /** disable host. don't send data **/
-
{
-
printk("[%s-%d]Info: host disable !!!\n", __func__, __LINE__);
-
return SendMsg->Length;
-
}
-
-
#if 0
-
//读三个发送缓冲器寄存器,以确定哪个发送缓冲器可用。
-
for(i = 0; i < 3; i++)
-
{
-
if(!(MCP2510_Read(TXBnCTRL[i]) & 0x08))
-
break;
-
}
-
//三个缓冲器都不可用,返回错误
-
if(i == 3)
-
{
-
//printk("[%s-%d]Warning: All 3 TX-buffer are busy \n", __func__, __LINE__);
-
return -EBUSY;
-
}
-
#else
-
/*** 只使用一个缓冲器,牺牲性能,保证顺序. 测试比较得出:牺牲的性能微不足道 ***/
-
i = 0;
-
if((MCP2510_Read(TXBnCTRL[i]) & 0x08))
-
{
-
return -EBUSY;
-
}
-
#endif
-
-
PLOG("[%s-%d]: Message Length: 0x%x,\tSID: 0x%x, EID: 0x%x, RTR: 0x%x\n sndMessage: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
-
__func__, __LINE__,
-
SendMsg->Length,
-
SendMsg->SID,
-
SendMsg->EID,
-
SendMsg->RTR,
-
SendMsg->Messages[0],
-
SendMsg->Messages[1],
-
SendMsg->Messages[2],
-
SendMsg->Messages[3],
-
SendMsg->Messages[4],
-
SendMsg->Messages[5],
-
SendMsg->Messages[6],
-
SendMsg->Messages[7]);
-
/** Start send process **/
-
MCP2510_CS_L;
-
iowrite8(0x02, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(TXBnCTRL[i] + 1, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
reg = SendMsg->SID >> 3;
-
iowrite8(reg, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
reg = (unsigned char)(SendMsg->SID << 5);
-
reg =reg |(SendMsg->EID >> 16);
-
//if(SendMsg->EID)
-
if(1)
-
{
-
reg |= (1 << 3);
-
}
-
iowrite8(reg, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
reg = (unsigned char)(SendMsg->EID >> 8);
-
iowrite8(reg, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
reg = (unsigned char)SendMsg->EID;
-
iowrite8(reg, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
if(SendMsg->Length > 8)
-
{
-
printk("[%s-%d]: the length of data is %d grate than 8 !!! \n", __func__, __LINE__, SendMsg->Length);
-
//SendMsg->Length = 8;
-
}
-
iowrite8(SendMsg->Length | (SendMsg->RTR << 6), (void *)SPTDAT0);
-
-
for(reg = 0; reg < SendMsg->Length; reg++)
-
{
-
while(!SPI0_READY);
-
iowrite8(SendMsg->Messages[reg], (void *)SPTDAT0);
-
}
-
while(!SPI0_READY);
-
//printk("[%s-%d]: %d bytes date had been sent ! \n", __func__, __LINE__, SendMsg->Length);
-
MCP2510_CS_H;
-
-
MCP2510_BitModi(TXBnCTRL[i], 0x08, 0x08);
-
-
return SendMsg->Length;
-
-
}
下面是中断上下文从canbus总线读取数据
-
/*************************************************************************************
-
*
-
* Function __mcp2510Pkt_read
-
*
-
* input: intrNum
-
* output: pRcvMsg
-
* return:
-
*
-
* descriptor:
-
*
-
*************************************************************************************/
-
static int __mcp2510Pkt_read(struct CANBus_Message* pRcvMsg, unsigned char intrNum)
-
{
-
unsigned char revAddr;
-
unsigned char uMes;
-
//int ret;
-
-
revAddr = (intrNum << 3) + 1; //得到触发中断的接收缓冲器寄存器的地址
-
-
/** read SID/EID/RTR/Length **/
-
MCP2510_CS_L;
-
while(!SPI0_READY);
-
iowrite8(0x03, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(revAddr, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
pRcvMsg->SID = ioread8((void *)SPRDAT0) << 3;
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
uMes = ioread8((void *)SPRDAT0);
-
pRcvMsg->SID |= (uMes >> 5);
-
pRcvMsg->EID = ((uMes << 16) & 0x3ffff);
-
if(!(uMes & 0x08))
-
{
-
pRcvMsg->RTR = (uMes >> 4) & 0x1;
-
}
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
pRcvMsg->EID |= (ioread8((void *)SPRDAT0) << 8);
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
pRcvMsg->EID |= ioread8((void *)SPRDAT0);
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
revAddr = ioread8((void *)SPRDAT0);
-
if(uMes & 0x08)
-
{
-
pRcvMsg->RTR = (revAddr >> 6) & 0x1;
-
}
-
pRcvMsg->Length = revAddr & 0x0F;
-
if (pRcvMsg->Length > 8)
-
{
-
PLOG("[%s-%d]: Message Length is:%u \n", __func__, __LINE__, pRcvMsg->Length);
-
pRcvMsg->Length = 8;
-
}
-
/** read data **/
-
for(uMes = 0; uMes < pRcvMsg->Length; uMes++)
-
{
-
iowrite8(0xFF, (void *)SPTDAT0);
-
while(!SPI0_READY);
-
pRcvMsg->Messages[uMes] = ioread8((void *)SPRDAT0);
-
}
-
while(!SPI0_READY);
-
MCP2510_CS_H;
-
/** Clear interrupt flag **/
-
uMes = (intrNum >> 1) - 5;
-
MCP2510_BitModi(0x2C, uMes, 0);
-
-
return 1;
-
}
阅读(1321) | 评论(0) | 转发(0) |