Chinaunix首页 | 论坛 | 博客
  • 博客访问: 693340
  • 博文数量: 192
  • 博客积分: 1875
  • 博客等级: 上尉
  • 技术积分: 2177
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 23:21
个人简介

有时候,就是想窥视一下不知道的东东,因为好奇!

文章分类

全部博文(192)

文章存档

2024年(8)

2023年(3)

2020年(1)

2019年(1)

2018年(1)

2017年(2)

2016年(69)

2015年(53)

2014年(14)

2013年(1)

2012年(5)

2011年(25)

2010年(9)

分类: LINUX

2014-09-25 19:44:27

s3c2440+mcp2510的canbus实现。记录备忘。
将2440引脚配置成spi端口。用spi接口配置mcp2510

点击(此处)折叠或打开

  1. #define rCLKCON 0x4C00000C

  2. #define rGPECON 0x56000040
  3. #define rGPEDAT 0x56000044
  4. #define rGPEUP 0x56000048

  5. #define rGPGCON 0x56000060
  6. #define rGPGDAT 0x56000064
  7. #define rGPGUP 0x56000068

  8. #define rSPCON0 0x59000000
  9. #define rSPSTA0 0x59000004
  10. #define rSPPIN0 0x59000008
  11. #define rSPPRE0 0x5900000C
  12. #define rSPTDAT0 0x59000010
  13. #define rSPRDAT0 0x59000014

  14. #define SPI0_READY (ioread8((void *)SPSTA0) & 0x1)

  15. #define MCP2510_CS_H iowrite32(ioread32((void *)GPGDAT) | (0x1<<14), (void *)GPGDAT)
  16. #define MCP2510_CS_L iowrite32(ioread32((void *)GPGDAT) & (~(0x1<<14)), (void *)GPGDAT)

  17. volatile unsigned int *GPGDAT;
  18. volatile u8 *SPTDAT0;
  19. volatile u8 *SPRDAT0;
  20. volatile u8 *SPSTA0;
  21. static unsigned char TXBnCTRL[3] = {0x30, 0x40, 0x50};

  22. static u8 MCP2510_Read(u8 Addr)
  23. {
  24.     u8 result;
  25.     MCP2510_CS_L;
  26.     iowrite8(0x03, (void *)SPTDAT0);
  27.     while(!SPI0_READY);
  28.     iowrite8(Addr, (void *)SPTDAT0);
  29.     while(!SPI0_READY);
  30.     iowrite8(0xFF, (void *)SPTDAT0);
  31.     while(!SPI0_READY);
  32.     result = ioread8((void *)SPRDAT0);
  33.     MCP2510_CS_H;
  34.     return result;
  35. }

  36. static void MCP2510_Write(u8 Addr, u8 Data)
  37. {
  38.     MCP2510_CS_L;
  39.     while(!SPI0_READY);
  40.     iowrite8(0x02, (void *)SPTDAT0);
  41.     while(!SPI0_READY);
  42.     iowrite8(Addr, (void *)SPTDAT0);
  43.     while(!SPI0_READY);
  44.     iowrite8(Data, (void *)SPTDAT0);
  45.     while(!SPI0_READY);
  46.     MCP2510_CS_H;
  47. }

  48. static void MCP2510_BitModi(u8 Addr, u8 Mask, u8 Data)
  49. {
  50.     MCP2510_CS_L;
  51.     iowrite8(0x05, (void *)SPTDAT0);
  52.     while(!SPI0_READY);
  53.     iowrite8(Addr, (void *)SPTDAT0);
  54.     while(!SPI0_READY);
  55.     iowrite8(Mask, (void *)SPTDAT0);
  56.     while(!SPI0_READY);
  57.     iowrite8(Data, (void *)SPTDAT0);
  58.     while(!SPI0_READY);
  59.     MCP2510_CS_H;
  60. }

  61. static void __config_spi(void)
  62. {
  63.     volatile unsigned int *REGISTER;
  64. /* GPG(2, 13)*/
  65.     //设置GPG2为输出(底电平重启), GPG13(外部中断号21)为中断
  66.     REGISTER = (unsigned int *)ioremap(rGPGCON, 4);
  67.     PLOG("GPGCON Value is %u\n", ioread32((void *)REGISTER));
  68.     iowrite32((ioread32((void *)REGISTER) & (~((0x03 << 26) | (0x03 << 4)))) | (0b10 << 26) | (0b01 << 4), (void *)REGISTER);
  69.     PLOG("GPGCON Value is %u\n", ioread32((void *)REGISTER));
  70.     iounmap(REGISTER);

  71.     //使能GPG2、13上拉
  72.     REGISTER = (unsigned int *)ioremap(rGPGUP, 4);
  73.     PLOG("GPGUP Value is %u\n", ioread32((void *)REGISTER));
  74.     iowrite32(ioread32((void *)REGISTER) & (~((0x1 << 13) | (0x1 << 2))), (void *)REGISTER);
  75.     PLOG("GPGUP Value is %u\n", ioread32((void *)REGISTER));
  76.     iounmap(REGISTER);

  77. /* reset mcp2510. Is it necessary ? */
  78.     //设置GPG2为高电平,GPG2和MCP2510的RST连接
  79.     REGISTER = (unsigned int *)ioremap(rGPGDAT, 4);
  80.     PLOG("GPGDAT Value is %u\n", ioread32((void *)REGISTER));
  81.     iowrite32(ioread32((void *)REGISTER) | (0x1 << 2), (void *)REGISTER);
  82.     PLOG("GPGDAT Value is %u\n", ioread32((void *)REGISTER));
  83.     iounmap(REGISTER);

  84.     //设置GPG14为输出,SPI_CS信号
  85.     REGISTER = (unsigned int *)ioremap(rGPGCON, 4);
  86.     PLOG("GPBCON Value is %u\n", ioread32((void *)REGISTER));
  87.     iowrite32((ioread32((void *)REGISTER) & (~(0b11 << 28))) | (0b01 << 28), (void *)REGISTER);
  88.     PLOG("GPBCON Value is %u\n", ioread32((void *)REGISTER));
  89.     iounmap(REGISTER);

  90.     //使能GPG14上拉
  91.     REGISTER = (unsigned int *)ioremap(rGPGUP, 4);
  92.     PLOG("GPBUP Value is %u\n", ioread32((void *)REGISTER));
  93.     iowrite32(ioread32((void *)REGISTER) & (~(0x1 << 14)), (void *)REGISTER);
  94.     PLOG("GPBUP Value is %u\n", ioread32((void *)REGISTER));
  95.     iounmap(REGISTER);

  96.     GPGDAT = (unsigned int *)ioremap(rGPGDAT, 4);
  97.     SPTDAT0 = (u8 *)ioremap(rSPTDAT0, 1);
  98.     SPRDAT0 = (u8 *)ioremap(rSPRDAT0, 1);
  99.     SPSTA0 = (u8 *)ioremap(rSPSTA0, 1);

  100.     //上拉GPG14
  101.     PLOG("GPGDAT Value is %u\n", ioread32((void *)GPGDAT));
  102.     MCP2510_CS_H;
  103.     PLOG("GPGDAT Value is %u\n", ioread32((void *)GPGDAT));

  104.     //打开SPI CLK使能
  105.     REGISTER = (unsigned int *)ioremap(rCLKCON, 4);
  106.     PLOG("CLKCON Value is %u\n", ioread32((void *)REGISTER));
  107.     iowrite32((ioread32((void *)REGISTER) | (1 << 18)), (void *)REGISTER);
  108.     PLOG("CLKCON Value is %u\n", ioread32((void *)REGISTER));
  109.     iounmap(REGISTER);

  110.     //设置GPE11、12、13为SPI功能
  111.     REGISTER = (unsigned int *)ioremap(rGPECON, 4);
  112.     PLOG("GPECON Value is %u\n", ioread32((void *)REGISTER));
  113.     iowrite32((ioread32((void *)REGISTER) & (0xF03FFFFF)) | (0b10 << 26) | (0b10 << 24) | (0b10 << 22), (void *)REGISTER);
  114.     PLOG("GPECON Value is %u\n", ioread32((void *)REGISTER));
  115.     iounmap(REGISTER);

  116.     //设置SPI0波特率
  117.     REGISTER = (unsigned int *)ioremap(rSPPRE0, 4);
  118.     PLOG("SPPRE0 Value is %u\n", ioread8((void *)REGISTER));
  119.     iowrite8(0x9, (void *)REGISTER);
  120.     PLOG("SPPRE0 Value is %u\n", ioread8((void *)REGISTER));
  121.     iounmap(REGISTER);

  122.     //设置SPCON0
  123.     REGISTER = (unsigned int *)ioremap(rSPCON0, 4);
  124.     PLOG("SPCON0 Value is %u\n", ioread8((void *)REGISTER));
  125.     iowrite8((0 << 6)|(0 << 5)|(1 << 4)|(1 << 3)|(0 << 2)|(0 << 1)|(0 << 0), (void *)REGISTER);
  126.     PLOG("SPCON0 Value is %u\n", ioread8((void *)REGISTER));
  127.     iounmap(REGISTER);

  128.     //设置SPPIN0
  129.     REGISTER = (unsigned int *)ioremap(rSPPIN0, 4);
  130.     PLOG("SPPIN0 Value is %u\n", ioread8((void *)REGISTER));
  131.     iowrite8(0, (void *)REGISTER);
  132.     PLOG("SPPIN0 Value is %u\n", ioread8((void *)REGISTER));
  133.     iounmap(REGISTER);
  134. }

