[課程筆記]Linux Driver正點原子課程筆記1 & 2 - Linux驅動開發 & 字符設備驅動開發基礎實驗

Posted by John on 2021-01-24
Words 903 and Reading Time 3 Minutes
Viewed Times

〖想觀看更多課程筆記,至[課程筆記]課程筆記系列總覽可以看到目前已發布的所有文章!〗

Course 1 - Linux驅動開發

驅動開發思維

為何需要Linux driver?

  • 直接在Linux下操作register不現實,太複雜也不安全
  • Linux具有各種驅動框架(driver framework),使得各種設置能夠依照一訂的規範進行開發

Linux下一切皆文件,而所有的driver都放置在/dev/xxx下,可以透過fops(file operation)來操作(打開、關閉、讀寫)

新版的Linux下supoort device tree,是一個.dts,記錄devices information,kernel會去分析.dts文件了解有哪些設備

驅動開發分類

linux 驅動分成三大類

  1. char device driver: 字符設備驅動,按照字符依序存取,大部分的驅動都是這種,e.g. i2c
  2. block device driver: 能以固定大小長度傳送和轉移,可以不需要按照順序操作,e.g. SD card
  3. network device driver: 網路設備驅動,e.g. wifi

一個設備可以同時是不同類型的驅動,例如USB WIFI, SDIO WIFI是network device driver但同時也是char device driver

Course 2 - 字符設備驅動開發基礎實驗

應用程序和驅動的交互原理

驅動就是用來和device溝通的程式。Linux驅動編譯除了要編寫一個driver外,還要編寫一個測試應用程式(application)

  • 單晶片機下驅動和應用是放在一個文件內
  • Linux下驅動和應用是完全分開的,所以此時就牽扯到user space & kernel space

以下部分內容引用自linux内存管理—用户空间和内核空间

关于虚拟内存有三点需要注意:

  • 4G的进程地址空间被人为的分为两个部分—用户空间与内核空间。用户空间从0到3G(0xc0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间的虚拟地址。例外情况只有用户进程进行系统调用(代表用户进程在内核态执行)等时刻可以访问到内核空间。
  • 用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程变化,是固定的。内核空间地址有自己对应的页表,用户进程各自有不同的页表。
  • 每个进程的用户空间都是完全独立、互不相干的。

user space & kernel space: 為了安全性而做的區隔

  • linux kernel & driver在kernel space執行
  • application跑在user space

因此當app要access kernel resource時有三種方式

  • system call: 可以透過API來間接調用system call,例如POSIX & C Lib
  • interrupt
  • trap: software interrupt

每個system call會有一個id,例如在/arch/arm64/include/asm/unistd32.h中可以看到system call和對應的id

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* /arch/arm64/include/asm/unistd32.h */
#ifndef __SYSCALL
#define __SYSCALL(x, y)
#endif

#define __NR_restart_syscall 0
__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
#define __NR_exit 1
__SYSCALL(__NR_exit, sys_exit)
#define __NR_fork 2
__SYSCALL(__NR_fork, sys_fork)
#define __NR_read 3
__SYSCALL(__NR_read, sys_read)
#define __NR_write 4
__SYSCALL(__NR_write, sys_write)
#define __NR_open 5
__SYSCALL(__NR_open, compat_sys_open)
...

要使用system call,必須要先透過trap觸發軟體中斷進入kernel mode,然後還需要指定system call id,然後整個流程大致如下圖:

字符設備驅動開發流程

Linux下一切皆文件(/dev/xxx),application可以透過open()來打開設備,並透過read(), write()來存取設備, 並透過close()來關閉

因此在設計驅動的時候,需要撰寫對應的open(), close(), write()… function,這些被記錄在file_operations的struct內向外提供


>