本课需要解决的知识点是:
1.当使用write系统调用时,是如何一步一步传递到串口驱动来的,
2.当串口驱动接收到来自用户空间的发送数据请求后,如何实现发送
在uart_write函数中,又会调用uart_start
uart_start调用__uart_start函数,
s3c24xx_serial_start_tx这个函数将是我们的发送函数,接下来我们需要了解这个函数是怎么实现的。
如果tx_enabled没有被打开,则使能中断,打开tx_enabled,但是这里面并没有数据的发送??,原因是在前面串口的打开即open 一章中介绍过,有发送中断和接收中断,当中断打开之后,如果有fifo数据,则在中断处理函数中,进行数据的接收和发送。
start_tx起到激活中断,使能中断的作用,在中断处理程序中完成数据的发送
找到中断处理程序:
发送中断处理程序s3c24xx_serial_tx_chars
发现发送数据寄存器S3C2410_UTXH,说明中断处理程序完成数据的发送。
也就是说,write函数经过一系列调用,找到了start_tx函数,start_tx激活中断,然后驱动程序里面的中断处理程序,完成数据的发送。
问题来了,数据从哪里来的?
在串口中有一个重要的部分—循环缓冲,tty会把数据放到循环缓冲里面,当触发发送中断时,中断处理程序会从循环缓冲里面把数据取走。
那么,数据是如何送进循环缓冲的?
在uart_write函数,可以看到buf是在这个函数里面写进去的,
上图中的buf是从应用程序中传递过来的,
然后uart_write会通过memcpy把buf写到循环缓冲里面去,如下
言归正传,开始分析串口中断处理处理程序之发送函数s3c24xx_serial_tx_chars函数:
循环缓冲为空,或者串口停止发送,则调用s3c24xx_serial_stop_tx来关闭中断
发送缓冲不为空,发送数据,
最多一次性发送256个字符
循环发送数据 条件:循环缓冲有数据 最多发送256个数据
在这个循环函数中,主要是做了三项工作
1.当发送fifo满的时候,退出发送
2.从循环缓冲中取出数据,写入UTXH寄存器
3.调整循环缓冲位置
综合以上流程,可以得知,uart_write会把用户空间的数据写到循环buf里面去, 驱动里面的start_tx会激活发送中断,从而调用发送中断处理函数,发送中断处理函数会从循环buf取出数据,通过一系列检验过程,最终把数据传送到串口,这便是串口的数据发送过程。
数据的接收和上面数据的发送过程基本一致,下面开始分析:
29
tty_read响应read系统调用,
调用线路规程里面的read,即n_tty_read
在n_tty_read函数中,做了下面几项工作:
将当前的状态设置为TASK_INTERRUPTIBLE状态,可中断阻塞态
如果没有数据可读,通过调度让阻塞失效。
上面便是接收数据函数之间的调用关系,流程图如下:
问题来了,read_buf中的数据从哪里来的?下面分析中断处理接收函数,便可以得到答案,
在串口接收终端处理函数s3c24xx_serial_rx_chars中,做了一下几个工作
36
如果接收到的是sysrq字符,进行特殊处理uart_handle_sysrq_char
把接收到的字符放到串口驱动的bufuart_insert_char
把串口驱动接收到的数据送进线路规程的read_buf -tty_flip_buffer_push
综合以上可以得知,在中断处理接收函数中,进行数据的接收,并将接收到的数据放到read_buf中去,而线路规程中的n_tty_read函数,则从read_buf中读走数据。over
下面是具体流程图
菜鸟一枚,如有错误,多多指教。。。