UART 发送字节成功,但是不能 执行 发送成功 对应的中断服务函数
学写驱动程序,是在虚拟机中运行的, Kernel 2.4.26 ,请大家看一下代码,帮忙分析一下为什么会出现这样的问题,是不是 request IRQ 以后,还需要作什么处理才能在 中断产生的时候,运行 中断服务函数。
---------------------------------- series_uart.c ------------------------
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/ioport.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/ioport.h>
- #include <linux/wait.h>
- #include <linux/list.h>
- //#include <asm/spinlock.h>
- #include <asm/system.h>
- #include <asm/io.h>
- #include <asm/uaccess.h>
- #include <asm/irq.h>
- #include <asm/semaphore.h>
- #include "series_uart.h"
- static unsigned int series_uart_major = 254 ; /* 240 -- 254 reserved */
- static const char series_uart_dev_name[] = "series_uart_dev";
- static const char series_uart_io_name[] = "series_uart_io";
- static const char series_uart_irq_name[] = "series_uart_irq";
- static unsigned long series_uart_io_base = 0x3f8;
- static unsigned long series_uart_io_size = 8; /* 9 bytes 0x3f8 -- 0x3ff */
- static int series_uart_dev_reg = -1 ;
- static int series_uart_io_reg = -1 ;
- static int series_uart_irq_reg = -1 ;
- static size_t series_uart_rx_buf_head = 0;
- static size_t series_uart_rx_buf_tail = 0;
- static char series_uart_rx_buf[ SERIES_UART_RX_BUF_SIZE ];
- static size_t series_uart_tx_buf_head = 0;
- static size_t series_uart_tx_buf_tail = 0;
- static char series_uart_tx_buf[ SERIES_UART_TX_BUF_SIZE ];
- static wait_queue_head_t series_uart_rx_wait_queue_head;
- static wait_queue_head_t series_uart_tx_wait_queue_head;
- static struct semaphore series_uart_rx_sem;
- static struct semaphore series_uart_tx_sem;
- static spinlock_t series_uart_rx_lock;
- static spinlock_t series_uart_tx_lock;
- static ssize_t series_uart_read( struct file *file, char *buf, size_t size, loff_t *loff )
- {
- size_t count;
- if( down_interruptible( &series_uart_rx_sem ) ){
- return -ERESTARTSYS;
- }
- while( size ){
- count = SERIES_UART_RX_BUF_SIZE - series_uart_rx_buf_head ;
- if( size < count ){
- count = size;
- }
- while( series_uart_rx_buf_tail - series_uart_rx_buf_head < count ){
- interruptible_sleep_on( &series_uart_rx_wait_queue_head );
- }
- /* <asm/uaccess.h>
- * unsigned long copy_to_user( void * to, const void * from, unsigned long count )
- */
- copy_to_user( buf, series_uart_rx_buf + series_uart_rx_buf_head, count );
- series_uart_rx_buf_head += count;
- spin_lock_irq( &series_uart_rx_lock );
- if( series_uart_rx_buf_head == series_uart_rx_buf_tail ){
- series_uart_rx_buf_head = series_uart_rx_buf_tail = 0;
- }
- spin_unlock_irq( &series_uart_rx_lock );
- buf += count;
- size -= count;
- }
- up( &series_uart_rx_sem );
- return size;
- }
- static ssize_t series_uart_write( struct file *file, const char *buf, size_t size, loff_t *loff )
- {
- size_t count;
- if( down_interruptible( &series_uart_tx_sem ) ){
- return -ERESTARTSYS;
- }
- while( size ){
- count = SERIES_UART_TX_BUF_SIZE - series_uart_tx_buf_tail;
- if( size < count ){
- count = size;
- }
- /* <asm/uaccess.h>
- * unsigned long copy_from_user( void * to, const void * from, unsigned long count )
- */
- copy_from_user( series_uart_tx_buf + series_uart_tx_buf_tail, buf, count );
- series_uart_tx_buf_tail += count;
- size -= count;
- buf += count;
- outb( series_uart_tx_buf[ series_uart_tx_buf_head ], SERIES_UART_IO_DATA );
- while( series_uart_tx_buf_tail != series_uart_tx_buf_head ){
- interruptible_sleep_on( &series_uart_tx_wait_queue_head );
- }
- series_uart_tx_buf_tail = series_uart_tx_buf_head = 0;
- }
- up( &series_uart_tx_sem );
- return size;
- }
- static struct file_operations series_uart_fops = {
- read : series_uart_read,
- write : series_uart_write,
- };
- static void series_uart_irq_hdlr_data_revieved( void )
- {
- if( series_uart_rx_buf_tail < SERIES_UART_RX_BUF_SIZE ){
- series_uart_rx_buf[ series_uart_rx_buf_tail ] = inb( SERIES_UART_IO_DATA );
- series_uart_rx_buf_tail ++ ;
- wake_up_interruptible( &series_uart_rx_wait_queue_head );
- }
- }
- static void series_uart_irq_hdlr_sent_holding( void )
- {
- if( series_uart_tx_buf_head < series_uart_tx_buf_tail ){
- outb( series_uart_tx_buf[ series_uart_tx_buf_head ], SERIES_UART_IO_DATA );
- series_uart_tx_buf_head ++ ;
- wake_up_interruptible( &series_uart_tx_wait_queue_head );
- }
- }
- static void series_uart_irq_hdlr( int irq, void *dev_id, struct pt_regs *reg )
- {
- unsigned char data;
- /* <asm/io.h>
- * unsigned inb( unsigned port )
- * void outb( unsigned char byte, unsigned port )
- */
- data = inb( SERIES_UART_IO_IRQ_HOLD );
- /* recieve error */
- if( data == 0x06 ){
- }
- /* data recieved */
- else if( data == 0x04 ){
- series_uart_irq_hdlr_data_revieved();
- }
- /* sent holding */
- else if( data == 0x02 ){
- series_uart_irq_hdlr_sent_holding();
- }
- /* modem */
- else if( data == 0x00 ){
- }
- outb( ( data | 0x01 ), SERIES_UART_IO_IRQ_HOLD );
- }
- static void series_uart_exit( void )
- {
- /*
- * int unregister_chrdev( unsigned int major, const char *name )
- */
- if( series_uart_dev_reg >= 0 ){
- unregister_chrdev( series_uart_major, series_uart_dev_name );
- }
- /* <linux/ioport.h>
- * void release_region( unsigned long start, unsigned long len )
- */
- if( series_uart_io_reg >= 0 ){
- release_region( series_uart_io_base, series_uart_io_size );
- }
- /* <asm/irq.h>
- * void free_irq( unsigned int irq, void *dev_id )
- */
- if( series_uart_irq_reg >= 0 ){
- free_irq( IRQ4, NULL );
- }
- }
- static int series_uart_init( void )
- {
- /*
- * int register_chrdev( unsigned int major, const char *name, struct file_operations * fops )
- */
- series_uart_dev_reg = register_chrdev( series_uart_major, series_uart_dev_name, &series_uart_fops );
- if( series_uart_dev_reg < 0 ){
- goto exit;
- }
- /* <linux/ioport.h>
- * int check_region( unsigned long start, unsigned long len )
- * struct resource * request_region( unsigned long start, unsigned long len, char *name )
- */
- series_uart_io_reg = check_region( series_uart_io_base, series_uart_io_size );
- if( series_uart_io_reg < 0 ){
- goto exit;
- }
- request_region( series_uart_io_base, series_uart_io_size, series_uart_io_name );
- /* initial the wait queue head */
- init_waitqueue_head( &series_uart_rx_wait_queue_head );
- init_waitqueue_head( &series_uart_tx_wait_queue_head );
- /* initial the semaphore */
- sema_init( &series_uart_rx_sem, 1 );
- sema_init( &series_uart_tx_sem, 1 );
- /* initial the lock */
- spin_lock_init( &series_uart_rx_lock );
- spin_lock_init( &series_uart_tx_lock );
- /* <asm/irq.h>
- * int request_irq(
- * unsigned int irq,
- * void (*handler)(int, void *, struct pt_regs *),
- * unsigned long flags,
- * const char *dev_name,
- * void *dev_id )
- * void enable_irq( int irq );
- */
- series_uart_irq_reg = request_irq( IRQ4, series_uart_irq_hdlr, SA_INTERRUPT, series_uart_irq_name, NULL );
- if( series_uart_irq_reg < 0 ){
- goto exit;
- }
- inb( SERIES_UART_IO_DATA );
- inb( SERIES_UART_IO_IRQ_SET );
- inb( SERIES_UART_IO_IRQ_HOLD );
- inb( SERIES_UART_IO_READ_LINE_STS );
- inb( SERIES_UART_IO_READ_MODEM_STS );
- /* set the default bit rate 19200 */
- outb( 0x80, SERIES_UART_IO_WRITE_LINE_CTRL );
- outb( 0x06, SERIES_UART_IO_RATE_LSB );
- outb( 0x00, SERIES_UART_IO_RATE_MSB );
- /* set 1 stop bit, 8bit data, no parity */
- outb( 0x07, SERIES_UART_IO_WRITE_LINE_CTRL );
- /* disable modem control register */
- outb( 0x00, SERIES_UART_IO_WRITE_MODEM_CTRL );
- /* set interrupt enable and interrupt trigger */
- outb( 0x03, SERIES_UART_IO_IRQ_SET );
- inb( SERIES_UART_IO_DATA );
- inb( SERIES_UART_IO_IRQ_SET );
- inb( SERIES_UART_IO_IRQ_HOLD );
- inb( SERIES_UART_IO_READ_LINE_STS );
- inb( SERIES_UART_IO_READ_MODEM_STS );
- return 0;
- exit:
- series_uart_exit();
- return -1;
- }
- module_init( series_uart_init );
- module_exit( series_uart_exit );
- MODULE_LICENSE("GPL");
复制代码
---------------------------------- series_uart.h ------------------------
- #ifndef __SERIES_UART_H__
- #define __SERIES_UART_H__
- #define SERIES_UART_IO_BASE 0x3F8
- #define SERIES_UART_IO_DATA ( SERIES_UART_IO_BASE )
- #define SERIES_UART_IO_RATE_LSB ( SERIES_UART_IO_BASE )
- #define SERIES_UART_IO_RATE_MSB ( SERIES_UART_IO_BASE + 1 )
- #define SERIES_UART_IO_IRQ_SET ( SERIES_UART_IO_BASE + 1 )
- #define SERIES_UART_IO_IRQ_HOLD ( SERIES_UART_IO_BASE + 2 )
- #define SERIES_UART_IO_WRITE_LINE_CTRL ( SERIES_UART_IO_BASE + 3 )
- #define SERIES_UART_IO_WRITE_MODEM_CTRL ( SERIES_UART_IO_BASE + 4 )
- #define SERIES_UART_IO_READ_LINE_STS ( SERIES_UART_IO_BASE + 5 )
- #define SERIES_UART_IO_READ_MODEM_STS ( SERIES_UART_IO_BASE + 6 )
- #define IRQ4 4
- #define SERIES_UART_RX_BUF_SIZE 2048
- #define SERIES_UART_TX_BUF_SIZE 2048
- #endif
复制代码
[ 本帖最后由 platinum 于 2006-7-4 18:23 编辑 ]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论