⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c44b0_uart.c

📁 基于s3c44b0串口uart的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*======================================================
*   File Name: s3c44b0_uart.c  
*
*   Author:gong
*
*   Email:gongyanlei@msn.com
*
*   QQ & MSN:6213599, gongyanlei@msn.com

*   Modification History: 2008-05 gong, created.
*
*   Debug History: 2008-05
*
======================================================*/

#ifndef __KERNEL__
#define __KERNEL__
#endif

//#ifndef MODULE
//  #define MODULE
//#endif

/* includes */

#include <linux/kernel.h>       /* printk() */
#include <linux/module.h>       /*this is a kernel module, so ....*/
#include <linux/interrupt.h>
#include <linux/init.h>         /*module_init, module_exit, etc*/
#include <linux/types.h>        /* size_t */
#include <linux/sched.h>        /* current and everything */
//#include <linux/tqueue.h>
#include <linux/fs.h>           /*register_chrdev, file etc*/

#include <asm/uaccess.h>        /*copy_to_user, copy_from_user*/
#include <asm/hardware.h>       	
#include <asm/irq.h>            /*request_irq, etc*/
#include <asm/io.h>
//#include <asm/system.h>
//#include <asm/bitops.h>

#include "s3c44b0_uart.h"

/* =============for debugging usage================*/

#define   DEBUG                     /*used while debugging*/

/*===========================================*/
/*                                          globals                                            */
/*===========================================*/
#define                 IRQ_S3C44B0_UART        INT_EINT2

static LOOP_QUEUE   rxQueue;                /*for received data */
static LOOP_QUEUE   txQueue;                /*for transmitted data */

static char *           dev_idkp = S3C44B0_UART_NAME;       /*for request_irq()*/

static unsigned char    lstCmdReqSN = 0 ;           /*last sequence number of command request*/
static unsigned char    lstStsRepSN  = 0 ;          /*last sequence number of transmitted status report*/


/*============================================
Description:    1.reset queue.
=============================================*/
static void reset_queue( LOOP_QUEUE * pQueue )
{
    int i = 0 ;
    int     j = 0 ;

    pQueue->rear =  0  ;
    pQueue->front  =  0  ;

    for ( i = 0 ; i < MAX_ITEM_NUM ; i++ )
    {
        for ( j = 0 ; j < MAX_MSG_LEN ; j++ )
        {
            pQueue->data[ i ][ j ] = 0; 
        }
    }
}


/*============================================
Description:    1.query if the query is empty.
Return:     1--empty.
            0--not empty.
=============================================*/
static int query_queue_empty ( LOOP_QUEUE * pQueue ) 
{

    return ( pQueue->rear == pQueue->front );
    
}


/*============================================
Description:    1.query if the query is full.
Return:     1--full.
            0--not full.
=============================================*/
static int query_queue_full ( LOOP_QUEUE * pQueue )
{
    return ( ( pQueue->rear + 1 ) % MAX_ITEM_NUM == pQueue->front );
}


/*============================================
Description:    insert an item into queue.
=============================================*/
static void in_queue (  LOOP_QUEUE * pQueue  ) 
{
    pQueue->rear = ( pQueue->rear + 1 ) % MAX_ITEM_NUM;
}


/*============================================
Description:    remove an item out of queue.
=============================================*/
static void out_queue (  LOOP_QUEUE * pQueue  ) 
{
    unsigned char i = 0 ;

    for ( i = 0 ; i < pQueue->len[ pQueue->front ] ; i ++ )
    {
        pQueue->data[ pQueue->front ][ i ] = 0 ;
    }
    
    pQueue->front = ( pQueue->front + 1 ) % MAX_ITEM_NUM;

}


/*============================================
Description:    1.disable THRE interrupt
            2.enable received data available interrupt,and receiver line 
            tatus interrupt
            3.this function shoud be used after enable_s3c44b0_uart_all_int().
=============================================*/
static void enable_s3c44b0_uart_thre_int(void)
{
    S3C44B0_UART_LCR = S3C44B0_UART_LCR & ( ~ LCR_DLAB );   /*DLAB=0*/

    S3C44B0_UART_IER = S3C44B0_UART_IER | IER_EN_THRE_INT ; 
}


/*============================================
Description:    1.disable THRE interrupt
            2.enable received data available interrupt,and receiver line 
            status interrupt
            3.this function shoud be used after enable_s3c44b0_uart_all_int().
=============================================*/
static void disable_s3c44b0_uart_thre_int(void)
{

    S3C44B0_UART_LCR = S3C44B0_UART_LCR & ( ~ LCR_DLAB );   /*DLAB=0*/

    S3C44B0_UART_IER = S3C44B0_UART_IER & ( ~ IER_EN_THRE_INT ); 
}


