主题 : mini2440串口驱动实验 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 19870
精华: 0
发帖: 27
金钱: 135 两
威望: 27 点
综合积分: 54 分
注册时间: 2010-04-24
最后登录: 2014-05-26
楼主  发表于: 2011-03-19 16:45

 mini2440串口驱动实验

串口驱动程序是参照韦东山版的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");
级别: 新手上路
UID: 19870
精华: 0
发帖: 27
金钱: 135 两
威望: 27 点
综合积分: 54 分
注册时间: 2010-04-24
最后登录: 2014-05-26
1楼  发表于: 2011-03-21 09:34
没人应答啊     自己应答一下  出现上述问题的原因是 寄存器的地址出错了 可能没有正常的写入串口寄存器当中 采用系统自带的定义 后 正常发送  但是关于寄存器定义的头文件 也就是 程序开头的INCLUDE  现在很不清晰  不知道有没人回答下这个问题