基于AT91RM9200+linux平台的MCP2510驱动

基于AT91RM9200+linux平台的MCP2510驱动 2011-05-26 11:40:25

分类: LINUX

 
内核为linux 2.6.30.4
在此内核里,can设备被视为网络设备,目录为linux2.6.30.4/net/can,由于项目紧,对此并不熟悉,放弃这种方式。
采用 这种方式做的驱动。
把CAN设备视为字符型驱动,添加到内核里。
适用前需创建设备
mknod /dev/mcp251x c 253 0
 
由于MCP2510与ADS7846共用SPI总线,在项目进行的过程中发现SPI总线冲突引起触摸屏死机,后来在触摸屏的驱动里新建了一个定时器,定时检查ADS7846的状态标志,发现标志有问题就恢复。解决了此问题。
 
static enum hrtimer_restart test_timer(struct hrtimer *handle)
{
struct ads7846 *ts = container_of(handle, struct ads7846, testtimer);
int value;
value = device_suspended(&ts->spi->dev);
hrtimer_start(&ts->testtimer, ktime_set(0, 50000*TS_POLL_DELAY),
     HRTIMER_MODE_REL);
if ((ts->irq_disabled == 1) && (ts->pending == 1) && (!get_pendown_state(ts)))
 {
 printk("i=%x, p=%x,v=%x\n",ts->irq_disabled,ts->pending,value);
 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),HRTIMER_MODE_REL);
 }
return HRTIMER_NORESTART;
}
static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
{
 struct ads7846 *ts = container_of(handle, struct ads7846, timer);
 int  status = 0;
static bool flag = true;
 spin_lock(&ts->lock);
 if (unlikely(!get_pendown_state(ts) ||
       device_suspended(&ts->spi->dev))) {
  if (ts->pendown) {
   struct input_dev *input = ts->input;
   input_report_key(input, BTN_TOUCH, 0);
   input_report_abs(input, ABS_PRESSURE, 0);
   input_sync(input);
   ts->pendown = 0;
#ifdef VERBOSE
   dev_dbg(&ts->spi->dev, "UP\n");
#endif
  }
  /* measurement cycle ended */
  if (!device_suspended(&ts->spi->dev)) {
   ts->irq_disabled = 0;
   enable_irq(ts->spi->irq);
  }
  ts->pending = 0;
 } else {
  /* pen is still down, continue with the measurement */
  ts->msg_idx = 0;
  ts->wait_for_sync();
  status = spi_async(ts->spi, &ts->msg[0]);
  if (status)
   dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
 }
 spin_unlock(&ts->lock);
 if (flag)
  {
  hrtimer_start(&ts->testtimer, ktime_set(0, 50000*TS_POLL_DELAY),
     HRTIMER_MODE_REL);
  flag = false;
  }
 return HRTIMER_NORESTART;
}
 
在MCP2510发送数据时,需加缓冲时间,等上一个字节发完了再发。验证可行。
static int mcp251x_hw_tx(struct spi_device *spi, int tx_buf_idx)
{
    struct mcp251x *chip = dev_get_drvdata(&spi->dev);
    uint8_t *buf = chip->spi_transfer_buf;
    struct can_frame *frame;
    int ret;
    int ext;
   int i = 0;
  
    dev_dbg(&spi->dev, "%s()\n", __FUNCTION__);
    if (down_interruptible(&chip->txblock))
     return -ERESTARTSYS;
    if (chip->txbout != chip->txbin) { 
  
 frame = &chip->txb[chip->txbout];
  
 //down(&chip->lock);
  
 if (frame->header.dlc > CAN_FRAME_MAX_DATA_LEN)
     frame->header.dlc = CAN_FRAME_MAX_DATA_LEN;
 if (frame->header.ide == 0)
     frame->header.eid = 0;
 /*  
 buf[0] = INSTRUCTION_LOAD_TXB(tx_buf_idx);
 buf[1] = frame->header.id >> 3;
 buf[2] = ((frame->header.id << 5) & 0x07) |(frame->header.srr<<4)| (frame->header.ide << 3)
     | ((frame->header.eid >> 16) & 0x03);
 buf[3]  = (frame->header.eid >> 8) &0xff;
 buf[4]  = frame->header.eid & 0xff;
 buf[5] = (frame->header.rtr << 6) | frame->header.dlc;
 memcpy(buf + 6, frame->data, frame->header.dlc);
 */
 /*
 if(frame->header.eid >0)
  ext = true;
 else
  ext = false;
 */
 ext = frame->header.ide;
 //printk("ext = %d, eid = %x\n",ext, frame->header.eid);
 if (!ext)
  {
  printk("in=%d out=%d\n",chip->txbin,chip->txbout);
  chip->txbout = chip->txbin - 1;
  frame = &chip->txb[chip->txbout];
  }
  mdelay(5); //发送缓冲时间
 mcp251x_write_can(spi, tx_buf_idx, ext, (frame->header.id<<18) |frame->header.eid, frame->header.rtr
  , frame->data, frame->header.dlc);
// ret = spi_write(spi, buf, 6 + CAN_FRAME_MAX_DATA_LEN);
// if (ret < 0)
//     dev_dbg(&spi->dev, "%s: failed: ret = %d\n", __FUNCTION__, ret);
// up(&chip->lock);
 /* update pos of ring buffer */
 chip->txbout++;
 if (chip->txbout >= MCP251X_BUF_LEN)
     chip->txbout = 0;
 up(&chip->txblock);
 mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ |TXBCTRL_TXPRI(3-tx_buf_idx));
    }
else
 up(&chip->txblock);
    return 0;
}
 
目前,此系统运行稳定可靠。
同时希望高手给出更可靠的方案
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值