通过spi接口初始化mcp2510

点击(此处)折叠或打开

  1. static int __config_mcp2510(void)
  2. {
  3.     int result;
  4.     u8 tmp;

  5.     //注册接收中断服务程序
  6.     if(request_irq(IRQ_EINT21, proc_Interrupt, IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_LOW, "MCP2510", &host))
  7.     {
  8.         result = -EFAULT;
  9.         goto err;
  10.     }

  11.     MCP2510_BitModi(0x0F, 0xE0, 0x80); //设置MCP2510为配置模式

  12.     MCP2510_Write(0x2B, 0x03); //设置(RX1IE, EX0IE)中断使能寄存器, 使能接收缓冲中断
  13.     /** RXFn**/
  14.     for(result = 0x0; result <= 0x0B; result++)
  15.     {
  16.         MCP2510_Write(result, 0x00);
  17.     }
  18.     /** RXFn**/
  19.     for(result = 0x10; result <= 0x1B; result++)
  20.     {
  21.         MCP2510_Write(result, 0x00);
  22.     }
  23.     /** RXFn**/
  24.     MCP2510_Write(0x01, 0x08);
  25.     MCP2510_Write(0x05, 0x08);
  26.     MCP2510_Write(0x09, 0x08);
  27.     MCP2510_Write(0x11, 0x08);
  28.     MCP2510_Write(0x15, 0x08);
  29.     MCP2510_Write(0x19, 0x08);
  30.     /*** 设置RXMn ***/
  31.     for(result = 0x20; result <= 0x27; result++)
  32.     {
  33.         if((result == 0x21) || (result == 0x25))
  34.         {
  35.             MCP2510_Write(result, 0xE0); /** SID(2..0), EID(17,16) **/
  36.         }
  37.         else if((result == 0x20) || (result == 0x24))
  38.         {
  39.             MCP2510_Write(result, 0x0f);
  40.         }
  41.         else
  42.         {
  43.             MCP2510_Write(result, 0x0);
  44.         }
  45.     }


  46.     MCP2510_CS_L; //设置接收屏蔽寄存器RXMn都为0
  47.     iowrite8(0x02, (void *)SPTDAT0);
  48.     while(!SPI0_READY);
  49.     iowrite8(0x20, (void *)SPTDAT0);
  50.     while(!SPI0_READY);
  51.     for(tmp=0; tmp < 8; tmp++)
  52.     {
  53.         iowrite8(0x0, (void *)SPTDAT0);
  54.         while(!SPI0_READY);
  55.     }
  56.     MCP2510_CS_H;

  57.     //设置接收控制寄存器
  58.     MCP2510_BitModi(TXBnCTRL[0], 0x0B, 0x03); //设置TXB0CTRL -发送缓冲器0有最高优先级
  59.     MCP2510_BitModi(TXBnCTRL[1], 0x0B, 0x02); //设置TXB1CTRL -发送缓冲器1有次高优先级
  60.     MCP2510_BitModi(TXBnCTRL[2], 0x0B, 0x01); //设置TXB2CTRL -发送缓冲器2有低优先级

  61.     MCP2510_BitModi(0x60, 0x64, 0x04); //设置RXB0CTRL -接收缓冲器0控制寄存器-
  62.     //接收符合滤波器条件的所有带扩展标识符或标准标识符的有效报文
  63.     //如果RXB0 满, RXB0 接收到的报文将被滚存至RXB1
  64.     MCP2510_BitModi(0x70, 0x60, 0x00); //设置RXB1CTRL -接收缓冲器 1 控制寄存器-
  65.     //接收符合滤波器条件的所有带扩展标识符或标准标识符的有效报文

  66.     //MCP2510_Write(0x2A, 0x02); //设置CNF1
  67.     MCP2510_Write(0x2A, 0x03); //设置CNF1
  68.     MCP2510_Write(0x29, 0x9E); //设置CNF2
  69.     MCP2510_Write(0x28, 0x03); //设置CNF3,设置波特率为125Kbps/s(1, 7, 4, 4)

  70.     MCP2510_Write(0x2C, 0x0); //清空中断标志
  71.     MCP2510_BitModi(0x0F, 0xE0, 0x00); //设置MCP2510为正常模式
  72.     result = 0;
  73. err:

  74.     return result;
  75. }

