分类: LINUX
2013-12-20 11:08:53
原文地址:S3C2440 RS485驱动 作者:fly123456789
环境arm linux
根据serial/s3c2410.c搭建485驱动整体框架,因为要实现实时响应命令功能,所以将部分数据处理放在驱动程序中做,这样可以保证在1ms内完成数据通信,系统通信可靠。
整体框架如下
static __init int s3c485_init(void)
{
int res;
dev_t dev = 0;
if (s3c485_major) {
dev = MKDEV(s3c485_major, uart_minor);
res = register_chrdev_region(dev, s3c485_nr_devs, S3C485_NAME);
} else {
// dynamic alloc dev major/minor
res = alloc_chrdev_region(&dev, uart_minor, s3c485_nr_devs, S3C485_NAME);
s3c485_major = MAJOR(dev);
}
if (res < 0) {
printk(KERN_INFO "s3c_uart1: can't get major %d/n", s3c485_major);
return res;
}
{
struct s3c485_dev *dev = &uart_dev;
s3c485_setup_cdev(dev, 0);
// 硬件配置,初始化寄存器地址和I/O,此处也可以写在device_driver的probe中
s3c485_setup_regs(dev, 2);
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(s3c485_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, S3C485_NAME);
#endif
/*
* 注册接收中断函数,实时响应命令
*/
if (request_irq(dev->irq, s3c485_rx_interrupt, /*SA_SHIRQ*/0, S3C485_NAME, dev)) {
printk("s3c485: uart_setup_base - Can't get irq %d/n", dev->irq);
return -EBUSY;
}
}
// register over
printk("S3C-UART2 driver v" S3C485_VER "/n");
return 0;
}
// exit函数做一些清理工作
static __exit void s3c485_exit(void)
{
struct s3c485_dev *dev = &uart_dev;
free_irq(dev->irq, dev);
cdev_del(&dev->cdev);
#ifdef CONFIG_DEVFS_FS
devfs_remove("s3c485");
#endif
unregister_chrdev_region(s3c485_major, s3c485_nr_devs);
}
module_init(s3c485_init);
module_exit(s3c485_exit);
// 打开函数
static int s3c485_open(struct inode *inode, struct file *filp)
{
struct s3c485_dev *dev;
int ret;
// get uart devices...
dev = container_of(inode->i_cdev, struct s3c485_dev, cdev);
// save dev data to private data
filp->private_data = dev;
// UART只允许独占方式打开
if (dev->isopened) {
up(&dev->sem);
return -EBUSY;
}
dev->isopened = 1;
// 使能接收
if ((ret = s3c485_setup_base(dev)) < 0) {
goto err;
}
// 数据初始化
...
return nonseekable_open(inode, filp);
err:
return ret;
}
// 中断函数
static irqreturn_t s3c485_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct s3c485_dev *dev = (struct s3c485_dev *)dev_id;
unsigned int status = s3c_read_reg(dev->reg_base, S3C2410_UERSTAT);// 读取错误状态寄存器
u8 data;
if (status)
PDEBUG("err status %x/n", status);
status = s3c_read_reg(dev->reg_base, S3C2410_UTRSTAT);
if (status & S3C2410_UTRSTAT_RXDR) {
data = s3c_read_reg(dev->reg_base, S3C2410_URXH) & 0xFF;
// 收到数据,并做数据处理
...
// 发送数据
s3c485_en_tx();// enable tx, I/O线置位发送
send_data();// 查询方式发送数据
s3c485_disable_tx();// disable tx, I/O线置位发送
}
out:
return IRQ_HANDLED;
}
调试时应注意通信时序
数据处理要即时