celinessl

celinessl

0个粉丝

3

问答

0

专栏

1

资料

celinessl  发布于  2015-11-04 15:39:07
采纳率 0%
3个问答
4722

大牛帮我看看,我的uart2驱动哪里有问题?

 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include     /* IOADDRESS */
#include /* copy from user */

#include "uart2.h"

#define APB_CLK     155000000ul
#define UART_CLK    APB_CLK

#define TX_FIFO_SIZE   16

/* mux ctrl reg */
#define MUXCTRL_REG_BASE  0x200F0000

#define MUXCTRL_REG1_OFFSET   0x04
#define MUXCTRL_REG20_OFFSET  0x50

#define PERI_CRG_REG_BASE  0x20030000

#define PERI_CRG10_OFFSET  0x28
#define PERI_CRG57_OFFSET  0xE4

#define WRITE_REG(Addr, Value)       ((*(volatile unsigned int *)(Addr)) = (Value))
#define READ_REG(Addr)                (*(volatile unsigned int *)(Addr))

#define UART2_BASE                        0x200A0000
#define UART_DR                                0x00
#define UART_RSR                        0x04
#define UART_FR                                0x18
#define UART_IBRD                        0x24
#define UART_FBRD                        0x28
#define UART_LCR_H                        0x2c
#define UART_CR                                0x30
#define UART_IFLS                        0x34
#define UART_IMSC                        0x38
#define UART_RIS                        0x3C
#define UART_MIS                        0x40
#define UART_ICR                        0x44
#define UART_DMACR                        0x48

#define UART_CR_UARTEN         (1 << 0)        /* UART enable */
#define UART_CR_RXE                (1 << 9)        /* receive enable */
#define UART_CR_TXE                (1 << 8)        /* transmit enable */
#define UART_CR_LBE                (1 << 7)        /* loopback enable */

#define UART_LCR_FIFO_EN  (1 << 4)
#define UART_LCR_5_BIT                (0 << 5)
#define UART_LCR_6_BIT                (1 << 5)
#define UART_LCR_7_BIT                (2 << 5)
#define UART_LCR_8_BIT                (3 << 5)

#define UART_IFLS_RXFIFO_1_8    (0 << 3)
#define UART_IFLS_RXFIFO_1_4    (1 << 3)
#define UART_IFLS_RXFIFO_1_2    (2 << 3)
#define UART_IFLS_RXFIFO_3_4    (3 << 3)
#define UART_IFLS_RXFIFO_7_8    (4 << 3)

#define UART_IFLS_TXFIFO_1_8    (0 << 0)
#define UART_IFLS_TXFIFO_1_4    (1 << 0)
#define UART_IFLS_TXFIFO_1_2    (2 << 0)
#define UART_IFLS_TXFIFO_3_4    (3 << 0)
#define UART_IFLS_TXFIFO_7_8    (4 << 0)

#define UART_IMSC_OEIM  (1 << 10)
#define UART_IMSC_BEIM  (1 << 9)
#define UART_IMSC_PEIM  (1 << 8)
#define UART_IMSC_FEIM  (1 << 7)
#define UART_IMSC_RTIM  (1 << 6)
#define UART_IMSC_TXIM  (1 << 5)
#define UART_IMSC_RXIM  (1 << 4)

#define UART_RIS_OERIS  (1 << 10)
#define UART_RIS_BERIS  (1 << 9)
#define UART_RIS_PERIS  (1 << 8)
#define UART_RIS_FERIS  (1 << 7)
#define UART_RIS_RTRIS  (1 << 6)
#define UART_RIS_TXRIS  (1 << 5)
#define UART_RIS_RXRIS  (1 << 4)

#define UART_MIS_OEMIS  (1 << 10)
#define UART_MIS_BEMIS  (1 << 9)
#define UART_MIS_PEMIS  (1 << 8)
#define UART_MIS_FEMIS  (1 << 7)
#define UART_MIS_RTMIS  (1 << 6)
#define UART_MIS_TXMIS  (1 << 5)
#define UART_MIS_RXMIS  (1 << 4)