/*============================================
Description:    we need to configure LCR,BAUD RATE,MCR,FCR,IER for 
            s3c44b0_uart.
=============================================*/
static void config_s3c44b0_uart(void)
{
    /*line control registe=0000 1011*/
    /*8 bits, 1 stop bit, odd*/
    
    S3C44B0_UART_LCR = LCR_8_CHR_BIT | LCR_1_STOP_BIT | LCR_EN_PARITY ;


    /*Baud Rate*/
    /*DLAB=1*/
    
    S3C44B0_UART_LCR = S3C44B0_UART_LCR | LCR_DLAB ;

    /*divisor = XIN frequency input  ÷(desired baud rate ×16)*/
    
    S3C44B0_UART_DLSB = ( XTALL / ( DESIRED_BAUD_RATE * 16 ) ) & 0x00FF ;   
    S3C44B0_UART_DMSB = ( XTALL / ( DESIRED_BAUD_RATE * 16 ) ) >> 8 ;   


    /*Modem Control Register=0010 0010*/
    /* Auto-RTS and auto-CTS enabled*/

    //S3C44B0_UART_MCR = MCR_EN_AUTO_FLOW;  


    /*FIFO Interrupt Control Register=0100 0001*/
    /*64bytes mode, trigger level=56, enable the transmit and receive FIFOs*/

    S3C44B0_UART_LCR = S3C44B0_UART_LCR | LCR_DLAB  ;   /* DLAB = 1 */
    S3C44B0_UART_FCR = FCR_64_BYTE_MODE | FCR_56_TRIGGER_LEVEL_64 | FCR_FIFO_ENALBE| FCR_CLR_RX_FIFO |FCR_CLR_TX_FIFO ;

    /*Interrupt Enable Register=0000 0101*/
    /*DLAB=0*/
    
    S3C44B0_UART_LCR = S3C44B0_UART_LCR & ( ~LCR_DLAB)  ;   

    /*enable received data available interrupt,  and receiver line status interrupt; disable THRE interrupt*/
    
    S3C44B0_UART_IER = IER_EN_RDA_INT | IER_EN_RLS_INT ;
    
}


/*============================================
Description:    1.if there are items in rxQueue, read one of them.
            2.we should enter the critical area to protect the shared data.
            3.we need do the maintenance of the rxQueue.
=============================================*/ 
static int s3c44b0_uart_read(struct file *filp, char *buf, int count, loff_t *l)
{

    unsigned char i = 0 ;   
    
    disable_irq( IRQ_S3C44B0_UART );                    /*disable s3c44b0_uart interrupt on ARM*/

    if ( query_queue_empty( &rxQueue) != 1 )
    {
#ifdef  DEBUG
        printk("enter S3C44B0_UART_read( ).\n");
        printk("rxQueue is not empty.\n");
#endif

        count = rxQueue.len[ rxQueue.front ] ;      /*get the length of data*/

#ifdef  DEBUG
        printk("rxQueue.len[ %u ] = %u\n",  rxQueue.front , count );
        printk("copying rxQueue.data[ %u ] to user... ...", rxQueue.front  );
#endif
        
        copy_to_user( buf, &rxQueue.data[ rxQueue.front ],  count );

#ifdef  DEBUG
        printk("done\n" );
        printk("they are:\n");
        
        for( i = 0 ; i < count ; i ++ )
        {
            printk("0x%x ", rxQueue.data[ rxQueue.front ][ i ] );
        }

        printk("\n");
        printk("out rxQueue... ...");
#endif

        out_queue( &rxQueue );                  /*maintanence of  the rxQueue*/

#ifdef  DEBUG
        printk("done\n" );
        printk("rxQueue.front = %u,  rxQueue.rear = %u\n",  rxQueue.front ,  rxQueue.rear );
#endif

#ifdef  DEBUG
        printk("exit S3C44B0_UART_read( ).\n\n" );
#endif
    }
    else
    {
        count = 0;
    }
    
    enable_irq(IRQ_S3C44B0_UART);                   /*enable s3c44b0_uart interrupt on ARM*/



    return count;
 }


/*=====================================================
Description:    1.check if the transimtter FIFO is empty.
            2.if transimitter FIFO is empty, write the tramsimitted data into 
            transimitter FIFO directly.
            3.if transimitter FIFO is not empty, write the transimitted data into
            txQueue.
Returns:    count:  the length of transmitted data which have been written 
                    into txQueue or transmitter FIFO.
            0:          the txQueue is full and transimitter FIFO is not empty!     	
======================================================*/    
static int  s3c44b0_uart_write(struct file *filp, const char *buf, int count, loff_t *l)
{

    unsigned char   lsr_val = 0 ;                   /*to store the value of IIR*/
    unsigned char       txMsg[MAX_MSG_LEN];     /*to store the data of buf temporarily*/
    unsigned char   i = 0 ;
    //unsigned char *   pBuf;

    printk("enter write\n");
    
    disable_irq( IRQ_S3C44B0_UART );                /*disable s3c44b0_uart interrupt on ARM*/   
    
    //pBuf = (unsigned char *)buf;

    lsr_val = S3C44B0_UART_LSR;

    printk("LSR = 0x%x\n", lsr_val);

    if ( lsr_val & LSR_THRE )
    {
#ifdef DEBUG
        printk("we will send msg directly\n");
        printk("coping msg from user... ...");
#endif
        copy_from_user( txMsg,  buf , count ) ;
#ifdef DEBUG
        printk("done\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -