linux arm9的串口tty设备驱动看的还可以,不过我想自己用杂项设备形式给串口写个驱动,驱动的目标是能发送一个字节数据,硬件上RXD、TXD短接达到自发自收。不过我驱动写的还不熟所以一些错误还不清楚怎么修改,希望您能耐心看完,代码如下
#include <linux/errno.h>
//#include <linux/kernel.h>
//#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include <plat/regs-serial.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
static void __iomem * base_addr;
#define rGPHCON (*(volatile unsigned *)0x56000070) //Port H control
#define rGPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define rULCON0 (*(volatile unsigned long *)(base_addr+S3C2410_ULCON))
#define rUCON0 (*(volatile unsigned long *)(base_addr+S3C2410_UCON))
#define rUFCON0 (*(volatile unsigned long *)(base_addr+S3C2410_UFCON))
#define rUMCON0 (*(volatile unsigned long *)(base_addr+S3C2410_UMCON))
#define rUTRSTAT0 (*(volatile unsigned long *)(base_addr+S3C2410_UTRSTAT))
#define rUERSTAT0 (*(volatile unsigned long *)(base_addr+S3C2410_UERSTAT))
#define rUFSTAT0 (*(volatile unsigned long *)(base_addr+S3C2410_UFSTAT))
#define rUMSTAT0 (*(volatile unsigned long *)(base_addr+S3C2410_UMSTAT))
#define rUTXH0 (*(volatile unsigned long *)(base_addr+S3C2410_UTXH))
#define rURXH0 (*(volatile unsigned long *)(base_addr+S3C2410_URXH))
#define rUBRDIV0 (*(volatile unsigned long *)(base_addr+S3C2410_UBRDIV))
#define BAUD_SET 115200 //设置波特率
#define DEVICE_NAME "s3c_UART0_jyj"
#define DEVICE_MAJOR 125
#define DEVICE_MINOR 0
static int vSignReceOK; //串口接收标志
static wait_queue_head_t uartrece_wait; //串口等待列表
static int uart0recedata; //接收数据
struct semaphore uart0_lock; //uart0互斥锁
static ssize_t S3C2440_uart0read (struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
if(down_trylock(&uart0_lock))
{
wait_event_interruptible(uartrece_wait, vSignReceOK);
//vSignReceOK = 0;
copy_to_user(buffer,(char * )&uart0recedata,sizeof(uart0recedata));
up(&uart0_lock);
}
}
static ssize_t S3C2440_uart0write (struct file *filp, char *buffer, size_t count,loff_t *offset)
{
while(!(rUTRSTAT0 & 0x04)); //等待,直到发送缓冲区中数据为空
rUTXH0 = 1; //想rUTXHO中写入数据,uart自动将它发送出去。
}
static ssize_t S3C2440_uart0open (struct inode *inode, struct file *filp)
{ init_waitqueue_head(&uartrece_wait);
printk("UART0 opened");
return 0;
}
static int S3C2440_UART_Release(struct inode *inode, struct file *filp)
{ //暂缺
}
static int S3C2440_uart0ioctl( struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{ //暂缺;
}
static struct file_operations dev_fops = { //文件指针
.owner = THIS_MODULE,
.open = S3C2440_uart0open,
.read = S3C2440_uart0read,
.write = S3C2440_uart0write,
.release = S3C2440_UART_Release,
.ioctl = S3C2440_uart0ioctl,
};
static struct miscdevice misc = {
.minor = DEVICE_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
/*串口中断接收数据*/
static irqreturn_t uart0reive_int_handler(int irq, void *dev_id)
{ while(!(rUTRSTAT0 & 0x01)); //等待,直到接收缓冲区中有数据
uart0recedata = rURXH0; //读取rURXH0中数据
wake_up_interruptible(&uartrece_wait);
}
/*******************************************************************************
*** 函数功能:S3C2440 UART I/O config
*** 入口参数:
*** 出口参数:
*** 函数说明: I/O表
GPH2~3 TXD0 RXD0
GPH4~5 TXD1 RXD1
GPH6~7 TXD2 RXD2
********************************************************************************/
void UARTIOPortConfig(void)
{ rGPHCON |= (0xa<<4); //将GPH2~3端口设置为串口功能,且允许上拉!
rGPHUP = 0x7ff;
}
/*******************************************************************************
*** 函数功能:UART0初始化设置
*** 入口参数:
*** 出口参数:
********************************************************************************/
void Uart_Init()
{ UARTIOPortConfig(); //配置相关串口I/O
rULCON0 = 0x3; //8个控制位,无校验位,1个停止位。
rUCON0 = 0x245; //工作于查询模式,设置uart的时钟源。
rUFCON0 = 0x0; //不使用FIFO
rUMCON0 = 0x0; //不适用流控制
rUBRDIV0 = 21;//这里我想的是自发自收,波特率暂不设置成某个值,只要能发就行
}
static int __init uart0_dev_init(void)
{ int ret;
base_addr = ioremap(S3C2410_PA_UART0,S3C_UART_OFFSET);
if(base_addr == NULL)
{ printk(KERN_ERR "failed to remap register block\n");
return -ENOENT;
}
Uart_Init();
ret = request_irq(IRQ_S3CUART_RX0, uart0reive_int_handler, IRQF_SHARED, DEVICE_NAME, 0);
if(ret)
goto ERR_reqint;
ret = misc_register(&misc);
if(ret)
goto ERR_register;
ERR_reqint :
printk(KERN_ERR "%s: request irq failed\n", __FILE__);
ERR_register :
printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
return ret;
}
static int __init uart0_dev_exit(void)
{ //暂缺;
}
module_init(uart0_dev_init);
module_exit(uart0_dev_exit);
MODULE_AUTHOR("yeqishi");
MODULE_DESCRIPTION("UART0 /dev entries driver");
MODULE_LICENSE("GPL");
/************** 内核编译出错信息如下: ***************************/
[root@yeqishi linux-2.6.30.4]# make zImage
CHK include/linux/version.h
make[1]: “include/asm-arm/mach-types.h”是最新的。
CHK include/linux/utsrelease.h
SYMLINK include/asm -> include/asm-arm
CALL scripts/checksyscalls.sh
<stdin>:1097:2: warning: #warning syscall fadvise64 not implemented
<stdin>:1265:2: warning: #warning syscall migrate_pages not implemented
<stdin>:1321:2: warning: #warning syscall pselect6 not implemented
<stdin>:1325:2: warning: #warning syscall ppoll not implemented
<stdin>:1365:2: warning: #warning syscall epoll_pwait not implemented
CHK include/linux/compile.h
CC drivers/char/uart.o
In file included from drivers/char/uart.c:13:
arch/arm/plat-s3c/include/plat/regs-serial.h:225: error: expected specifier-qualifier-list before 'upf_t' //问题主要是这句
drivers/char/uart.c:86: warning: initialization from incompatible pointer type
drivers/char/uart.c:125: warning: function declaration isn't a prototype
drivers/char/uart.c:162: warning: initialization from incompatible pointer type
make[2]: *** [drivers/char/uart.o] 错误 1
make[1]: *** [drivers/char] 错误 2
make: *** [drivers] 错误 2
这些错误还不清楚怎么修改,如果您知道能指点一二吗,谢谢
[ 此帖被yeqishi在2010-11-07 20:28重新编辑 ]