linux裝置驅動之串列埠移植

2021-06-01 09:56:29 字數 4243 閱讀 6805

(1)串列埠移植

s3c2440共有3個串列埠,在smdk2440平台上串列埠0和串列埠1都作為普通串列埠使用,串列埠2工作在紅外收發模式。tq2440開發板將它們都作為普通串列埠,目前所需要的只有串列埠0,作為控制終端,所以此處不作修改。

在檔案 linux/arch/arm/plat-s3c24xx/devs.c中定義了三個串列埠的硬體資源。

static struct resource s3c2410_uart0_resource = ;

static struct resource s3c2410_uart1_resource = ;

static struct resource s3c2410_uart2_resource = ;

在檔案linux/arch/arm/plat-samsung/dev-uart.c中定義了每個串列埠對應的平台裝置。

static struct platform_device s3c24xx_uart_device0 = ;

static struct platform_device s3c24xx_uart_device1 = ;

static struct platform_device s3c24xx_uart_device2 = ;

在檔案linux/arch/arm/mach-s3c2440/mach-smdk2440.c中有串列埠一些暫存器的初始化配置。

static struct s3c2410_uartcfg smdk2440_uartcfgs __initdata = ,

[1] = ,

/* ir port */

[2] = 

};在檔案linux/arch/arm/mach-s3c2440/mach-smdk2440.c中將呼叫函式

s3c24xx_init_uarts()最終將上面的硬體資源,初始化配置,平台裝置整合到一起。

在檔案 linux/arch/arm/plat-s3c/init.c中有

static int __init s3c_arch_init(void)

這個函式將串列埠所對應的平台裝置新增到了核心。

(2)串列埠裝置驅動原理**

我認為任何裝置在linux中的實現就「兩條線」。一是裝置模型的建立,二是讀寫資料流。串列埠驅動也是這樣。

串列埠裝置模型建立:

串列埠裝置驅動的核心結構體在檔案linux/drivers/serial/samsuing.c中如下

static struct uart_driver s3c24xx_uart_drv = ;

串列埠驅動的註冊

static int __init s3c24xx_serial_modinit(void)

串列埠驅動其實是乙個典型的tty驅動

int uart_register_driver(struct uart_driver *drv)

其實tty驅動的本質是乙個字元裝置,在檔案 linux/drivers/char/tty_io.c中

int tty_register_driver(struct tty_driver *driver)

它所關聯的操作函式集tty_fops在檔案linux/drivers/char/tty_io.c中實現

static const struct file_operations tty_fops = ;

到此串列埠的驅動作為tty_driver被註冊到了核心。前面提到串列埠的每乙個埠都是作為平台裝置被新增到核心的。那麼這些平台裝置就對應著有它們的平台裝置驅動。在檔案linux/drivers/serial/s3c2440.c中有:

static struct platform_driver s3c2440_serial_driver = ,

};當其驅動與裝置匹配時就會呼叫他的探測函式

static int s3c2440_serial_probe(struct platform_device *dev)

每乙個埠都有乙個描述它的結構體s3c24xx_uart_port 在 檔案linux/drivers/serial/samsuing.c

static struct s3c24xx_uart_port s3c24xx_serial_ports[config_serial_samsung_uarts] = 

},………………………………

}上面探測函式的具體工作是函式s3c24xx_serial_probe()來完成的

int s3c24xx_serial_probe(struct platform_device *dev,

struct s3c24xx_uart_info *info)

int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)

串列埠資料流分析:

在串列埠裝置模型建立中提到了三個操作函式集,uart_ops ,tty_fops,s3c24xx_serial_ops資料的流動便是這些操作函式間的呼叫,這些呼叫關係如下:

在對乙個裝置進行其他操作之前必須先開啟它,linux/drivers/char/tty_io.c

static const struct file_operations tty_fops = ;

static int tty_open(struct inode *inode, struct file *filp)

else

tty = tty_init_dev(driver, index, 0); //建立乙個tty_struct 並初始化

………………………………

}struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,int first_ok)

void initialize_tty_struct(struct tty_struct *tty,struct tty_driver *driver, int idx)

埠裝置開啟之後就可以進行讀寫操作了,這裡只討論資料的讀取,在檔案 linux/drivers/char/tty_io.c中,

static const struct file_operations tty_fops = ;

static ssize_t tty_read(struct file *file, char __user *buf, size_t count,

loff_t *ppos)

在linux/drivers/char/n_tty.c中:

struct tty_ldisc_ops tty_ldisc_n_tty = ;

static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,

unsigned char __user *buf, size_t nr)

else 

}………………………………

}使用者空間是從快取tty->read_buf中讀取資料讀的,那麼快取tty->read_buf中的資料有是從那裡來的呢?分析如下:

回到檔案 linux/drivers/serial/samsuing.c中,串列埠資料接收中斷處理函式實現如下:

這是串列埠最原始的資料流入的地方

static irqreturn_t  s3c24xx_serial_rx_chars(int irq, void *dev_id)

tty_flip_buffer_push(tty); //將讀取到的max_count個資料向上層傳遞。

out:

return irq_handled;

}void tty_flip_buffer_push(struct tty_struct *tty)

static void flush_to_ldisc(struct work_struct *work)

}上面呼叫的函式disc->ops->receive_buf在檔案linux/drivers/char/n_tty.c中實現

struct tty_ldisc_ops tty_ldisc_n_tty = ;

static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)

else 

………………………………

}………………………………

}到此,資料讀取的整個過程就結束了。可以看出資料讀取可以分為兩個階段,乙個階段是上層函式從環形快取區tty->read_buf 讀取資料,第二階段是底層函式將接收的資料考到環形快取區tty->read_buf 中。

Linux裝置驅動之《字元裝置驅動》

linux裝置中最大的特點就是裝置操作猶如檔案操作一般,在應用層看來,硬體裝置只是乙個裝置檔案。應用程式可以像操作檔案一樣對硬體裝置進行操作,如open close read write 等。下面是乙個字元裝置驅動程式的簡單實現test.c 模組分析 1.初始化裝置驅動的結構體 struct fil...

Linux裝置驅動之字元裝置驅動

一 linux裝置的分類 linux系統將裝置分成三種基本型別,每個模組通常實現為其中某一類 字元模組 塊模組或網路模組。這三種型別有 字元裝置 字元裝置是個能夠像位元組流 類似檔案 一樣被訪問的裝置,由字元裝置驅動程式來實現這種特性。字元裝置可以通過檔案系統節點來訪問,比如 dev tty1等。這...

linux裝置驅動 DM9000移植

一 開發環境 1 核心 linux 2.6.22.6 2 jz2440 3 ubuntu9.10 二 移植過程 1 新增標頭檔案在核心目錄下的 arch arm plat s3c24xx commom smdk.c檔案中新增 if defined config dm9000 defined conf...