应用层使用socketCan的方法:http://pan.baidu.com/s/1ntsvbb7
功能:对can驱动程序的函数直接调用,而不经过设备驱动功能层、网络设备接口层、网络协议接口层
像串口驱动程序调用can驱动程序函数时,首先要调用
mytscan1_probe(&m_ppriv); mysja1000_set_bittiming(&m_ppriv); mysja1000_open(&m_ppriv);
这些函数,实现结构体的初始化以及相关寄存器的初始化操作。
调用 netdev_tx_t mysja1000_start_xmit(struct can_frame *cf,struct sja1000_priv *priv) 进行数据的发送。
调用 mysja1000_close()函数进行寄存器及中断的关闭操作
样例:
#include "mycan_drive.h" #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/tty.h> #include <linux/ratelimit.h> #include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> #include <linux/serial_8250.h> #include <linux/nmi.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/pm_runtime.h> #include <asm/io.h> #include <asm/serial.h> static const struct can_bittiming_const mysja1000_bittiming_const = { .name = "", .tseg1_min = 1, .tseg1_max = 16, .tseg2_min = 1, .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 64, .brp_inc = 1, }; struct sja1000_priv m_ppriv; extern struct uart_8250_port canserial_ports[15]; static int can_update_spt(const struct can_bittiming_const *btc, int sampl_pt, int tseg, int *tseg1, int *tseg2) { *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; if (*tseg2 < btc->tseg2_min) *tseg2 = btc->tseg2_min; if (*tseg2 > btc->tseg2_max) *tseg2 = btc->tseg2_max; *tseg1 = tseg - *tseg2; if (*tseg1 > btc->tseg1_max) { *tseg1 = btc->tseg1_max; *tseg2 = tseg - *tseg1; } return 1000 * (tseg + 1 - *tseg2) / (tseg + 1); } static int can_calc_bittiming(struct can_priv *priv, struct can_bittiming *bt, const struct can_bittiming_const *btc) { printk("Enter can_calc_bittiming "); long best_error = 1000000000, error = 0; int best_tseg = 0, best_brp = 0, brp = 0; int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; int spt_error = 1000, spt = 0, sampl_pt; long rate; u64 v64; bt->bitrate = 1000000; /* Use CiA recommended sample points */ if (bt->sample_point) { sampl_pt = bt->sample_point; } else { if (bt->bitrate > 800000) sampl_pt = 750; else if (bt->bitrate > 500000) sampl_pt = 800; else sampl_pt = 875; } /* tseg even = round down, odd = round up */ for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { tsegall = 1 + tseg / 2; /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; /* chose brp step which is possible in system */ brp = (brp / btc->brp_inc) * btc->brp_inc; if ((brp < btc->brp_min) || (brp > btc->brp_max)) continue; rate = priv->clock.freq / (brp * tsegall); error = bt->bitrate - rate; /* tseg brp biterror */ if (error < 0) error = -error; if (error > best_error) continue; best_error = error; if (error == 0) { spt = can_update_spt(btc, sampl_pt, tseg / 2, &tseg1, &tseg2); error = sampl_pt - spt; if (error < 0) error = -error; if (error > spt_error) continue; spt_error = error; } best_tseg = tseg / 2; best_brp = brp; if (error == 0) break; } // if (best_error) { // /* Error in one-tenth of a percent */ // error = (best_error * 1000) / bt->bitrate; // if (error > CAN_CALC_MAX_ERROR) { // // netdev_err(dev, // // "bitrate error %ld.%ld%% too high ", // // error / 10, error % 10); // return -EDOM; // } else { // // netdev_warn(dev, "bitrate error %ld.%ld%% ", // // error / 10, error % 10); // } // } /* real sample point */ bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg, &tseg1, &tseg2); v64 = (u64)best_brp * 1000000000UL; do_div(v64, priv->clock.freq); bt->tq = (u32)v64; bt->prop_seg = tseg1 / 2; bt->phase_seg1 = tseg1 - bt->prop_seg; bt->phase_seg2 = tseg2; /* check for sjw user settings */ if (!bt->sjw || !btc->sjw_max) bt->sjw = 1; else { /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ if (bt->sjw > btc->sjw_max) bt->sjw = btc->sjw_max; /* bt->sjw must not be higher than tseg2 */ if (tseg2 < bt->sjw) bt->sjw = tseg2; } bt->brp = best_brp; /* real bit-rate */ bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1)); printk("can_calc_bittiming bitrate:%d ",bt->bitrate); return 0; } int mysja1000_set_bittiming(struct sja1000_priv *priv) { printk("Enter mysja1000_set_bittiming "); can_calc_bittiming(&priv->can,&priv->can.bittiming,&mysja1000_bittiming_const); struct can_bittiming *bt = &priv->can.bittiming; u8 btr0, btr1; btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) | (((bt->phase_seg2 - 1) & 0x7) << 4); if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) btr1 |= 0x80; // netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x ", btr0, btr1); printk("mysja1000_set_bittiming BTR0=0x%02x BTR1=0x%02x ",btr0,btr1); priv->write_reg(priv, SJA1000_BTR0, btr0); priv->write_reg(priv, SJA1000_BTR1, btr1); return 0; } // 对发送接收计数失败的统计 int mysja1000_get_berr_counter(const struct sja1000_priv *priv, struct can_berr_counter *bec) { bec->txerr = priv->read_reg(priv, SJA1000_TXERR); bec->rxerr = priv->read_reg(priv, SJA1000_RXERR); return 0; } /* Read SJA1000 register */ static u8 mytscan1_read(const struct sja1000_priv *priv, int reg) { return inb((unsigned long)priv->reg_base + reg); } /* Write SJA1000 register */ static void mytscan1_write(const struct sja1000_priv *priv, int reg, u8 val) { outb(val, (unsigned long)priv->reg_base + reg); } void myset_normal_mode(struct sja1000_priv *priv) { printk("Enter myset_normal_mode "); unsigned char status = priv->read_reg(priv, SJA1000_MOD); u8 mod_reg_val = 0x00; int i; for (i = 0; i < 100; i++) { /* check reset bit */ if ((status & MOD_RM) == 0) { priv->can.state = CAN_STATE_ERROR_ACTIVE; /* enable interrupts */ if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) priv->write_reg(priv, SJA1000_IER, IRQ_ALL); else priv->write_reg(priv, SJA1000_IER, IRQ_ALL & ~IRQ_BEI); return; } /* set chip to normal mode */ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) mod_reg_val |= MOD_LOM; if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) mod_reg_val |= MOD_STM; priv->write_reg(priv, SJA1000_MOD, mod_reg_val); udelay(10); status = priv->read_reg(priv, SJA1000_MOD); } } void myset_reset_mode(struct sja1000_priv *priv) { unsigned char status = priv->read_reg(priv, SJA1000_MOD); int i; /* disable interrupts */ priv->write_reg(priv, SJA1000_IER, IRQ_OFF); for (i = 0; i < 100; i++) { /* check reset bit */ if (status & MOD_RM) { priv->can.state = CAN_STATE_STOPPED; return; } /* reset chip */ priv->write_reg(priv, SJA1000_MOD, MOD_RM); udelay(10); status = priv->read_reg(priv, SJA1000_MOD); } } // open can /******************************************************************************/ void mysja1000_write_cmdreg(struct sja1000_priv *priv, u8 val) { unsigned long flags; /* * The command register needs some locking and time to settle * the write_reg() operation - especially on SMP systems. */ spin_lock_irqsave(&priv->cmdreg_lock, flags); priv->write_reg(priv, SJA1000_CMR, val); priv->read_reg(priv, SJA1000_SR); spin_unlock_irqrestore(&priv->cmdreg_lock, flags); } /* * initialize SJA1000 chip: * - reset chip * - set output mode * - set baudrate * - enable interrupts * - start operating mode */ void mychipset_init(struct sja1000_priv *priv ) { printk("Enter the mychipset_init "); /* set clock divider and output control register */ #if defined(CONFIG_LS1X_CAN0) || defined(CONFIG_LS1X_CAN1) mysja1000_write_cmdreg(priv, 0x80); #else priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN); #endif /* set acceptance filter (accept all) */ priv->write_reg(priv, SJA1000_ACCC0, 0x00); priv->write_reg(priv, SJA1000_ACCC1, 0x00); priv->write_reg(priv, SJA1000_ACCC2, 0x00); priv->write_reg(priv, SJA1000_ACCC3, 0x00); priv->write_reg(priv, SJA1000_ACCM0, 0xFF); priv->write_reg(priv, SJA1000_ACCM1, 0xFF); priv->write_reg(priv, SJA1000_ACCM2, 0xFF); priv->write_reg(priv, SJA1000_ACCM3, 0xFF); priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL); } void mysja1000_start(struct sja1000_priv *priv) { printk("Enter the mysja1000_start "); /* leave reset mode */ if (priv->can.state != CAN_STATE_STOPPED) myset_reset_mode(priv); /* Initialize chip if uninitialized at this stage */ if (!(priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN)) mychipset_init(priv); /* Clear error counters and error code capture */ priv->write_reg(priv, SJA1000_TXERR, 0x0); priv->write_reg(priv, SJA1000_RXERR, 0x0); priv->read_reg(priv, SJA1000_ECC); /* leave reset mode */ myset_normal_mode(priv); } int mysja1000_set_mode(struct sja1000_priv *priv, enum can_mode mode) { switch (mode) { case CAN_MODE_START: mysja1000_start(priv); // if (netif_queue_stopped(dev)) // netif_wake_queue(dev); break; default: return -EOPNOTSUPP; } return 0; } static u8 sp_read_reg8(const struct sja1000_priv *priv, int reg) { return ioread8(priv->reg_base + reg); } static void sp_write_reg8(const struct sja1000_priv *priv, int reg, u8 val) { iowrite8(val, priv->reg_base + reg); } int calc_com_addr(int can_id) { int device_addr, sub_addr; device_addr = can_id & 0x0F; sub_addr = (can_id & 0x70)>>4; return sub_addr+(device_addr-1)*5; } void mysja1000_rx(struct sja1000_priv *priv) { // struct net_device_stats *stats = &dev->stats; // struct can_frame can_buff; char length_can; // struct can_frame *cf = &can_buff; struct sk_buff skb; uint8_t fi; uint8_t dreg; canid_t id; int i; unsigned ch; printk("Enter the mysja1000_rx "); /*******************************/ // 进行数据的获取 /* create zero'ed CAN frame buffer */ // skb = alloc_can_skb(dev, &cf); // if (skb == NULL) // return; fi = priv->read_reg(priv, SJA1000_FI); if (fi & SJA1000_FI_FF) { printk("mysja1000_rx expand frame "); /* extended frame format (EFF) */ dreg = SJA1000_EFF_BUF; id = (priv->read_reg(priv, SJA1000_ID1) << 21) | (priv->read_reg(priv, SJA1000_ID2) << 13) | (priv->read_reg(priv, SJA1000_ID3) << 5) | (priv->read_reg(priv, SJA1000_ID4) >> 3); id |= CAN_EFF_FLAG; } else { /* standard frame format (SFF) */ dreg = SJA1000_SFF_BUF; id = (priv->read_reg(priv, SJA1000_ID1) << 3) | (priv->read_reg(priv, SJA1000_ID2) >> 5); } // cf->can_dlc = get_can_dlc(fi & 0x0F); length_can = get_can_dlc(fi & 0x0F); int curr_index = calc_com_addr(id); printk("receive from can's com addr:%d ",curr_index); struct uart_port *curr_port = &canserial_ports[curr_index].port; if (fi & SJA1000_FI_RTR) { id |= CAN_RTR_FLAG; } else { for (i = 0; i < length_can; i++) { ch = priv->read_reg(priv, dreg++); uart_insert_char(curr_port, 0, 0x02, ch, 0); curr_port->icount.tx++; // cf->data[i] = priv->read_reg(priv, dreg++); // printk("rx data %x ",data[i]); } } spin_unlock(&curr_port->lock); tty_flip_buffer_push(&curr_port->state->port); spin_lock(&curr_port->lock); /* release receive buffer */ mysja1000_write_cmdreg(priv, CMD_RRB); } irqreturn_t mysja1000_interrupt(int irq, void *dev_id) { struct sja1000_priv *priv = (struct sja1000_priv*)dev_id; printk("mysja1000_interrupt "); // struct net_device_stats *stats = &dev->stats; uint8_t isrc, status; int n = 0; if (priv->pre_irq) priv->pre_irq(priv); /* Shared interrupts and IRQ off? */ if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF) goto out; while ((isrc = priv->read_reg(priv, SJA1000_IR)) && (n < SJA1000_MAX_IRQ)) { status = priv->read_reg(priv, SJA1000_SR); /* check for absent controller due to hw unplug */ // if (status == 0xFF && sja1000_is_absent(priv)) // goto out; // if (isrc & IRQ_WUI) // netdev_warn(dev, "wakeup interrupt "); if (isrc & IRQ_TI) { /* transmission buffer released */ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT && !(status & SR_TCS)) { // stats->tx_errors++; // can_free_echo_skb(dev, 0); } else { /* transmission complete */ // stats->tx_bytes += priv->read_reg(priv, SJA1000_FI) & 0xf; // stats->tx_packets++; } // can_led_event(dev, CAN_LED_EVENT_TX); } if (isrc & IRQ_RI) { /* receive interrupt */ while (status & SR_RBS) { mysja1000_rx(priv); status = priv->read_reg(priv, SJA1000_SR); /* check for absent controller */ // if (status == 0xFF && sja1000_is_absent(priv)) // goto out; } } if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { /* error interrupt */ // if (sja1000_err(dev, isrc, status)) // break; } n++; } out: if (priv->post_irq) priv->post_irq(priv); // if (n >= SJA1000_MAX_IRQ) // netdev_dbg(dev, "%d messages handled in ISR", n); return (n) ? IRQ_HANDLED : IRQ_NONE; } EXPORT_SYMBOL_GPL(mysja1000_interrupt); int mysja1000_open(struct sja1000_priv *priv) { printk("enter mysja1000_open "); myset_reset_mode(priv); /***********************open_candev()**********************/ // err = open_candev(dev); 等效 if (!priv->can.bittiming.bitrate) { printk("bit-timing not yet defined "); return -EINVAL; } printk("priv->can.bittiming.bitrate is %d " ,priv->can.bittiming.bitrate); if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && (!priv->can.data_bittiming.bitrate || (priv->can.data_bittiming.bitrate < priv->can.bittiming.bitrate))) { // netdev_err(dev, "incorrect/missing data bit-timing "); printk("incorrect/missing data bit-timing "); return -EINVAL; } // mysja1000_set_mode(priv, CAN_MODE_START); /*********************************************/ // 请求中断 待解决 // 第一个参数irq:申请的硬件中断号; // 第二个参数handler:是一个函数指针,向系统登记的中断处理函数,是一个回调函数,当中断发生时,系统调用这个函数,传入的参数包括中断设备 id,寄存器值。 // 第三个参数flags:指定了快速中断或中断共享等中断处理属性。 // 第四个参数devices:指定设备驱动程序的名称。 // 第五个参数dev_id:传入中断处理程序的参数,可以为NULL,在注册共享中断时,此参数不能为NULL,作为共享中断时的中断区别参数。 int err = request_irq(14, mysja1000_interrupt, priv->irq_flags, "canserial8250", (void *)priv); if(!err) { printk("request_irq failed "); } mysja1000_start(priv); } int mysja1000_close(struct sja1000_priv *priv) { printk("mysja1000_close "); myset_reset_mode(priv); if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) free_irq(14, (void *)priv); // close_candev(dev); return 0; } /* * transmit a CAN message * message layout in the sk_buff should be like this: * xx xx xx xx ff ll 00 11 22 33 44 55 66 77 * [ can-id ] [flags] [len] [can data (up to 8 bytes] */ // netdev_tx_t mysja1000_start_xmit(struct sk_buff *skb, // struct sja1000_priv *priv) netdev_tx_t mysja1000_start_xmit(struct can_frame *cf, struct sja1000_priv *priv) { // 对sk_buff 结构体定义其id、can_dlc、data // struct can_frame *cf = (struct can_frame *)skb->data; uint8_t fi; uint8_t dlc; canid_t id; uint8_t dreg; u8 cmd_reg_val = 0x00; int i; printk("Enter the mysja1000_start_xmit "); printk("the start send data:%s ",cf->data); // if (can_dropped_invalid_skb(dev, skb)) // return NETDEV_TX_OK; // netif_stop_queue(dev); fi = dlc = cf->can_dlc; id = cf->can_id; if (id & CAN_RTR_FLAG) fi |= SJA1000_FI_RTR; // CAN_EFF_FLAG 扩展帧 用扩展帧对数据进行发送 if (id & CAN_EFF_FLAG) { printk("Enter mysja1000_start_xmit expand frame "); fi |= SJA1000_FI_FF; dreg = SJA1000_EFF_BUF; priv->write_reg(priv, SJA1000_FI, fi); priv->write_reg(priv, SJA1000_ID1, (id & 0x1fe00000) >> 21); priv->write_reg(priv, SJA1000_ID2, (id & 0x001fe000) >> 13); priv->write_reg(priv, SJA1000_ID3, (id & 0x00001fe0) >> 5); priv->write_reg(priv, SJA1000_ID4, (id & 0x0000001f) << 3); } else { dreg = SJA1000_SFF_BUF; priv->write_reg(priv, SJA1000_FI, fi); priv->write_reg(priv, SJA1000_ID1, (id & 0x000007f8) >> 3); priv->write_reg(priv, SJA1000_ID2, (id & 0x00000007) << 5); } for (i = 0; i < dlc; i++) { printk("send data:%d ", cf->data[i]); priv->write_reg(priv, dreg++, cf->data[i]); } // can_put_echo_skb(skb, dev, 0); if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) cmd_reg_val |= CMD_AT; if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) cmd_reg_val |= CMD_SRR; else cmd_reg_val |= CMD_TR; mysja1000_write_cmdreg(priv, cmd_reg_val); return NETDEV_TX_OK; } int sja1000_is_absent(struct sja1000_priv *priv) { printk("sja1000_is_absent "); return (priv->read_reg(priv, SJA1000_MOD) == 0xFF); } int myregister_sja1000dev(struct sja1000_priv *priv) { int ret; printk("Enter myregister_sja1000dev "); // if (!mysja1000_probe_chip(priv)) // return -ENODEV; if (priv->reg_base && sja1000_is_absent(priv)) { printk("probing failed "); return 0; } // dev->flags |= IFF_ECHO; we support local echo // dev->netdev_ops = &sja1000_netdev_ops; myset_reset_mode(priv); mychipset_init(priv); // ret = register_candev(dev); // if (!ret) // devm_can_led_init(dev); // return ret; } // probe 这一块没什么问题 int mytscan1_probe(struct sja1000_priv *priv) { printk("Enter mytscan1_probe "); priv->irq_flags = 0; // dev->irq = 14; priv->reg_base = (void __iomem *)0xbfe50000; priv->can.clock.freq = 41406250; priv->ocr = 88; priv->cdr = 64; priv->read_reg = sp_read_reg8; priv->write_reg = sp_write_reg8; //alloc_sja1000dev priv->dev = NULL; priv->can.bittiming_const = &mysja1000_bittiming_const; priv->can.do_set_bittiming = mysja1000_set_bittiming; priv->can.do_set_mode = mysja1000_set_mode; priv->can.do_get_berr_counter = mysja1000_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_PRESUME_ACK; myregister_sja1000dev(priv); return 0; }