#define UART_ICR_OEIC   (1 << 10)
#define UART_ICR_BEIC   (1 << 9)
#define UART_ICR_PEIC   (1 << 8)
#define UART_ICR_FEIC   (1 << 7)
#define UART_ICR_RTIC   (1 << 6)
#define UART_ICR_TXIC   (1 << 5)
#define UART_ICR_RXIC   (1 << 4)

#define UART_TXIS                (1 << 5)        /* transmit interrupt status */
#define UART_RXIS                (1 << 4)        /* receive interrupt status */
#define UART_RTIS                (1 << 6)        /* receive timeout interrupt status */

#define UART_FR_TXFE   (1 << 7)
#define UART_FR_RXFF   (1 << 6)
#define UART_FR_TXFF   (1 << 5)
#define UART_FR_RXFE   (1 << 4)
#define UART_FR_BUSY   (1 << 3)

#define UART_DR_OE                (1 << 11)
#define UART_DR_BE                (1 << 10)
#define UART_DR_PE                (1 << 9)
#define UART_DR_FE                (1 << 8)

#define UART_DR_ERROR        (UART_DR_OE | UART_DR_BE | UART_DR_PE | UART_DR_FE)

#define UART_RSR_OE          (1 << 3)
#define UART_RSR_BE          (1 << 2)
#define UART_RSR_PE          (1 << 1)
#define UART_RSR_FE          (1 << 0)

#define  DEVICE_NAME     "uart2"

#define DELAY(us)        time_delay_us(us)

#define DEF_UART_BUFFER_SIZE     256

static int baud_rate = 115200;
module_param(baud_rate, int, S_IRUGO);

static int buffer_size = DEF_UART_BUFFER_SIZE;
module_param(buffer_size, int, S_IRUGO);

struct ring_buffer
{
        char *buffer;

        int length;
       
        int head;

        int tail;
};

struct uart2
{
        struct miscdevice  dev;

        struct ring_buffer rx_buffer;

        char *rx_save_buffer;
        int  rx_save_buffer_length;

        spinlock_t          rx_buffer_spinlock;
        wait_queue_head_t   rx_wait_queue;
};

static struct uart2  uart2_dev;

static void time_delay_us(unsigned int usec)
{       
        volatile int i,j;   
        //ASIC: 155MHZ      
        //AP = 155/25 = 6.2   
        for(i=0;i         {               
                for(j=0;j<50*6;j++)               
                {;}       
        }
}

static irqreturn_t uart2_isr(int irq, void * dev_id)
{
        unsigned int status;
       
        struct uart2 *dev = dev_id;

        unsigned int mis = READ_REG(IO_ADDRESS(UART2_BASE + UART_MIS));
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_ICR), mis);
       
        if (mis & (UART_MIS_RXMIS | UART_MIS_RTMIS))
        {
                /* rx or receive timeout */
                do
                {
                        unsigned int dr = READ_REG(IO_ADDRESS(UART2_BASE + UART_DR));

                        if (unlikely(dr & UART_DR_ERROR))
                        {
                                if (dr & UART_DR_OE)
                                {
                                        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_OE);

                                        printk("uart2 rx oe!\n");
                                }

                                if (dr & UART_DR_BE)
                                {
                                        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);

                                        printk("uart2 rx be!\n");
                                }

                                if (dr & UART_DR_PE)
                                {
                                        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);

                                        printk("uart2 rx pe!\n");
                                }       

                                if (dr & UART_DR_FE)
                                {
                                        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);

                                        printk("uart2 rx fe!\n");
                                }                       
                        }
                        else
                        {
                                if ((dev->rx_buffer.tail + 1) % dev->rx_buffer.length != dev->rx_buffer.head)
                                {
                                        spin_lock(&dev->rx_buffer_spinlock);       
                                        dev->rx_buffer.buffer[dev->rx_buffer.tail] = dr & 0xff;
                                        dev->rx_buffer.tail++;
                                        dev->rx_buffer.tail %= dev->rx_buffer.length;
                                        spin_unlock(&dev->rx_buffer_spinlock);
                                }
                                else
                                {
                                        break;
                                }
                        }

                        status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
                } while (!(status & UART_FR_RXFE));

                if (dev->rx_buffer.tail != dev->rx_buffer.head)
                {
                        wake_up_interruptible(&dev->rx_wait_queue);
                }
        }

        return IRQ_HANDLED;
}

