linux UART串口驅動開發(fā)文檔
W83697/W83977 super I/O串口驅動開發(fā)
本文引用地址:http://2s4d.com/article/148457.htm內容簡介: 介紹了Linux下的串口驅動的設計層次及接口, 并指出串口與TTY終端之間的關聯層次(串口可作TTY終端使用), 以及Linux下的中斷處理機制/中斷共享機制, 還有串口緩沖機制當中涉及的軟中斷機制; 其中有關w83697/w83977 IC方面的知識, 具體參考相關手冊, 對串口的配置寄存器有詳細介紹, 本文不再進行說明.
目錄索引:
一. Linux的串口接口及層次.
二. Linux的中斷機制及中斷共享機制.
三. Linux的軟中斷機制.
四. TTY與串口的具體關聯.
一. Linux的串口接口及層次.
串口是使用已經非常廣的設備了, 因此在linux下面的支持已經很完善了, 具有統一的編程接口, 驅動開發(fā)者所要完整的工作就是針對不同的串口IC來做完成相應的配置宏, 這此配置宏包括讀與寫, 中斷打開與關閉(如傳送與接收中斷), 接收狀態(tài)處理, 有FIFO時還要處理FIFO的狀態(tài). 如下我們就首先切入這一部分, 具體了解一下與硬件串口IC相關的部分在驅動中的處理, 這一部分可以說是串口驅動中的最基礎部分, 直接與硬件打交道, 完成最底層具體的串口數據傳輸.
1. 串口硬件資源的處理.
W83697及W83977在ep93xx板子上的映射的硬件物理空間如下:
W83697: 0x20000000起1K空間.
W83977: 0x30000000起1K空間.
因為串口設備的特殊性, 可以當作終端使用, 但是終端的使用在內核還未完全初始化之前(關于串口與終端的關聯及層次在第四節(jié)中詳細), 此時還沒有通過mem_init()建立內核的虛存管理機制, 所以不能通過ioreamp來進行物理內存到虛存的映射(物理內存必須由內核映射成系統管理的虛擬內存后才能進行讀寫訪問), 這與先前所講的frAMEbuffer的物理內存映射是不同的, 具體原因如下:
√終端在注冊并使用的調用路徑如下:
STart_kernel→cONsole_init→uart_console_init→ep93xxuart_console_init→register_console→csambuart_console_write.
√FrameBuffer顯卡驅動中的物理內存映射調用路徑如下:
start_kernel→ rest_init→init(內核初始線程)→ do_basic_setup→ do_initcalls→fbmem_init→lanrryfb_init
(Linux下用__setup啟動初期初始機制與__initcall系統初始化完成后的調用機制, 這兩個機制本質沒有什么差別,主要是執(zhí)行時所處的系統時段)
√串口物理內存映射到虛存的時機:
依據上面所介紹的兩條執(zhí)行路徑,再看內核的內存初始化的調用時期,只有完成這個初始化后才能進行物理內存到虛存的映射,內存的初始化主要是在start_kernel中調用的mem_init,這個調用明顯在uart_console_init之后,在fbmem_init之后,到此就全部說明了為何不能在對串口使用ioremap進行物理內存的映射了。那么究竟要在什么時機用什么方法進行串口物理內存的映射呢?
√串口物理內存的映射方式:
參考ep93xx的板載I/O的映射處理,它的處理方式是一次性將所有的物理I/O所在的內存空間映射到虛存空間,映射的基址是IO_BASE_VIRT,大小是IO_SIZE.
/* Where in virtual memory the IO devices (TImers, system controllers
* and so on). This gets used in arch/ARM/mach-ep93xx/mm.c.*/
#define IO_BASE_VIRT 0xFF000000 // Virtual addrESS of IO
#define IO_BASE_PHYS 0x80000000 // Physical address of IO
#define IO_SIZE 0x00A00000 // How much?
完成映射的函數是ep93xx_map_io, 所有要進行映射內存都在ep93xx_io_desc結構當中描述,我們的串口映射也加在這個地方,基址分別如下:
文件: linux-2.4.21/include/asm-arm/arch-ep93xx/regmap.h
#define IO_W83697_UART_BASE 0x20000000
#define IO_W83697_UART_SIZE 0x1000
#define IO_W83977_UART_BASE 0x30000000
#define IO_W83977_UART_SIZE 0x1000
#define IO_SIZE_2 (IO_SIZE+0x100000)
#define IO_BASE83697_VIRT IO_BASE_VIRT+IO_SIZE
#define IO_BASE83977_VIRT IO_BASE_VIRT+IO_SIZE_2
ep93xx_map_io完成是在arch初始化中賦值給struct machine_desc mdesc這個機器描述結構體,主要由位于mach-ep93xxarch.c文件中如下宏完成此結構的初始化:
MACHINE_START(EDB9302, edb9302)
…..
MAPIO(ep93xx_map_io) //初始化. map_io= ep93xx_map_io….
MACHINE_END
最終這個函數在調用路徑如下:
start_kernel→setup_arch→paging_init→(mdesc->map_io())
至此完成串口物理內存的映射,這個過程在console_init調用之前,因此不會有問題, 此種方法建立映射是直接創(chuàng)建物理內存頁與虛存頁的對應,大小為4k一頁,最終調用的是create_mapping(), 建立頁表映射是與具體的平臺相關的,位于mach_ep93xx/mm/ proc-arm920.S文件中提供了與具體平臺相關的頁表建立函數,其中包括TLB表操作/Cache操作/頁表操作等:
在上層的start_kernel→setup_arch→ setup_processor調用下,會在proc-arm920.S文件中查找.proc.info節(jié)的__arm920_proc_info,并從中找到配置的process相關的操作函數,具體的arm頁表建立的詳情須要參看ARM內存管理的相關手冊.
.section .proc.info, #alloc, #execinstr
.type __arm920_proc_info,#object
__arm920_proc_info:
.long 0x41009200
……
.long arm920_processor_functions
.size __arm920_proc_info, . - __arm920_proc_info
在arm920_processor_functions中包含的頁表操作如下:
/* pgtable */
.word CPU_arm920_set_pgd
.word cpu_arm920_set_pmd
.word cpu_arm920_set_pte
2. 與串口硬件相關的宏主.
如下, 下面將詳術如下, 并指出其具體被使用的環(huán)境上下文:
1>. 讀寫數據.
linux操作系統文章專題:linux操作系統詳解(linux不再難懂)linux相關文章:linux教程
評論