Chinaunix首页 | 论坛 | 博客
  • 博客访问: 392761
  • 博文数量: 200
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 810
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-07 12:12
文章分类

全部博文(200)

文章存档

2015年(2)

2013年(198)

分类:

2013-01-07 14:21:12

原文地址:串口驱动程序分析 作者:garyybl

  1. //串口驱动程序分析  
  2. (1),串口写数据  
  3. 当用户层调用write()函数,就对应调用/driver/char/tty_io.c里面的tty_write()  
  4.     tty_write() --->  
  5.         do_tty_write() --->  
  6.                 //driver/char/n_tty.c  
  7.                 n_tty_write() --->  
  8.                         add_wait_queue(&tty->write_wait, &wait);//加入等待队列  
  9.                         c = tty->ops->write(tty, b, nr);--->//  
  10.                                 //driver/serial/serial_core.c  
  11.                                 uart_write();--->      
  12.                                     //数据先保存在串口端口的缓冲区,然后起动发送  
  13.                                     uart_start(tty); --->  
  14.                                         __uart_start(tty); --->  
  15.                                             port->ops->start_tx(port); --->  
  16.                                                     //串口驱动层 driver/serial/5250.c  
  17.                                                     serial8250_start_tx(); --->  
  18.                                                         up->ier |= UART_IER_THRI;//使能串口发送中断   
  19.                                                         serial_out(up, UART_IER, up->ier);//字符发送在中断函数中进行  
  20.                         schedule(); //进程调度  
  21. 总结:可见,即使是发送数据,也没有使用循环查询的方法,它只是把数据保存起来,然后开启发送中断,当串口  
  22.       芯片内部的发送缓冲区可以再次存入数据时,这个中断被触发;在中断处理函数中将数据一点点地发送给串口芯片。  
  23.         
  24. (2),串口中断发送函数  
  25.     //driver/serial/5250.c  
  26.     serial8250_interrupt(); --->  
  27.         serial8250_handle_port(up); --->  
  28.             transmit_chars(up); --->  
  29.                 serial_out();  
  30.                 uart_write_wakeup(&up->port);--->//如果已经发送完毕,唤醒进程   
  31.                     tasklet_schedule(&state->tlet); --->  
  32.                         uart_tasklet_action(); --->  
  33.                             tty_wakeup();--->  
  34.                                 //唤醒等待发送完毕的进程,以上面的加入等待队列相对应  
  35.                                 wake_up_interruptible_poll(&tty->write_wait, POLLOUT);  
  36.       
  37.                 __stop_tx(up);//如果已经发送完毕,则禁止发送中断  
  38.       
  39.       
  40.       
  41. (3)、串口读数据分析  
  42. 当用户层调用read()函数,就对应调用/driver/char/tty_io.c里面的tty_read()  
  43.     tty_read(); --->  
  44.         //读操作的具体细节都在线路规程中实现的默认的线路规程的读操作时read_chan函数  
  45.         if (ld->ops->read)  
  46.             i = (ld->ops->read)(tty, file, buf, count);--->  
  47.                 n_tty_read(); --->  
  48.                     add_wait_queue(&tty->read_wait, &wait);//加入读等待队列  
  49.                   
  50.                 c = tty->read_buf[tty->read_tail];  
  51.                 spin_lock_irqsave(&tty->read_lock, flags);      <----------------<--------<-----------                    
  52.                 tty->read_tail = ((tty->read_tail+1) &(N_TTY_BUF_SIZE-1));                            |  
  53.                 tty_put_user()                                                                      |  
  54.                 .......                                                                             |  
  55.                                                                                                     |  
  56.         n_tty_receive_buf(); --->                 <----------<---------------<-------------         |  
  57.             n_tty_receive_char(); --->                                                     |         |     
  58.                 put_tty_queue() --->                                                   |         |  
  59.                     put_tty_queue_nolock(); ---> //把数据读上来                              |         |  
  60.                         if (tty->read_cnt < N_TTY_BUF_SIZE) {                           |         |  
  61.                             tty->read_buf[tty->read_head] = c;                              |         |  
  62.                             tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);     |         |  
  63.                             tty->read_cnt++; //数据可读                    ----->--------->-------  
  64.                         }                                                                 |  
  65.                                                                                           |  
  66.                                                                                           |  
  67.         //driver/serial/5250.c                                                            |  
  68.         serial8250_interrupt(); --->                                                   |  
  69.             serial8250_handle_port();--->                                                  |  
  70.                 receive_chars(up, &status); --->                                       |  
  71.                     uart_insert_char();--->                                                |   
  72.                         tty_insert_flip_char(); --->//插入数据                             |  
  73.                             struct tty_buffer *tb = tty->buf.tail;                         |  
  74.                             if (tb && tb->used < tb->size) {                             |   
  75.                                 tb->flag_buf_ptr[tb->used] = flag;                          |  
  76.                                 tb->char_buf_ptr[tb->used++] = ch;                          |   
  77.                                 return 1;                           -------->-------------|                    
  78.                             }                                                             |  
  79.                         tty_flip_buffer_push(tty);--->                                     |   
  80.                             flush_to_ldisc(&tty->buf.work.work);--->                    |  
  81.                                 __tty_buffer_flush();---> /*刷新数据*/                     |  
  82.                                     struct tty_buffer *thead;                             |  
  83.                                     while ((thead = tty->buf.head) != NULL) {              |  
  84.                                         tty->buf.head = thead->next;                    |  
  85.                                         tty_buffer_free(tty, thead);  --------->-----------  
  86.                                     }  
  87.                                     tty->buf.tail = NULL;  
  88.                                 wake_up(&tty->read_wait);    //唤醒读进程  
  89.       
  90. http://blog.csdn.net/hui523hui523hui523/article/details/7521981
阅读(724) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~