UART 发送字节成功,但是不能 执行 发送成功 对应的中断服务函数

发布于 2022-07-23 18:26:29 字数 20341 浏览 11 评论 0

学写驱动程序,是在虚拟机中运行的, Kernel 2.4.26 ,请大家看一下代码,帮忙分析一下为什么会出现这样的问题,是不是 request IRQ 以后,还需要作什么处理才能在 中断产生的时候,运行 中断服务函数。

---------------------------------- series_uart.c ------------------------

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/ioport.h>
  5. #include <linux/fs.h>
  6. #include <linux/types.h>
  7. #include <linux/ioport.h>
  8. #include <linux/wait.h>
  9. #include <linux/list.h>
  10. //#include <asm/spinlock.h>
  11. #include <asm/system.h>
  12. #include <asm/io.h>
  13. #include <asm/uaccess.h>
  14. #include <asm/irq.h>
  15. #include <asm/semaphore.h>
  16. #include "series_uart.h"
  17. static unsigned int series_uart_major = 254 ; /* 240 -- 254 reserved */
  18. static const char series_uart_dev_name[] = "series_uart_dev";
  19. static const char series_uart_io_name[]  = "series_uart_io";
  20. static const char series_uart_irq_name[] = "series_uart_irq";
  21. static unsigned long series_uart_io_base = 0x3f8;
  22. static unsigned long series_uart_io_size = 8; /* 9 bytes  0x3f8 -- 0x3ff */
  23. static int series_uart_dev_reg = -1 ;
  24. static int series_uart_io_reg  = -1 ;
  25. static int series_uart_irq_reg = -1 ;
  26. static size_t  series_uart_rx_buf_head = 0;
  27. static size_t  series_uart_rx_buf_tail = 0;
  28. static char    series_uart_rx_buf[ SERIES_UART_RX_BUF_SIZE ];
  29. static size_t  series_uart_tx_buf_head = 0;
  30. static size_t  series_uart_tx_buf_tail = 0;
  31. static char    series_uart_tx_buf[ SERIES_UART_TX_BUF_SIZE ];
  32. static wait_queue_head_t series_uart_rx_wait_queue_head;
  33. static wait_queue_head_t series_uart_tx_wait_queue_head;
  34. static struct semaphore series_uart_rx_sem;
  35. static struct semaphore series_uart_tx_sem;
  36. static spinlock_t series_uart_rx_lock;
  37. static spinlock_t series_uart_tx_lock;
  38. static ssize_t series_uart_read( struct file *file, char *buf, size_t size, loff_t *loff )
  39. {
  40.         size_t count;
  41.         if( down_interruptible( &series_uart_rx_sem ) ){
  42.                 return -ERESTARTSYS;
  43.         }
  44.         while( size ){
  45.                 count = SERIES_UART_RX_BUF_SIZE - series_uart_rx_buf_head ;
  46.                 if( size < count ){
  47.                         count = size;
  48.                 }
  49.                 while( series_uart_rx_buf_tail - series_uart_rx_buf_head < count ){
  50.                         interruptible_sleep_on( &series_uart_rx_wait_queue_head  );
  51.                 }
  52.                
  53.                 /* <asm/uaccess.h>
  54.                  * unsigned long copy_to_user( void * to, const void * from, unsigned long count )
  55.                  */
  56.                 copy_to_user( buf, series_uart_rx_buf + series_uart_rx_buf_head, count );
  57.                
  58.                 series_uart_rx_buf_head += count;
  59.                
  60.                 spin_lock_irq( &series_uart_rx_lock );
  61.                 if( series_uart_rx_buf_head == series_uart_rx_buf_tail ){
  62.                         series_uart_rx_buf_head = series_uart_rx_buf_tail = 0;
  63.                 }
  64.                 spin_unlock_irq( &series_uart_rx_lock );
  65.                 buf  += count;
  66.                 size -= count;
  67.         }
  68.         
  69.         up( &series_uart_rx_sem );
  70.         return size;
  71. }
  72. static ssize_t series_uart_write( struct file *file, const char *buf, size_t size, loff_t *loff )
  73. {
  74.         size_t count;
  75.         
  76.         if( down_interruptible( &series_uart_tx_sem ) ){
  77.                 return -ERESTARTSYS;
  78.         }
  79.         while( size ){
  80.                 count = SERIES_UART_TX_BUF_SIZE - series_uart_tx_buf_tail;
  81.                 if( size < count ){
  82.                         count = size;
  83.                 }
  84.                 /* <asm/uaccess.h>
  85.                  * unsigned long copy_from_user( void * to, const void * from, unsigned long count )
  86.                  */
  87.                 copy_from_user( series_uart_tx_buf + series_uart_tx_buf_tail, buf, count );
  88.                
  89.                 series_uart_tx_buf_tail += count;
  90.                 size -= count;
  91.                 buf  += count;
  92.                 outb( series_uart_tx_buf[ series_uart_tx_buf_head ], SERIES_UART_IO_DATA );
  93.                
  94.                 while( series_uart_tx_buf_tail != series_uart_tx_buf_head ){
  95.                         interruptible_sleep_on( &series_uart_tx_wait_queue_head  );
  96.                 }
  97.                 series_uart_tx_buf_tail = series_uart_tx_buf_head = 0;
  98.         }
  99.         
  100.         up( &series_uart_tx_sem );
  101.         return size;
  102. }
  103. static struct file_operations series_uart_fops = {
  104.         read  : series_uart_read,
  105.         write : series_uart_write,
  106. };
  107. static void series_uart_irq_hdlr_data_revieved( void )
  108. {
  109.         if( series_uart_rx_buf_tail < SERIES_UART_RX_BUF_SIZE ){
  110.                 series_uart_rx_buf[ series_uart_rx_buf_tail ] = inb( SERIES_UART_IO_DATA );
  111.                 series_uart_rx_buf_tail ++ ;
  112.                 wake_up_interruptible( &series_uart_rx_wait_queue_head );
  113.         }
  114. }
  115. static void series_uart_irq_hdlr_sent_holding( void )
  116. {
  117.         if( series_uart_tx_buf_head < series_uart_tx_buf_tail ){
  118.                 outb( series_uart_tx_buf[ series_uart_tx_buf_head ], SERIES_UART_IO_DATA );
  119.                 series_uart_tx_buf_head ++ ;
  120.                 wake_up_interruptible( &series_uart_tx_wait_queue_head );
  121.         }
  122. }
  123. static void series_uart_irq_hdlr( int irq, void *dev_id, struct pt_regs *reg )
  124. {
  125.         unsigned char data;
  126.         /* <asm/io.h>
  127.          * unsigned inb( unsigned port )
  128.          * void outb( unsigned char byte, unsigned port )
  129.          */
  130.         data = inb( SERIES_UART_IO_IRQ_HOLD );
  131.         
  132.         /* recieve error */
  133.         if( data == 0x06 ){
  134.         }
  135.         /* data recieved */
  136.         else if( data == 0x04 ){
  137.                 series_uart_irq_hdlr_data_revieved();
  138.         }
  139.         /* sent holding  */
  140.         else if( data == 0x02 ){
  141.                 series_uart_irq_hdlr_sent_holding();
  142.         }
  143.         /* modem         */
  144.         else if( data == 0x00 ){
  145.         }
  146.         outb( ( data | 0x01 ), SERIES_UART_IO_IRQ_HOLD );
  147. }
  148. static void series_uart_exit( void )
  149. {
  150.         /*
  151.          * int unregister_chrdev( unsigned int major, const char *name )
  152.          */
  153.         if( series_uart_dev_reg >= 0 ){
  154.                 unregister_chrdev( series_uart_major, series_uart_dev_name );
  155.         }
  156.         /* <linux/ioport.h>
  157.          * void release_region( unsigned long start, unsigned long len )
  158.          */
  159.         if( series_uart_io_reg >= 0 ){
  160.                 release_region( series_uart_io_base, series_uart_io_size );
  161.         }
  162.         /* <asm/irq.h>
  163.          * void free_irq( unsigned int irq, void *dev_id )
  164.          */
  165.         if( series_uart_irq_reg >= 0 ){
  166.                 free_irq( IRQ4, NULL );
  167.         }
  168. }
  169. static int series_uart_init( void )
  170. {
  171.         /*
  172.          * int register_chrdev( unsigned int major, const char *name, struct file_operations * fops )
  173.          */
  174.         series_uart_dev_reg = register_chrdev( series_uart_major, series_uart_dev_name, &series_uart_fops );
  175.         if( series_uart_dev_reg < 0 ){
  176.                 goto exit;
  177.         }
  178.         /* <linux/ioport.h>
  179.          * int check_region( unsigned long start, unsigned long len )
  180.          * struct resource * request_region( unsigned long start, unsigned long len, char *name )
  181.          */
  182.         series_uart_io_reg = check_region( series_uart_io_base, series_uart_io_size );
  183.         if( series_uart_io_reg < 0 ){
  184.                 goto exit;
  185.         }
  186.         request_region( series_uart_io_base, series_uart_io_size, series_uart_io_name );
  187.         /* initial the wait queue head */
  188.         init_waitqueue_head( &series_uart_rx_wait_queue_head );
  189.         init_waitqueue_head( &series_uart_tx_wait_queue_head );
  190.       
  191.         /* initial the semaphore */
  192.         sema_init( &series_uart_rx_sem, 1 );
  193.         sema_init( &series_uart_tx_sem, 1 );
  194.       
  195.         /* initial the lock */
  196.         spin_lock_init( &series_uart_rx_lock );
  197.         spin_lock_init( &series_uart_tx_lock );
  198.         /* <asm/irq.h>
  199.          * int request_irq(
  200.          *      unsigned int irq,
  201.          *      void (*handler)(int, void *, struct pt_regs *),
  202.          *      unsigned long flags,
  203.          *      const char *dev_name,
  204.          *      void *dev_id )
  205.          * void enable_irq( int irq );
  206.          */
  207.         series_uart_irq_reg = request_irq( IRQ4, series_uart_irq_hdlr, SA_INTERRUPT, series_uart_irq_name, NULL );
  208.         if( series_uart_irq_reg < 0 ){
  209.                 goto exit;
  210.         }
  211.         inb( SERIES_UART_IO_DATA );
  212.         inb( SERIES_UART_IO_IRQ_SET );
  213.         inb( SERIES_UART_IO_IRQ_HOLD );
  214.         inb( SERIES_UART_IO_READ_LINE_STS );
  215.         inb( SERIES_UART_IO_READ_MODEM_STS );
  216.         
  217.         /* set the default bit rate  19200 */
  218.         outb( 0x80, SERIES_UART_IO_WRITE_LINE_CTRL );
  219.         outb( 0x06, SERIES_UART_IO_RATE_LSB );
  220.         outb( 0x00, SERIES_UART_IO_RATE_MSB );
  221.         /* set 1 stop bit, 8bit data, no parity */
  222.         outb( 0x07, SERIES_UART_IO_WRITE_LINE_CTRL );
  223.         /* disable modem control register */
  224.         outb( 0x00, SERIES_UART_IO_WRITE_MODEM_CTRL );
  225.         /* set interrupt enable and interrupt trigger */
  226.         outb( 0x03, SERIES_UART_IO_IRQ_SET );
  227.         inb( SERIES_UART_IO_DATA );
  228.         inb( SERIES_UART_IO_IRQ_SET );
  229.         inb( SERIES_UART_IO_IRQ_HOLD );
  230.         inb( SERIES_UART_IO_READ_LINE_STS );
  231.         inb( SERIES_UART_IO_READ_MODEM_STS );
  232.         return 0;
  233. exit:
  234.         series_uart_exit();
  235.         return -1;
  236. }
  237. module_init( series_uart_init );
  238. module_exit( series_uart_exit );
  239. MODULE_LICENSE("GPL");