static int uart2_open(struct inode *inode, struct file *filp)
{
        int ret;
        unsigned int status;
        unsigned int dummy;

        spin_lock(&uart2_dev.rx_buffer_spinlock);
        uart2_dev.rx_buffer.head = 0;
        uart2_dev.rx_buffer.tail = 0;
        spin_unlock(&uart2_dev.rx_buffer_spinlock);
       
        filp->private_data = &uart2_dev;

        /* clear fifo */
        status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
        while (!(status & UART_FR_RXFE))
        {
                dummy = READ_REG(IO_ADDRESS(UART2_BASE + UART_DR));

                status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
        }
       
        /* request interrupt */
        ret = request_irq(UART2_IRQ, uart2_isr, 0, DEVICE_NAME, &uart2_dev);
        if (ret)
        {
                printk("[uart2_init] request_irq err!\n");

                return -EIO;
        }

        /* enable interrupt */
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), UART_IMSC_RXIM | UART_IMSC_RTIM);       
       
        return 0;
}

static int uart2_close(struct inode *inode, struct file *filp)
{
        /* disable interrupt */
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), 0);

        free_irq(UART2_IRQ, &uart2_dev);
       
        return 0;
}

static ssize_t uart2_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
        int i;

        int ret;

        struct uart2 *dev = filp->private_data;
       
        if (count == 0)
        {
                return 0;
        }

        if (dev->rx_buffer.head == dev->rx_buffer.tail)
        {
                if (filp->f_flags & O_NONBLOCK)
                {
                        return -EAGAIN;
                }
                else
                {       
                        wait_event_interruptible(dev->rx_wait_queue, dev->rx_buffer.head != dev->rx_buffer.tail);
                }
        }

        /* read data */
        spin_lock(&dev->rx_buffer_spinlock);
        if (dev->rx_buffer.tail > dev->rx_buffer.head)
        {
                if (count > dev->rx_buffer.tail - dev->rx_buffer.head)
                {
                        count = dev->rx_buffer.tail - dev->rx_buffer.head;
                }
        }
        else
        {
                if (count > dev->rx_buffer.length - dev->rx_buffer.head + dev->rx_buffer.tail)
                {
                        count = dev->rx_buffer.length - dev->rx_buffer.head + dev->rx_buffer.tail;
                }
        }

        for (i = 0; i < count; i++)
        {
                dev->rx_save_buffer = dev->rx_buffer.buffer[dev->rx_buffer.head];
                dev->rx_buffer.head++;
                dev->rx_buffer.head %= dev->rx_buffer.length;
        }
        spin_unlock(&dev->rx_buffer_spinlock);
       
        ret = copy_to_user(buf, dev->rx_save_buffer, count);
        if (ret < 0)
        {
                printk("[uart2_read] copy_to_user err!\n");

                return -ERESTARTSYS;
        }

        return count;
}

