应用层使用socketCan的方法:http://pan.baidu.com/s/1ntsvbb7#path=%252Floongson1%252Ftools%252Fcan

功能:对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 = ,
.tseg1_max = ,
.tseg2_min = ,
.tseg2_max = ,
.sjw_max = ,
.brp_min = ,
.brp_max = ,
.brp_inc = ,
}; struct sja1000_priv m_ppriv; extern struct uart_8250_port canserial_ports[]; static int can_update_spt(const struct can_bittiming_const *btc,
int sampl_pt, int tseg, int *tseg1, int *tseg2)
{
*tseg2 = tseg + - (sampl_pt * (tseg + )) / ;
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 * (tseg + - *tseg2) / (tseg + );
} static int can_calc_bittiming(struct can_priv *priv, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{ printk("Enter can_calc_bittiming\n"); long best_error = , error = ;
int best_tseg = , best_brp = , brp = ;
int tsegall, tseg = , tseg1 = , tseg2 = ;
int spt_error = , spt = , sampl_pt;
long rate;
u64 v64; bt->bitrate = ;
/* Use CiA recommended sample points */
if (bt->sample_point) {
sampl_pt = bt->sample_point;
} else {
if (bt->bitrate > )
sampl_pt = ;
else if (bt->bitrate > )
sampl_pt = ;
else
sampl_pt = ;
} /* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * + ;
tseg >= (btc->tseg1_min + btc->tseg2_min) * ; tseg--) {
tsegall = + tseg / ;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % ;
/* 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 < )
error = -error;
if (error > best_error)
continue;
best_error = error;
if (error == ) {
spt = can_update_spt(btc, sampl_pt, tseg / ,
&tseg1, &tseg2);
error = sampl_pt - spt;
if (error < )
error = -error;
if (error > spt_error)
continue;
spt_error = error;
}
best_tseg = tseg / ;
best_brp = brp;
if (error == )
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\n",
// // error / 10, error % 10);
// return -EDOM;
// } else {
// // netdev_warn(dev, "bitrate error %ld.%ld%%\n",
// // 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 / ;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2; /* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max)
bt->sjw = ;
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 + )); printk("can_calc_bittiming bitrate:%d\n",bt->bitrate); return ;
} int mysja1000_set_bittiming(struct sja1000_priv *priv)
{ printk("Enter mysja1000_set_bittiming\n");
can_calc_bittiming(&priv->can,&priv->can.bittiming,&mysja1000_bittiming_const); struct can_bittiming *bt = &priv->can.bittiming;
u8 btr0, btr1; btr0 = ((bt->brp - ) & 0x3f) | (((bt->sjw - ) & 0x3) << );
btr1 = ((bt->prop_seg + bt->phase_seg1 - ) & 0xf) |
(((bt->phase_seg2 - ) & 0x7) << );
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
btr1 |= 0x80; // netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1); printk("mysja1000_set_bittiming BTR0=0x%02x BTR1=0x%02x\n",btr0,btr1);
priv->write_reg(priv, SJA1000_BTR0, btr0);
priv->write_reg(priv, SJA1000_BTR1, btr1); return ;
} // 对发送接收计数失败的统计
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 ;
} /* 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\n ");
unsigned char status = priv->read_reg(priv, SJA1000_MOD);
u8 mod_reg_val = 0x00;
int i; for (i = ; i < ; i++) {
/* check reset bit */
if ((status & MOD_RM) == ) {
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(); 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 = ; i < ; 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();
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\n"); /* 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\n"); /* 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 ;
} 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)>>; return sub_addr+(device_addr-)*;
} 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\n"); /*******************************/
// 进行数据的获取
/* 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\n");
/* extended frame format (EFF) */
dreg = SJA1000_EFF_BUF;
id = (priv->read_reg(priv, SJA1000_ID1) << )
| (priv->read_reg(priv, SJA1000_ID2) << )
| (priv->read_reg(priv, SJA1000_ID3) << )
| (priv->read_reg(priv, SJA1000_ID4) >> );
id |= CAN_EFF_FLAG;
} else {
/* standard frame format (SFF) */
dreg = SJA1000_SFF_BUF;
id = (priv->read_reg(priv, SJA1000_ID1) << )
| (priv->read_reg(priv, SJA1000_ID2) >> );
} // 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\n",curr_index);
struct uart_port *curr_port = &canserial_ports[curr_index].port; if (fi & SJA1000_FI_RTR) {
id |= CAN_RTR_FLAG;
} else {
for (i = ; i < length_can; i++)
{ ch = priv->read_reg(priv, dreg++); uart_insert_char(curr_port, , 0x02, ch, ); curr_port->icount.tx++;
// cf->data[i] = priv->read_reg(priv, dreg++);
// printk("rx data %x\n",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\n"); // struct net_device_stats *stats = &dev->stats; uint8_t isrc, status;
int n = ; 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\n"); 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\n"); myset_reset_mode(priv); /***********************open_candev()**********************/
// err = open_candev(dev); 等效
if (!priv->can.bittiming.bitrate) {
printk("bit-timing not yet defined\n");
return -EINVAL;
} printk("priv->can.bittiming.bitrate is %d\n" ,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\n");
printk("incorrect/missing data bit-timing\n");
return -EINVAL;
} // mysja1000_set_mode(priv, CAN_MODE_START); /*********************************************/ // 请求中断 待解决
// 第一个参数irq:申请的硬件中断号; // 第二个参数handler:是一个函数指针,向系统登记的中断处理函数,是一个回调函数,当中断发生时,系统调用这个函数,传入的参数包括中断设备 id,寄存器值。 // 第三个参数flags:指定了快速中断或中断共享等中断处理属性。 // 第四个参数devices:指定设备驱动程序的名称。 // 第五个参数dev_id:传入中断处理程序的参数,可以为NULL,在注册共享中断时,此参数不能为NULL,作为共享中断时的中断区别参数。
int err = request_irq(, mysja1000_interrupt, priv->irq_flags,
"canserial8250", (void *)priv); if(!err)
{
printk("request_irq failed\n");
} mysja1000_start(priv); } int mysja1000_close(struct sja1000_priv *priv)
{ printk("mysja1000_close\n");
myset_reset_mode(priv); if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER))
free_irq(, (void *)priv); // close_candev(dev); return ;
} /*
* 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\n");
printk("the start send data:%s\n",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 \n");
fi |= SJA1000_FI_FF;
dreg = SJA1000_EFF_BUF;
priv->write_reg(priv, SJA1000_FI, fi);
priv->write_reg(priv, SJA1000_ID1, (id & 0x1fe00000) >> );
priv->write_reg(priv, SJA1000_ID2, (id & 0x001fe000) >> );
priv->write_reg(priv, SJA1000_ID3, (id & 0x00001fe0) >> );
priv->write_reg(priv, SJA1000_ID4, (id & 0x0000001f) << );
} else {
dreg = SJA1000_SFF_BUF;
priv->write_reg(priv, SJA1000_FI, fi);
priv->write_reg(priv, SJA1000_ID1, (id & 0x000007f8) >> );
priv->write_reg(priv, SJA1000_ID2, (id & 0x00000007) << );
} for (i = ; i < dlc; i++)
{
printk("send data:%d\n", 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\n");
return (priv->read_reg(priv, SJA1000_MOD) == 0xFF);
} int myregister_sja1000dev(struct sja1000_priv *priv)
{
int ret; printk("Enter myregister_sja1000dev\n");
// if (!mysja1000_probe_chip(priv))
// return -ENODEV; if (priv->reg_base && sja1000_is_absent(priv)) {
printk("probing failed\n");
return ;
} // 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\n");
priv->irq_flags = ;
// dev->irq = 14;
priv->reg_base = (void __iomem *)0xbfe50000;
priv->can.clock.freq = ;
priv->ocr = ;
priv->cdr = ; 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 ;
}

最新文章

  1. [Unity3D插件]2dToolKit系列三 碰撞检测功能的实现以及障碍物的随机摆放
  2. url传参中文乱码
  3. 让结构体类型frame的某个属性可以直接修改
  4. HDU 4020 Ads Proposal
  5. jQuery核心之那些有效的方法
  6. Phpstorm常用设置
  7. Android sqlite管理数据库基本用法
  8. When you’re nearly 40 and unmarried, and you realize you’re going to be okay
  9. 【转】iTunes下载速度太慢?两招帮你提速!-- 不错
  10. SSIS从理论到实战,再到应用(5)----流程控制之Foreach循环
  11. T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst、语言版本影响!
  12. 以太坊系列之十六: 使用golang与智能合约进行交互
  13. inode 详解
  14. c语言基础学习01
  15. ElasticSearch 5.0.0 集群安装部署文档
  16. python3 Django集成Ueditor富文本编辑器
  17. QT * 使用VS2013+QT5.7.0实现简单计算器
  18. logback root level logger level 日志级别覆盖?继承?
  19. XSS攻击 CSRF攻击
  20. hibernate配置二级缓存

热门文章

  1. POJ 2739 Sum of Consecutive Prime Numbers(尺取法)
  2. sql 分页的两种写法
  3. 3秒后自动跳转页面【js】
  4. 完整的ajax请求投票点赞功能的实现【数据库表一(票数)表二(ip限制重复投票)】
  5. day4之函数
  6. CLR
  7. JavaBean出现的目的
  8. yii2嵌入微信公众号支付
  9. windows下php连接sqlserver2008
  10. Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)