下面是向canbus总线写入数据

点击(此处)折叠或打开

  1. /***********************************************************************
  2.  *
  3.  * input: SendMsg
  4.  * output:
  5.  * return:
  6.  *
  7.  * descript:
  8.  * send canbus frame via spi interface
  9.  *
  10.  ***********************************************************************/
  11. int __mcp2510Pkt_write(struct CANBus_Message* SendMsg)
  12. {
  13.     int i = 0;
  14.     unsigned char reg;

  15.     if(host.iEnable == 0) /** disable host. don't send data **/
  16.     {
  17.         printk("[%s-%d]Info: host disable !!!\n", __func__, __LINE__);
  18.         return SendMsg->Length;
  19.     }

  20. #if 0
  21.     //读三个发送缓冲器寄存器,以确定哪个发送缓冲器可用。
  22.     for(i = 0; i < 3; i++)
  23.     {
  24.         if(!(MCP2510_Read(TXBnCTRL[i]) & 0x08))
  25.             break;
  26.     }
  27.     //三个缓冲器都不可用,返回错误
  28.     if(i == 3)
  29.     {
  30.         //printk("[%s-%d]Warning: All 3 TX-buffer are busy \n", __func__, __LINE__);
  31.         return -EBUSY;
  32.     }
  33. #else
  34.     /*** 只使用一个缓冲器,牺牲性能,保证顺序. 测试比较得出:牺牲的性能微不足道 ***/
  35.     i = 0;
  36.     if((MCP2510_Read(TXBnCTRL[i]) & 0x08))
  37.     {
  38.         return -EBUSY;
  39.     }
  40. #endif
  41.     
  42.     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",
  43.             __func__, __LINE__,
  44.             SendMsg->Length,
  45.             SendMsg->SID,
  46.             SendMsg->EID,
  47.             SendMsg->RTR,
  48.             SendMsg->Messages[0],
  49.             SendMsg->Messages[1],
  50.             SendMsg->Messages[2],
  51.             SendMsg->Messages[3],
  52.             SendMsg->Messages[4],
  53.             SendMsg->Messages[5],
  54.             SendMsg->Messages[6],
  55.             SendMsg->Messages[7]);
  56.     /** Start send process **/
  57.     MCP2510_CS_L;
  58.     iowrite8(0x02, (void *)SPTDAT0);
  59.     while(!SPI0_READY);
  60.     iowrite8(TXBnCTRL[i] + 1, (void *)SPTDAT0);
  61.     while(!SPI0_READY);
  62.     reg = SendMsg->SID >> 3;
  63.     iowrite8(reg, (void *)SPTDAT0);
  64.     while(!SPI0_READY);
  65.     reg = (unsigned char)(SendMsg->SID << 5);
  66.     reg =reg |(SendMsg->EID >> 16);
  67.     //if(SendMsg->EID)
  68.     if(1)
  69.     {
  70.         reg |= (1 << 3);
  71.     }
  72.     iowrite8(reg, (void *)SPTDAT0);
  73.     while(!SPI0_READY);
  74.     reg = (unsigned char)(SendMsg->EID >> 8);
  75.     iowrite8(reg, (void *)SPTDAT0);
  76.     while(!SPI0_READY);
  77.     reg = (unsigned char)SendMsg->EID;
  78.     iowrite8(reg, (void *)SPTDAT0);
  79.     while(!SPI0_READY);
  80.     if(SendMsg->Length > 8)
  81.     {
  82.         printk("[%s-%d]: the length of data is %d grate than 8 !!! \n", __func__, __LINE__, SendMsg->Length);
  83.         //SendMsg->Length = 8;
  84.     }
  85.     iowrite8(SendMsg->Length | (SendMsg->RTR << 6), (void *)SPTDAT0);

  86.     for(reg = 0; reg < SendMsg->Length; reg++)
  87.     {
  88.         while(!SPI0_READY);
  89.         iowrite8(SendMsg->Messages[reg], (void *)SPTDAT0);
  90.     }
  91.     while(!SPI0_READY);
  92.     //printk("[%s-%d]: %d bytes date had been sent ! \n", __func__, __LINE__, SendMsg->Length);
  93.     MCP2510_CS_H;

  94.     MCP2510_BitModi(TXBnCTRL[i], 0x08, 0x08);

  95.     return SendMsg->Length;

  96. }