复制代码

---------------------------------- series_uart.h ------------------------

  1. #ifndef __SERIES_UART_H__
  2. #define __SERIES_UART_H__
  3. #define SERIES_UART_IO_BASE             0x3F8
  4. #define SERIES_UART_IO_DATA             ( SERIES_UART_IO_BASE )
  5. #define SERIES_UART_IO_RATE_LSB         ( SERIES_UART_IO_BASE )
  6. #define SERIES_UART_IO_RATE_MSB         ( SERIES_UART_IO_BASE + 1 )
  7. #define SERIES_UART_IO_IRQ_SET          ( SERIES_UART_IO_BASE + 1 )
  8. #define SERIES_UART_IO_IRQ_HOLD         ( SERIES_UART_IO_BASE + 2 )
  9. #define SERIES_UART_IO_WRITE_LINE_CTRL  ( SERIES_UART_IO_BASE + 3 )
  10. #define SERIES_UART_IO_WRITE_MODEM_CTRL ( SERIES_UART_IO_BASE + 4 )
  11. #define SERIES_UART_IO_READ_LINE_STS    ( SERIES_UART_IO_BASE + 5 )
  12. #define SERIES_UART_IO_READ_MODEM_STS   ( SERIES_UART_IO_BASE + 6 )
  13. #define IRQ4 4
  14. #define SERIES_UART_RX_BUF_SIZE 2048
  15. #define SERIES_UART_TX_BUF_SIZE 2048
  16. #endif

复制代码
[ 本帖最后由 platinum 于 2006-7-4 18:23 编辑 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文