sja1000芯片can驱动程序
应用层使用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 ;
}
sja1000芯片can驱动程序的更多相关文章
- ZYNQ使用88E1510 PHY芯片的驱动程序
SDK V2014.4 PHY 88E1510 PL端以太网,自协商 standalone应用程序 PL端设计,略. 根据PL端生成的hdf,新建项目,采用官方lwip echo server例程.发 ...
- CAN 总线通信控制芯片SJA1000 的读写
SJA1000 控制信号的产生 CAN总线通信控制芯片SJA1000 没有提供单独的地址线,而使用可以与Intel 和Motorola系列微控制器兼容的分时复用地址/ 数据线.在一个读写周期内,微控制 ...
- 【openwrt】再设置
https://wiki.openwrt.org/zh-cn/doc/uci/network https://wiki.openwrt.org/zh-cn/doc/uci/wireless https ...
- 第十一章、认识与学习BASH
第十一章.认识与学习 BASH 最近升级日期:2009/08/25 1. 认识 BASH 这个 Shell 1.1 硬件.核心与 Shell 1.2 为何要学文字接口的 shell 1.3 系统的合法 ...
- Linux就这个范儿 第12章 一个网络一个世界
Linux就这个范儿 第12章 一个网络一个世界 与Linux有缘相识还得从一项开发任务说起.十八年前,我在Nucleus OS上开发无线网桥AP,需要加入STP生成树协议(SpanningTree ...
- (整理)ubuntu 的 相关知识(来自 鸟哥的私房菜)
1. Linux 文件权限概念 $ ls 察看文件的指令 $ ls -al 出所有的文件详细的权限与属性 (包含隐藏档,就是文件名第一个字符为『 . 』的文件) 在你第一次以root身份登入Linux ...
- 如何学好C语言
我相信,这可能是很多朋友的问题,我以前也有这样的感觉,编程编到一定的时候,发现能力到了瓶颈,既不深,也不扎实,半吊子.比如:你长期地使用Java和.NET ,这些有虚拟机的语言对于开发便利是便利,但是 ...
- USB中CDC-ECM的了解和配置
USB中典型类及子类: 类别 解释 子类 典型应用 IC芯片 备注 UVC 视频类 免驱USB摄像头 CDC 通讯类 RNDIS ECM(p24) 免驱USB网卡 RTL8152B EEM ..... ...
- Cramfs、JFFS2、YAFFS2全面对比
由 于嵌入式系统自身存在一些特殊要求使得一些传 统的文件系统 (如FAT.EXT2等) 并不十分适合.专 用的嵌入式文件系统应有一些自身的特性如文件系统 面对的储存介质特殊性.文件系统应具有的跨 ...
随机推荐
- 创建与合并分支-git入门教程
在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支.HEAD严格来说不是指向提交,而 ...
- PHP函数-检查某个值是否存在于数组中
函数:in_array -- 检查数组中是否存在某个值定义:bool in_array ( mixed needle, array haystack [, bool strict] )在haystac ...
- JavaWeb学习总结-04 Servlet 学习和使用
一 Servlet 1 Servlet概念 Servlet时运行在服务器端的Java程序. Servlet的框架核心是 javax.servlet.Servlet 接口. 所有自定义的Servlet都 ...
- [USACO2009 NOV GOLD]奶牛的图片
校内题,不给传送门了. 以前做完NOIp2013的火柴排队那道题后,当时很担心NOIp会出那种题,因为贪心的规则能不能看出来真的要看运气.但是这类题做多了后发现其实那道题的规则其实是很多题都已经用到了 ...
- 数据库中Count是什么意思和SUM有什么区别?
今天早上在做数据库的练习, 我是这样写的: 得出是: 后来才知道是: 结果是: 后来我意识到区别,于是查资料得到: 数据库中的count,是用来统计你查询出来的记录数,比如学生表中有十条记录:sele ...
- JavaWeb学习笔记——jsp:setproperty和getproperty
- throw er; // Unhandled 'error' event
events.js:72 throw er; // Unhandled 'error' event ^Error: listen EADDRINUSE at errnoException (net.j ...
- Redis for .NET 系列之实现分页需求
代码笔记: var tableName = "Table1"; redisClient.AddItemToSortedSet(tableName, ); redisClient.A ...
- mysql和oracle的区别(功能性能、选择、使用它们时的sql等对比)
一.并发性 并发性是oltp数据库最重要的特性,但并发涉及到资源的获取.共享与锁定. mysql:mysql以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他se ...
- CF459C Pashmak and Buses (构造d位k进制数
C - Pashmak and Buses Codeforces Round #261 (Div. 2) C. Pashmak and Buses time limit per test 1 seco ...