下面是中断上下文从canbus总线读取数据

点击(此处)折叠或打开

  1. /*************************************************************************************
  2.  *
  3.  * Function __mcp2510Pkt_read
  4.  *
  5.  * input: intrNum
  6.  * output: pRcvMsg
  7.  * return:
  8.  *
  9.  * descriptor:
  10.  *
  11.  *************************************************************************************/
  12. static int __mcp2510Pkt_read(struct CANBus_Message* pRcvMsg, unsigned char intrNum)
  13. {
  14.     unsigned char revAddr;
  15.     unsigned char uMes;
  16.     //int ret;

  17.     revAddr = (intrNum << 3) + 1; //得到触发中断的接收缓冲器寄存器的地址

  18.     /** read SID/EID/RTR/Length **/
  19.     MCP2510_CS_L;
  20.     while(!SPI0_READY);
  21.     iowrite8(0x03, (void *)SPTDAT0);
  22.     while(!SPI0_READY);
  23.     iowrite8(revAddr, (void *)SPTDAT0);
  24.     while(!SPI0_READY);
  25.     iowrite8(0xFF, (void *)SPTDAT0);
  26.     while(!SPI0_READY);
  27.     pRcvMsg->SID = ioread8((void *)SPRDAT0) << 3;
  28.     iowrite8(0xFF, (void *)SPTDAT0);
  29.     while(!SPI0_READY);
  30.     uMes = ioread8((void *)SPRDAT0);
  31.     pRcvMsg->SID |= (uMes >> 5);
  32.     pRcvMsg->EID = ((uMes << 16) & 0x3ffff);
  33.     if(!(uMes & 0x08))
  34.     {
  35.         pRcvMsg->RTR = (uMes >> 4) & 0x1;
  36.     }
  37.     iowrite8(0xFF, (void *)SPTDAT0);
  38.     while(!SPI0_READY);
  39.     pRcvMsg->EID |= (ioread8((void *)SPRDAT0) << 8);
  40.     iowrite8(0xFF, (void *)SPTDAT0);
  41.     while(!SPI0_READY);
  42.     pRcvMsg->EID |= ioread8((void *)SPRDAT0);
  43.     iowrite8(0xFF, (void *)SPTDAT0);
  44.     while(!SPI0_READY);
  45.     revAddr = ioread8((void *)SPRDAT0);
  46.     if(uMes & 0x08)
  47.     {
  48.         pRcvMsg->RTR = (revAddr >> 6) & 0x1;
  49.     }
  50.     pRcvMsg->Length = revAddr & 0x0F;
  51.     if (pRcvMsg->Length > 8)
  52.     {
  53.         PLOG("[%s-%d]: Message Length is:%u \n", __func__, __LINE__, pRcvMsg->Length);
  54.         pRcvMsg->Length = 8;
  55.     }
  56.     /** read data **/
  57.     for(uMes = 0; uMes < pRcvMsg->Length; uMes++)
  58.     {
  59.         iowrite8(0xFF, (void *)SPTDAT0);
  60.         while(!SPI0_READY);
  61.         pRcvMsg->Messages[uMes] = ioread8((void *)SPRDAT0);
  62.     }
  63.     while(!SPI0_READY);
  64.     MCP2510_CS_H;
  65.     /** Clear interrupt flag **/
  66.     uMes = (intrNum >> 1) - 5;
  67.     MCP2510_BitModi(0x2C, uMes, 0);

  68.     return 1;
  69. }


阅读(1321) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~