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

📄 tl16c750.c

📁 此程序为串口芯片tl16c750在uClinux + s3c44b0环境下的驱动程序.tl16c750R FIFO设置为64BYTES, 除此之外,此程序还能缓存20条已经收到的串口数据.即存储数据量
💻 C
📖 第 1 页 / 共 2 页
字号:


/*======================================================
*
*   File Name: 
*   ---------
*   tl16c750.c  
*
*
*   Author:
*   -------
*   zhang dahai
*
*   Email:
*   ------
*   olivercheung@126.com
*
*   QQ & MSN;
*   ---------
*   334654529, olivercheung2005@yahoo.com.cn

*   Modification History:
*   -----------------
*   2006-7-17, zhang dahai, created.
*
*   Debug History:
*   -----------------
*   2006-9-7,22:35, zhang dahai.
*
======================================================*/

#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 "tl16c750.h"

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

#define   DEBUG                     /*used while debugging*/

/*===========================================*/
/*                                          globals                                            */
/*===========================================*/
#define                 IRQ_TL16C750        INT_EINT2

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

static char *           dev_idkp = TL16C750_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_tl16c750_all_int().
=============================================*/
static void enable_tl16c750_thre_int(void)
{
    TL16C750_LCR = TL16C750_LCR & ( ~ LCR_DLAB );   /*DLAB=0*/

    TL16C750_IER = TL16C750_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_tl16c750_all_int().
=============================================*/
static void disable_tl16c750_thre_int(void)
{

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

    TL16C750_IER = TL16C750_IER & ( ~ IER_EN_THRE_INT ); 
}


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


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

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


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

    //TL16C750_MCR = MCR_EN_AUTO_FLOW;  


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

    TL16C750_LCR = TL16C750_LCR | LCR_DLAB  ;   /* DLAB = 1 */
    TL16C750_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*/
    
    TL16C750_LCR = TL16C750_LCR & ( ~LCR_DLAB)  ;   

    /*enable received data available interrupt,  and receiver line status interrupt; disable THRE interrupt*/
    
    TL16C750_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 ssize_t tl16c750_read(struct file *filp, char *buf, size_t count, loff_t *l)
{

    unsigned char i = 0 ;   
    
    disable_irq( IRQ_TL16C750 );                    /*disable tl16c750 interrupt on ARM*/

    if ( query_queue_empty( &rxQueue) != 1 )
    {
#ifdef  DEBUG
        printk("enter TL16C750_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 TL16C750_read( ).\n\n" );
#endif
    }
    else
    {
        count = 0;
    }
    
    enable_irq(IRQ_TL16C750);                   /*enable tl16c750 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 ssize_t  tl16c750_write(struct file *filp, const char *buf, size_t 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_TL16C750 );                /*disable tl16c750 interrupt on ARM*/   
    
    //pBuf = (unsigned char *)buf;

    lsr_val = TL16C750_LSR;

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

    if ( lsr_val & LSR_THRE )

⌨️ 快捷键说明

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