static int uart2_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
        unsigned int status;

        int ret;

        int fifo_count;

        int i;

        struct uart2 *dev = filp->private_data;
       
        if (count == 0)
        {
                return 0;
        }
       
        if (count > dev->rx_save_buffer_length)
        {
                count = dev->rx_save_buffer_length;
        }

        ret = copy_from_user(dev->rx_save_buffer, buf, count);
        if (ret < 0)
        {
                printk("[uart3_write] copy_from_user err!\n");

                return -ERESTARTSYS;
        }
       
        i = 0;
        while (count > 0)
        {
                fifo_count = TX_FIFO_SIZE;
                while (fifo_count > 0 && count > 0)
                {
                        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_DR), dev->rx_save_buffer[i++]);

                        count--;
                        fifo_count--;
                }

                do
                {
                        status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
                } while (status & UART_FR_BUSY);
        }
       
        return i;
}

static void init_uart2_dev(int baud)
{
        int reg;
        int val;

        int imsc_save = READ_REG(IO_ADDRESS(UART2_BASE + UART_IMSC));
       
        /* reset */
        reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET));
        reg |= (1 << 9);
        WRITE_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET), reg);

        DELAY(1);
        reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET));
        reg &= ~(1 << 9);
        WRITE_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET), reg);
       
        /* init uart2 */
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), 0);

        /* baudrate */
        val = UART_CLK / 16 * 64 / baud;

        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_FBRD), val & 0x3f);
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IBRD), val >> 6);

        /* enable fifo */
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_LCR_H), UART_LCR_FIFO_EN | UART_LCR_8_BIT);

        /* set fifo */
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IFLS), UART_IFLS_RXFIFO_1_2);

        /* restore interrupt */
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), imsc_save);

        /* enable */
#if 1
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE);
#else
        WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE | UART_CR_LBE);
#endif
       

#if 0
        reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG10_OFFSET));
        printk("PERI_CRG10:0x%X\n", reg);
#endif
}

static long uart2_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
{
        int ret = -EINVAL;

        struct uart2 *dev = filp->private_data;
       
        if (_IOC_TYPE(cmd) != UART2_MAGIC)
        {
                printk("uart2_ioctl cmd invalid!\n");

                return -EINVAL;
        }

        if (_IOC_NR(cmd) > UART2_MAX_NR)
        {
                printk("uart2_ioctl cmd invalid!\n");

                return -EINVAL;
        }

        switch (cmd)
        {
        case UART2_BUFFER_RESET:
                spin_lock(&dev->rx_buffer_spinlock);
                dev->rx_buffer.head = 0;
                dev->rx_buffer.tail = 0;
                spin_unlock(&dev->rx_buffer_spinlock);

                ret = 0;
               
                break;

        case UART2_GET_BAUDRATE:
                *(int *)arg = baud_rate;
               
                ret = 0;

                break;
               
        case UART2_SET_BAUDRATE:
                baud_rate = *(int *)arg;
               
                init_uart2_dev(baud_rate);

                spin_lock(&dev->rx_buffer_spinlock);
                dev->rx_buffer.head = 0;
                dev->rx_buffer.tail = 0;
                spin_unlock(&dev->rx_buffer_spinlock);
       
                ret = 0;
       
                break;
               
        default:
                printk("uart2 cmd invalid!\n");

                return -EINVAL;
        }
       
        return ret;
}

static unsigned int uart2_poll(struct file *filp, poll_table *wait)
{
        unsigned int mask = 0;

        struct uart2 *dev = filp->private_data;
       
        poll_wait(filp, &dev->rx_wait_queue, wait);

        if (dev->rx_buffer.head != dev->rx_buffer.tail)
        {
                mask |= (POLLIN | POLLRDNORM);
        }

        return mask;
}

static struct file_operations uart2_fops =
{
        .owner                = THIS_MODULE,
        .open                = uart2_open,
        .read                = uart2_read,
        .write                = uart2_write,
        .release        = uart2_close,
        .unlocked_ioctl = uart2_ioctl,
        .poll                = uart2_poll
};

static int __init uart2_init(void)
{   
        int ret;
        int reg;
       
        uart2_dev.dev.minor = MISC_DYNAMIC_MINOR;
        uart2_dev.dev.name = DEVICE_NAME;
        uart2_dev.dev.fops = &uart2_fops;

        uart2_dev.rx_buffer.buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (uart2_dev.rx_buffer.buffer == NULL)
        {
                printk("kmalloc error\n");

                return -1;
        }
        uart2_dev.rx_buffer.length = buffer_size;
        uart2_dev.rx_buffer.head = 0;
        uart2_dev.rx_buffer.tail = 0;
        uart2_dev.rx_save_buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (uart2_dev.rx_save_buffer == NULL)
        {
                printk("kmalloc error\n");

                return -1;
        }
        uart2_dev.rx_save_buffer_length = buffer_size;

        spin_lock_init(&uart2_dev.rx_buffer_spinlock);

        init_waitqueue_head(&uart2_dev.rx_wait_queue);
       
        /* config pins */
        /* pin UART2_TXD */
        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));
        reg &= ~0x03;
        reg |= 0x02;
        WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET), reg);
       
        /* pin UART2_RXD */
        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
        reg &= ~0x03;
        reg |= 0x02;
        WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET), reg);

        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));       
        printk("uart2 tx %4x\n",reg);
        /* pin UART2_RXD */
        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
        printk("uart2 rxx %4x\n",reg);

       
        init_uart2_dev(baud_rate);
   
        ret = misc_register(&uart2_dev.dev);
        if (ret)
        {
                printk("could not register uart2 devices\n");

                return ret;
        }

        printk("uart2 device init OK, baud_rate:%d, buffer_size:%d\n", baud_rate, buffer_size);

        return 0;       
}

static void __exit uart2_exit(void)
{
        misc_deregister(&uart2_dev.dev);

        kfree(uart2_dev.rx_buffer.buffer);

        kfree(uart2_dev.rx_save_buffer);
       
        printk("uart2 device exit!\n");
}

module_init(uart2_init);
module_exit(uart2_exit);

MODULE_AUTHOR("Eddie Zhu");
MODULE_DESCRIPTION("uart2 driver");
MODULE_LICENSE("GPL");
我来回答
回答7个
时间排序
认可量排序

celinessl

0个粉丝

3

问答

0

专栏

1

资料

celinessl 2015-11-04 15:41:29
认可0
使用的是HI3531,应用程序打开,读写,设置均没有出错,就是管脚上没波形

kenneth197

0个粉丝

16

问答

0

专栏

17

资料

kenneth197 2015-11-04 15:48:12
认可0
看看复用配置对了没。

celinessl

0个粉丝

3

问答

0

专栏

1

资料

celinessl 2015-11-04 15:54:45
认可0
     /* config pins */
        /* pin UART2_TXD */
        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));
        reg &= ~0x03;
        reg |= 0x02;
        WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET), reg);
        
        /* pin UART2_RXD */
        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
        reg &= ~0x03;
        reg |= 0x02;
        WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET), reg);

        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));        
        printk("uart2 tx %4x\n",reg);
        /* pin UART2_RXD */
        reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
        printk("uart2 rxx %4x\n",reg);


这个地方我都确认了好多遍,管脚复用没问题呀

celinessl

0个粉丝

3

问答

0

专栏

1

资料

celinessl 2015-11-04 15:59:27
认可0
uart2 txpin reg:0x200f0004 regvalue: 0x   2
uart2 rxpin reg:0x200f0050 regvalue: 0x   2

这是我打印出来的

celinessl

0个粉丝

3

问答

0

专栏

1

资料

celinessl 2015-11-06 09:16:17
认可0
还没解决呀

knaffe

0个粉丝

3

问答

0

专栏

0

资料

knaffe 2016-07-02 08:47:11
认可0
楼主的问题解决了吗?我现在也在做串口,我只需要用串口发出一些数据就可以了。请问要做哪些工作。另外,请问在哪里可以找到关于串口的例程?

celinessl

0个粉丝

3

问答

0

专栏

1

资料

celinessl 2016-09-26 13:50:58
认可0
没解决,放弃了
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区