串口驱动程序是参照韦东山版的linux完全手册 驱动程序的结构采用比较老旧的方式
对寄存器的读写也是采用比较老的版本
以下驱动目的是通过驱动程序对串口寄存器的读写实现通信
但是在应用程序执行后没有任何反应
不知道又没人做过此类驱动指点迷津
/************************************
NAME: uart_test.c
************************************/
#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 <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <mach/hardware.h>
#include <plat/regs-adc.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/cpufreq.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <plat/regs-serial.h>
#define devicename "uart_test"
#define uart_testmajor 135
#define PCLK 50000000
#define UART1CLK PCLK
#define UARTBAUDRATE 115200
#define UART_BRD ((UART1CLK / (UARTBAUDRATE * 16)) -1)
#define TXD0READY (1<<2) //传送完毕标志位 相当于掩码
#define RXD0READY (1) //接收完毕标志位 相当于掩码
#define S3C2410_ULCON1 0x00 //一下定义用于IO映射时 基址+偏移 这边的定义就是偏移
#define S3C2410_UCON1 0x04
#define S3C2410_UFCON1 0x08
#define S3C2410_UMCON1 0x0C
#define S3C2410_UTRSTAT1 0x10
#define S3C2410_UERSTAT1 0x14
#define S3C2410_UFSTAT1 0x18
#define S3C2410_URXH1 0x24
#define S3C2410_UTXH1 0x20
#define S3C2410_UBRDIV1 0x28
#define S3C2400_PA_UARTljj (0x15000000) //原本想做的是UART1的驱动,但是开发板上的UART1只是TTL电平无法与
//PC连上 所以可以看到前面的定义都是ULCON1 等 如果是UART1驱动那么
//这里的0X15000000改为0x15004000 所以以下的ULCON1等其实上是ULCON0
static struct clk *uart_clk; //定义时钟结构体
static void __iomem *uart_base; // IO映射基址
static int uart1_init()
{ unsigned int tmp;
tmp=(readl(S3C2410_GPHCON)); //读GPHCON寄存器 为的是把管脚设为TXD0 RXD0模式
tmp= tmp&(~(0x0f) << 4);
tmp= tmp | ((0x0a << 4));
writel(tmp,S3C2410_GPHCON);
tmp=(readl(S3C2410_GPHUP)); //内部上拉
tmp= tmp&(~(0x03) << 2);
writel(tmp,S3C2410_GPHUP);
tmp=0x03;
writel(tmp,uart_base + S3C2410_ULCON1); //波特率115200 8数据位 无流控
tmp=0x05;
writel(tmp,uart_base + S3C2410_UCON1); //查询方式 PCLK时钟
tmp=0x00;
writel(tmp,uart_base + S3C2410_UFCON1); //不使用FIFO
tmp=0x00;
writel(tmp,uart_base + S3C2410_UMCON1); //不使用流控
tmp=UART_BRD;
writel(tmp,uart_base + S3C2410_UBRDIV1); //115200
}
static int uart_test_open(struct inode *inode, struct file *file) //编译 加载后 应用程序会执行OPEN函数
{ unsigned int tmp;
printk("init ok !");
uart1_init();
//在这里本应该判断上一字符是否发出 因为程序执行后只发送一次所以我想不用判断
tmp='c'; //直接往UTXH中写 按照原理来说这时 它会自动的发出字符 但是 结果没反应 所以很是疑惑
//不知道有谁能帮我解答下 谢谢
//以下都是基本结构
writel(tmp,uart_base + S3C2410_UTXH1);
printk("init ok !");
return 0;
}
static int uart_test_ioctl(struct inode *inode, struct file *file, unsigned long ciicadd, unsigned long iiccssj)
{
return 0;
}
static int uart_test_close(struct inode *inode, struct file *file)
{
return 0;
}
static int uart_test_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
return 0;
}
static char __initdata banner[] = "urrt test \n";
static struct class *uart_test_class;
static struct file_operations uart_test_fops = {
.owner = THIS_MODULE,
.release = uart_test_close,
.read = uart_test_read,
.ioctl = uart_test_ioctl,
.open = uart_test_open,
};
static int __init uart_test_init(void)
{
int ret;
unsigned int tmp;
unsigned int err;
printk(banner);
uart_clk = clk_get(NULL, "uart");
if (!uart_clk)
{
printk(KERN_ERR "failed to find adc clock source\n");
return -ENOENT;
}
clk_enable(uart_clk);
uart_base = ioremap(S3C2400_PA_UARTljj, 0x30);
if (uart_base == NULL)
{
printk(KERN_ERR "Failed to remap register block\n");
ret = -EINVAL;
}
ret = register_chrdev(uart_testmajor, devicename, &uart_test_fops);
if(ret < 0)
{
printk(devicename "can't register major number\n");
return ret;
}
uart_test_class = class_create(THIS_MODULE, devicename);
if(IS_ERR(uart_test_class))
{
printk("Err: failed in ljji2c_test class. \n");
return -1;
}
device_create(uart_test_class, NULL, MKDEV(uart_testmajor, 0), NULL, devicename);
printk(devicename "initialized\n");
return 0;
}
static void __exit uart_test_exit(void)
{
unregister_chrdev(uart_testmajor, devicename);
device_destroy(uart_test_class, MKDEV(uart_testmajor, 0));
class_destroy(uart_test_class);
}
module_init(uart_test_init);
module_exit(uart_test_exit);
MODULE_AUTHOR("LJJ");
MODULE_DESCRIPTION("uart_test");
MODULE_LICENSE("GPL");