1. Trang chủ
  2. » Giáo Dục - Đào Tạo

MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB

71 15 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 71
Dung lượng 5,33 MB

Cấu trúc

  • MỤC LỤC

  • HÌNH ẢNH VÀ BẢNG BIỂU

  • CHƯƠNG 1. TỔNG QUAN DEVICE DRIVER

    • 1.1. Cơ bản về driver trên Linux

      • 1.1.1. Định nghĩa Driver

      • 1.1.2. Vai trò và nhiệm vụ của Driver

      • 1.1.3. Mô hình phân lớp theo chiều dọc:

    • 1.2. Viết driver đầu tiên trên Linux

      • 1.2.1. Nạp động driver vào hệ thống

      • 1.2.2. Viết driver đầu tiên

      • 1.2.3. Biên dịch Driver đầu tiên:

    • 1.3. Lập trình C ở tầng nhân

      • 1.3.1. Ghi log thông điệp trong tầng nhân:

      • 1.3.2. Một số mở rộng của GCC ở tầng nhân:

      • 1.3.3. Sử dụng giá trị trả về cho các hàm ở tầng nhân:

      • 1.3.4. Kernel C chính là pure C:

    • 1.4. Linux character drivers

      • 1.4.1. Device file (device node):

      • 1.4.2. Device number:

      • 1.4.3. Cấu trúc của character driver:

      • 1.4.4. Cấp phát tĩnh Device Number:

      • 1.4.5. Cấp phát động Device number:

      • 1.4.6. Tạo device file

      • 1.4.7. Cấp phát bộ nhớ và khởi tạo thiết bị:

      • 1.4.8. Đăng kí entry point open và release:

      • 1.4.9. Đăng ký entry point read và write

  • CHƯƠNG 2. USB DEVICE DRIVER

    • 1.5. Cơ bản về USB

      • 1.5.1. Định nghĩa USB

      • 1.5.2. Chuẩn tín hiệu

      • 1.5.3. Mô hình mạng:

      • 1.5.4. Kịch bản hoạt động của USB

      • 1.5.5. Chế độ truyền của USB

      • 1.5.6. Quá trình nhận dạng thiết bị usb trên Linux

      • 1.5.7. Giải mã thông tin về thiết bị USB

  • TÀI LIỆU THAM KHẢO

  • PHỤ LỤC

Nội dung

TỔNG QUAN DEVICE DRIVER

C Ơ BẢN VỀ DRIVER TRÊN L INUX

Driver là phần mềm chứa lệnh hướng dẫn CPU tương tác với các thiết bị như chuột, bàn phím, ổ cứng, card mạng, loa và màn hình Chẳng hạn, máy tính có card Wifi nhưng nếu không cài đặt driver, bạn sẽ không thể sử dụng Wifi.

1.1.2 Vai trò và nhiệm vụ của Driver a) Vai trò của driver

Driver là cầu nối giữa hệ điều hành và phần cứng máy tính; nếu thiếu driver hoặc driver không tương thích, hệ điều hành sẽ không nhận diện được thiết bị, khiến máy tính không thể hoạt động.

Driver là trình điều khiển có nhiệm vụ quản lý và giám sát các thực thể dưới quyền của nó, như bus driver cho đường bus và device driver cho các thiết bị như chuột, bàn phím, màn hình, và đĩa cứng Tương tự như phi công điều khiển máy bay, driver có thể điều khiển phần cứng hoặc được quản lý bởi các phần cứng khác thông qua device controller Các controller như hard disk controller, display controller, và audio controller cũng cần driver để quản lý thiết bị kết nối, bao gồm các loại controller như IDE, PCI, USB, SPI, và I2C.

Hình 1.1 Tương tác giữa thiết bị và driver

Các device controller thường kết nối với CPU thông qua các đường bus như PCI, IDE, USB, SPI, v.v Trong vi điều khiển, CPU và device controller thường được tích hợp trên một chip, giúp giảm kích thước và chi phí, phù hợp với phát triển hệ thống nhúng Về nguyên tắc, các driver trên hệ thống máy tính cá nhân không có sự khác biệt lớn so với các driver trong vi điều khiển Hai nhiệm vụ chính của driver là quản lý giao tiếp giữa hệ điều hành và phần cứng, đồng thời đảm bảo rằng các thiết bị hoạt động hiệu quả trong hệ thống.

Các bus driver cung cấp giao diện đặc tả cho các giao thức phần cứng tương ứng.

Driver thiết bị nằm ở tầng dưới cùng trong mô hình phân lớp phần mềm của hệ điều hành, với nhiệm vụ chính là điều khiển các thiết bị cụ thể Chúng cung cấp giao diện trừu tượng cho người sử dụng, cho phép tương tác với các thiết bị thông qua tầng trên của hệ điều hành Một driver bao gồm hai phần quan trọng.

 Giao tiếp với thiết bị (Device-specific)

 Giao tiếp với hệ điều hành (OS-specific)

Hình 1.2 Các thành phần của driver thên Linux

Thành phần giao tiếp với thiết bị của driver là giống nhau trên tất cả các hệ điều hành, cho phép hiểu và giải mã thông tin về thiết bị, bao gồm chi tiết kỹ thuật, kiểu thao tác, hiệu năng và cách lập trình giao tiếp.

Thành phần giao tiếp với hệ điều hành (OS-specific) được liên kết chặt chẽ với các cơ chế của hệ điều hành, dẫn đến sự khác biệt rõ rệt giữa driver trên Linux, Windows và MacOS.

1.1.3 Mô hình phân lớp theo chiều dọc:

Trên hệ điều hành Linux, driver thiết bị đóng vai trò cung cấp giao diện gọi hàm hệ thống cho ứng dụng, tạo ra ranh giới giữa không gian nhân (kernel space) và không gian người dùng (user space) Mô hình phân tầng này thể hiện sự phân chia rõ ràng giữa các thành phần trong hệ thống.

Hình 1.3 Kiến trúc tổng quan nhân Linux

Tùy thuộc vào đặc trưng của driver với hệ điều hành, driver trên Linux được chia làm 3 loại (phân cấp theo chiều dọc):

 Driver hướng gói dữ liệu (Packet-orented or the network vertical)

 Driver hướng khối dữ liệu (Block-oriented or the storage vertical)

 Driver hướng byte/kí tự (Byte-oriented or the character vertical)

Packet-oriented hay network driver gồm 2 phần:

 Network interface card (NIC) device drivers hoặc đơn giản là network device driver (có thể là Ethernet,Wi-fi, hoặc bất kì mạng giao tiếp nào khác,

Block-oriented hay storage driver gồm 2 phần:

 File-system drivers để giải mã các định dạng khác nhau trên các phân vùng lưu trữ khác nhau (FAT, ext, …)

 Block device drivers cho các giao thức phần cứng ứng với các thiết bị lưu trữ khác nhau (IDE, SCSI, MTD, …).

Byte-oriented or character drivers are further sub-classified into categories such as tty drivers, input drivers, console drivers, frame-buffer drivers, and sound drivers, which correspond to various interfaces like RS232, PS/2, VGA, I2C, and SPI.

V IẾT DRIVER ĐẦU TIÊN TRÊN L INUX

Bài viết này hướng dẫn cách nạp driver vào hệ thống khi hệ điều hành đã được thực thi mà không cần biên dịch hay khởi động lại nhân Người đọc sẽ được làm quen với quy trình nạp động driver và cách xây dựng driver đầu tiên của mình.

1.2.1 Nạp động driver vào hệ thống

Các driver nạp động vào hệ thống thường được xây dựng dựa trên cơ chế modules và được biên dịch thành file có đuôi ko (kernel object) Mỗi hệ thống Linux quy định một vị trí để lưu trữ các modules đã biên dịch, thường là trong thư mục /lib/modules//kernel.

Phiên bản nhân hệ thống Linux hiện tại có thể được xác định bằng lệnh `uname -r` Để xem thông tin về các module có sẵn, bạn có thể tham khảo hình ảnh minh họa dưới đây.

Để quản lý các module trên hệ thống Linux, bạn có thể sử dụng các lệnh sau đây, cần thực hiện dưới quyền root trong thư mục /sbin Đầu tiên, để liệt kê các module đã được nạp, sử dụng lệnh `lsmod` Để nạp một module vào hệ thống, sử dụng `insmod `, lưu ý rằng các module phụ thuộc cần được nạp trước Nếu bạn muốn nạp một module cùng với các module phụ thuộc tự động, hãy sử dụng `modprobe ` Cuối cùng, để gỡ một module khỏi hệ thống, bạn có thể sử dụng lệnh `rmmod `.

Hình 1.5 Xem các module đã được nạp

Một driver không thể tự thực thi mà hoạt động như một thư viện được nạp và đăng ký các hàm bởi ứng dụng đang chạy Driver được viết bằng ngôn ngữ C nhưng không có hàm main() Do driver được nạp và liên kết với hệ điều hành, nó cần được biên dịch theo cách tương tự như biên dịch nhân hệ điều hành Các tệp header được sử dụng trong mã nguồn driver chỉ là những tệp mà nhân hệ điều hành cung cấp, không bao gồm các hàm của thư viện lập trình C thường được lưu trữ trong thư mục riêng.

Sau đây là mã nguồn cho một driver đơn giản đầu tiên trên linux:

MODULE_DESCRIPTION("A hello world LKM");

This function is called, when the module is loaded into the kernel */ static int init ModuleInit(void) { /*Constructor*/ printk("Hello, Kernel!\n"); return 0;

This function is called, when the module is removed from the kernel */ static void exit ModuleExit(void) { /*Destructor*/ printk("Goodbye, Kernel\n");

} module_init(ModuleInit); module_exit(ModuleExit);

Mã nguồn driver được lưu trong file ofd.c, trong đó không sử dụng các thư viện ứng dụng như stdio.h, mà thay vào đó là các thư viện tầng nhân như kernel.h Hàm printk() tương tự như printf(), nhưng thay vì xuất dữ liệu ra thiết bị chuẩn, nó ghi vào file log của kernel và cần các công cụ đặc biệt để truy cập.

1.2.3 Biên dịch Driver đầu tiên:

Trước khi biên dịch nên cài cái gói linux header, ta có thể sử dụng lệnh: sudo apt-get install linux-headers-$(uname -r)

Sau khi có mã nguồn C cho driver, bước tiếp theo là biên dịch để tạo file module với đuôi ko, cụ thể là ofd.ko Để thực hiện điều này, cần sử dụng phương pháp biên dịch ở tầng nhân, bao gồm việc viết một Makefile để đăng ký thư viện biên dịch từ mã nguồn nhân và đăng ký driver cần biên dịch.

Trước khi biên dịch driver trên Linux bằng Makefile, cần có mã nguồn nhân (kernel source) của hệ thống Giả sử mã nguồn nhân được cài đặt tại /usr/src/linux; nếu không, cần chỉ định vị trí của nó trong biến KERNEL_SOURCE trong Makefile.

Sau khi chuẩn bị mã nguồn driver (ofd.c) và Makefile trong cùng một thư mục, hãy sử dụng lệnh make để biên dịch driver Quá trình biên dịch thành công sẽ tạo ra file ofd.ko, sẵn sàng để nạp vào hệ thống.

Trước hết, ta tạo một file document tên là Makefile trong folder chứa mã nguồn C.

Có thể dùng lệnh touch document

Viết Makefile để biên dịch mã nguồn như sau: obj-m += mymodule.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

 Thẻ all chứa câu lệnh để biên dịch các module trong thư mục hiện tại.

 Thẻ clean chứa lệnh xóa tất cả các object file có trong thư mục hiện tại.

Ta tạo thêm file Kbuild nằm cùng thư mục với Makefile:

EXTRA_CFLAGS = -Wall obj-m = mymodule.o

Biến obj-m chỉ ra rằng: object file sẽ được biên dịch theo kiểu kernel module.

 Cờ -Wall cho phép trình biên dịch hiển thị tất cả các bản tin cảnh báo trong quá trình biên dịch.

Sau đó trong terminal gõ lệnh make để biên dịch ra file mymodule.ko Ta được kết quả như hình dưới.

Hình 1.6 Kết quả biên dịch file mymodule.ko

Ta có thể kiểm tra các module đã được nạp vào bằng lệnh ls

Hình 1.7 Kiểm tra các module đã được nạp vào bằng lệnh ls

Sử dụng Make file giúp biên dịch chương trình nhanh chóng và hiệu quả, đồng thời cho phép theo dõi các file đã được biên dịch để tránh việc biên dịch lại không cần thiết Bên cạnh đó, Make file còn hỗ trợ việc xóa file một cách dễ dàng.

Nạp module mymodule.ko vào hệ thống:

Dùng lệnh dmesgđể theo dõi quá trình hoạt động của module.

Gỡ kernel module ta dùng lệnh rmmod

Hình 1.9 Gỡ module khỏi kernel

L ẬP TRÌNH C Ở TẦNG NHÂN

Hàm printk in các thông điệp ra console, nhưng do device driver có thể gọi hàm này nhiều lần, dẫn đến hàng nghìn thông điệp được in ra trong khi kích thước của console có hạn Điều này khiến nhiều thông điệp quan trọng bị mất, gây khó khăn trong việc phân tích lỗi Để khắc phục, hàm printk lưu trữ tất cả các thông điệp vào một buffer trong kernel space, bất kể mức độ log của thông điệp Khác với việc in ra console, chỉ những thông điệp có mức log thấp hơn mức log của console mới được hiển thị Việc lưu trữ này rất hữu ích cho việc phân tích nguyên nhân gây ra lỗi.

1.3.1 Ghi log thông điệp trong tầng nhân:

Hàm xuất dữ liệu printf và printk có nhiều điểm tương đồng về tham số, nhưng trong lập trình tầng nhân, hàm printk không hỗ trợ các định dạng dữ liệu.

Hàm printk trong hệ điều hành không giống như hàm printf, vì nó không được thiết kế để xuất dữ liệu ra các thiết bị chuẩn Thay vào đó, printk hoạt động ngầm và thực thi như một thư viện, chỉ được kích hoạt từ tầng phần cứng hoặc ứng dụng Tất cả các lời gọi hàm printk sẽ ghi lại thông điệp vào một bộ đệm ở tầng nhân, sau đó tiến trình syslog ở tầng ứng dụng sẽ thu thập và điều hướng các thông điệp này đến các đầu ra xác định, chẳng hạn như file cấu hình.

Hàm printk sử dụng các macro như KERN_INFO để kết hợp với thông điệp, tạo thành một xâu Xâu này được phân loại theo loại thông điệp dựa vào ba ký tự đầu tiên Các macro này được định nghĩa trong thư viện linux/kernel.h.

#define KERN_EMERG "" /* system is unusable */

#define KERN_ALERT "" /* action must be taken immediately */

#define KERN_CRIT "" /* critical conditions */

#define KERN_ERR "" /* error conditions */

#define KERN_WARNING "" /* warning conditions */

#define KERN_NOTICE "" /* normal but significant condition */

#define KERN_DEBUG "" /* debug-level messages */

Dựa vào loại thông điệp (3 ký tự đầu tiên của xâu), tiến trình syslog trong không gian người dùng sẽ điều hướng thông điệp đến đích đã được cấu hình Một trong những đích chung cho tất cả thông điệp là file log /var/log/messages, do đó, tất cả các lời gọi hàm printk mặc định sẽ ghi thông điệp vào file này Ngoài ra, có thể cấu hình để xuất thông điệp ra các đầu ra khác, chẳng hạn như cổng nối tiếp (/dev/ttyS0) hoặc màn hình console, thường áp dụng cho thông điệp loại KERN_EMERG.

Tệp /var/log/messages không chỉ lưu trữ thông điệp từ nhân mà còn từ các tiến trình người dùng Để đọc nội dung của tệp này, cần sử dụng công cụ phù hợp Một số công cụ phổ biến bao gồm lệnh dmesg và Log File Viewer trên Ubuntu Lệnh dmesg cung cấp thông tin phân tích trực tiếp từ bộ đệm của nhân và hiển thị trên thiết bị đầu ra chuẩn.

Sử dụng lệnh dmesg để xem thông tin ghi log từ tầng nhân, kết hợp với lệnh tail giúp giới hạn số dòng hiển thị, do hệ thống ghi quá nhiều thông tin.

Hình 1.10 Xem các thông điệp được ghi log từ kernel

1.3.2 Một số mở rộng của GCC ở tầng nhân:

Bộ trình dịch GNU (GNU Compiler Collection - GCC) là một tập hợp trình biên dịch hỗ trợ nhiều ngôn ngữ lập trình Là một phần quan trọng của GNU toolchain, GCC được sử dụng rộng rãi như trình dịch tiêu chuẩn trên các hệ điều hành giống Unix, bao gồm Linux và Mac OS X.

Lập trình C ở tầng nhân (kernel C) tuân theo chuẩn C với các mở rộng của GCC, bao gồm các từ khóa đặc biệt như init và exit Những từ khóa này không ảnh hưởng đến mã nguồn khi driver được nạp động, mà chỉ có tác động khi driver được đính trước vào nhân hệ điều hành khi biên dịch Các hàm được đánh dấu init sẽ tự động được đặt trong vùng init của nhân và chỉ thực hiện một lần khi khởi động, giúp giải phóng bộ nhớ RAM Tương tự, các hàm exit sẽ được thực hiện khi hệ thống tắt Sự phối hợp giữa nhân và GCC mang lại hiệu quả tối ưu, lý do mà nhân Linux chỉ có thể được biên dịch bởi các trình biên dịch dựa trên GCC.

1.3.3 Sử dụng giá trị trả về cho các hàm ở tầng nhân:

Trong lập trình tầng nhân, việc xử lý giá trị trả về của hàm là rất quan trọng Mỗi hàm cần có cơ chế kiểm soát lỗi và trả về một số nguyên, biểu thị ý nghĩa cụ thể Khi xảy ra lỗi, hàm sẽ trả về giá trị âm, với dấu trừ trước một hằng số quy định mã lỗi được định nghĩa trong tệp tiêu đề kernel linux/errno.h Tệp này cũng chứa định nghĩa mã lỗi khác trong mã nguồn kernel như asm/errno.h, asm-generic/errno.h và asm-generic/errno-base.h.

Nếu hàm thực thi thành công, nó sẽ trả về giá trị 0, trừ khi cần cung cấp thêm thông tin Trong trường hợp này, hàm sẽ trả về một giá trị dương, thể hiện số lượng byte dữ liệu được truyền.

Lập trình C ở tầng nhân là lập trình C thuần, không sử dụng các thư viện chuẩn như stdio.h hay string.h Thay vào đó, các nhà phát triển nhân hệ điều hành cung cấp một tập hợp các hàm trong mã nguồn nhân, bao gồm hàm printk và nhiều hàm khác về xâu, bộ nhớ, nằm trong các thư mục như kernel, ipc, lib, và được định nghĩa trong các tệp tiêu đề trong thư mục include/linux Điều này giải thích tại sao mã nguồn nhân cần thiết khi biên dịch driver, thường được lưu trữ trong thư mục /usr/src/kernels/, nơi tương ứng với phiên bản nhân Linux của hệ thống Để cài đặt mã nguồn nhân, người dùng có thể sử dụng lệnh: sudo apt-get update -y và sudo apt-get install -y linux-source.

Hình 1.11 Cài đặt kernel source

L INUX CHARACTER DRIVERS

Khi bắt đầu học lập trình C, chúng ta được làm quen với việc đọc dữ liệu từ bàn phím và in ra màn hình mà không cần hiểu cấu tạo của chúng Điều này cho thấy có một lớp trừu tượng giúp che giấu sự phức tạp của các thiết bị vật lý, cho phép chúng ta dễ dàng tương tác với dữ liệu.

Câu trả lời cho vấn đề này có thể là các hàm scanf() và printf() trong thư viện C, nhưng đó chỉ là bề nổi của vấn đề Chúng ta cần đi sâu hơn để hiểu rõ toàn bộ khía cạnh của nó Nội dung cần khám phá sẽ bao gồm nhiều khía cạnh khác nhau liên quan đến việc sử dụng và ứng dụng của các hàm này.

 Khái niệm device file và ý nghĩa của device file.

 Ý nghĩa của device number – một thuộc tính quan trọng của device file.

 Cấu trúc chung của một character driver.

Trong kernel Linux, file được phân loại thành 6 loại chính: file thông thường, thư mục, pipe, socket, symbolic link và device file Kernel Linux tạo ra device file để làm cho các tiến trình tin rằng các char/block device thực chất chỉ là file thông thường Điều này cho phép các tiến trình thực hiện việc đọc/ghi dữ liệu từ thiết bị một cách tương tự như khi thao tác với file thông thường.

Tiến trình bắt đầu bằng việc gọi system call để tương tác với device file, và cũng có thể thực hiện việc này một cách gián tiếp thông qua các library call từ thư viện trung gian.

Next, the kernel will invoke an entry point of the corresponding device driver associated with the device file Each entry point essentially represents a function within the device driver When the device driver is integrated into the kernel, it registers these functions with the kernel, allowing the kernel to understand the purpose of each function Typically, there is a one-to-one correspondence between the kernel's system calls and the device driver's entry points.

 Cuối cùng, device driver sẽ hướng dẫn CPU giao tiếp với thiết bị.

Từ hình 1.12, chúng ta nhận thấy rằng:

 Một device driver có thể ứng với một hoặc nhiều device file.

 Một device driver có thể điều khiển một hoặc nhiều thiết bị.

 Một device file có thể sử dụng bởi nhiều tiến trình.

 Một tiến trình có thể cần dùng nhiều device file.

Hình 1.12 Kết nối giữa tiến trình và character device trong Linux

Device file hoạt động tương tự như các file thông thường với các thao tác như mở, đóng, ghi và đọc Tuy nhiên, kết quả từ những thao tác này không giống nhau Đối với file thông thường, nếu ghi dữ liệu A và sau đó đọc lại, bạn sẽ nhận được A Ngược lại, với device file, như audio device file, khi ghi dữ liệu, nó sẽ được gửi đến loa, trong khi đọc dữ liệu sẽ nhận được thông tin từ microphone.

Kernel sử dụng device number để biết device driver nào ứng với device file. Device number là một số gồm hai số: major number và minor number:

 Major number giúp Kernel nhận biết device driver nào tương ứng với device file.

 Minor number giúp device driver nhận biết nó sẽ phải điều khiển thiết bị nào, nếu như device driver đó đang điều khiển nhiều thiết bị.

Khi thực hiện lệnh “ls -l /dev” trên terminal, bạn sẽ thấy kết quả hiển thị thông tin về các thiết bị Ký tự đầu tiên trong cột thứ nhất có thể là “c” cho thiết bị ký tự (character device) hoặc “b” cho thiết bị khối (block device) Tên của file thiết bị được hiển thị ở cột thứ 10, thường có màu vàng, trong khi cột thứ 5 thể hiện số lớn (major number) và cột thứ 6 thể hiện số nhỏ (minor number) của file thiết bị.

Hình 1.13 Một số device file

Khi lắp driver thiết bị vào kernel, hàm khởi tạo sẽ đăng ký với kernel Linux các số thiết bị, bao gồm cặp Các cặp này có cùng số major, trong khi các số minor tạo thành một dải số tự nhiên liên tiếp, thường nằm trong khoảng từ 0 đến 63 Mặc dù giá trị minor number thường bắt đầu từ 0, nhưng điều này không phải là bắt buộc.

1.4.3 Cấu trúc của character driver:

Tương tự như các device driver khác, character driver (gọi tắt là char driver) gồm 2 phần:

 Phần OS specific gồm các nhóm hàm sau: o Hàm khởi tạo Hàm này chịu trách nhiệm:

 Yêu cầu kernel cấp phát device number.

 Yêu cầu kernel tạo device file.

 Yêu cầu kernel cấp phát bộ nhớ cho các cấu trúc dữ liệu của driver và khởi tạo chúng.

 Yêu cầu khởi tạo thiết bị vật lý.

 Đăng ký các hàm entry point với kernel.

Registering an interrupt handler involves defining a termination function that reverses the actions of the initialization function Key entry point functions include open(), release(), read(), write(), ioctl(), and mmap(), which are essential for managing device interactions effectively.

 Phần device specific gồm các nhóm hàm sau: o Nhóm các hàm khởi tạo/giải phóng thiết bị. o Nhóm các hàm đọc/ghi vào các thanh ghi của thiết bị.

 Đọc/ghi các thanh ghi dữ liệu.

 Lấy thông tin từ các thanh ghi trạng thái.

 Thiết lập lệnh cho các thanh ghi điều khiển. o Nhóm các hàm xử lý ngắt.

Dưới đây là nội dung của một tệp mã nguồn triển khai driver cho một thiết bị ký tự ảo, tương tự như tệp mymodule.c đã đề cập ở phần trước.

#define DRIVER_DESC "A sample character device driver"

/* ham khoi tao thiet bi */

/* ham giai phong thiet bị */

/* ham doc tu cac thanh ghi du lieu cua thiet bi */

/* ham ghi vao cac thanh ghi du lieu cua thiet bi */

/* ham doc tu cac thanh ghi trang thai cua thiet bi */

/* ham ghi vao cac thanh ghi dieu khien cua thiet bi */

/* ham xu ly tin hieu ngat gui tu thiet bi */

/*Hàm khởi tạo driver*/ static int _init vchar_driver_init(void)

/* cap phat bo nho co cac cau truc du lieu cua driver va khoi tao*/

/* khoi tao thiet bi vat lu */

/* dang ki cac entry point vơi kernel */

/* dang ki ham xu ly ngat */ printk(“Khoi tao vchar driver thanh cong\n”); return 0;

Static void exit vchar_driver_exit(void)

/* Huy dang ky xu li ngat */

/* Huy dang ky entry point voi kernel */

/* giai phong thiet bi vat ly */

/* giai phong bo nho da cap phat */

Printk(“Ket thuc vchar driver\n”);

/*=========== OS specific – END =========*/ module_init(vchar_driver_init); module_exit(vchar_driver_exit);

MODULE_LICENSE("GPL"); /* giay phep su dung cua module */

MODULE_AUTHOR(DRIVER_AUTHOR); /* tac gia cua module */

The module description outlines the functionality of the module, while the module version specifies its version details Additionally, the supported device type is indicated as "testdevice," highlighting the compatibility of the module with this specific device.

1.4.4 Cấp phát tĩnh Device Number: Để khởi tạo char driver, một trong những bước mà chúng ta cần thực hiện đó là yêu cầu kernel cấp phát device number Có 2 phương pháp cấp phát device number: cấp phát động và cấp phát tĩnh Trước khi tìm hiểu phương pháp cấp phát tĩnh, ta cần tìm hiểu xem Linux kernel biểu diễn device number như thế nào? a) Biểu diễn device number:

Trong Linux kernel, cấu trúc dev_t được sử dụng để biểu diễn số thiết bị với kích thước 32 bit, trong đó 12 bits dành cho số major và 20 bits cho số minor Ngoài ra, kernel cũng cung cấp các hàm và macro hỗ trợ việc thao tác với biến kiểu dev_t.

MAJOR(dev_t dev ) Trả về major number từ device number

MINOR (dev_t dev ) Trả về minor number từ device number

The MKDEV function combines the major and minor numbers to create an unsigned device number The function imajor retrieves the major number from a given inode structure, which describes a device file, while the iminor function returns the minor number from the same inode structure.

Bảng 1.1 Một số hàm và marco làm việc với device number b) Cấp phát tĩnh device number:

Trong phương pháp này, chúng ta sẽ chọn một giá trị làm major number Để xác định giá trị phù hợp, hãy sử dụng lệnh `cat /proc/devices`, trong đó cột đầu tiên liệt kê các major number đã được sử dụng bởi các driver khác Do đó, cần tránh chọn những số này Ngoài những số đã được sử dụng, bạn có thể chọn bất kỳ số nào trong khoảng từ 0 đến (2^12 - 1) làm major number.

Hình 1.14 Danh sách các thiết bị đang hoạt động trong hệ thống

USB DEVICE DRIVER

Ngày đăng: 22/12/2021, 05:46

HÌNH ẢNH LIÊN QUAN

Hình 1.1 Tương tác giữa thiết bị và driver - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.1 Tương tác giữa thiết bị và driver (Trang 8)
Hình 1.2 Các thành phần của driver thên Linux - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.2 Các thành phần của driver thên Linux (Trang 9)
Hình 1.3 Kiến trúc tổng quan nhân Linux - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.3 Kiến trúc tổng quan nhân Linux (Trang 10)
Hình 1.4 Xem các module có sẵn trên Linux - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.4 Xem các module có sẵn trên Linux (Trang 11)
Hình 1.5 Xem các module đã được nạp - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.5 Xem các module đã được nạp (Trang 12)
Hình 1.6 Kết quả biên dịch file mymodule.ko - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.6 Kết quả biên dịch file mymodule.ko (Trang 15)
Hình 1.8 Nạp module - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.8 Nạp module (Trang 16)
Hình 1.9 Gỡ module khỏi kernel - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.9 Gỡ module khỏi kernel (Trang 16)
Hình 1.11 Cài đặt kernel source - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.11 Cài đặt kernel source (Trang 20)
Hình 1.12 Kết nối giữa tiến trình và character device trong Linux - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.12 Kết nối giữa tiến trình và character device trong Linux (Trang 22)
Hình 1.13 Một số device file - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.13 Một số device file (Trang 23)
Bảng 1.1 Một số hàm và marco làm việc với device number - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Bảng 1.1 Một số hàm và marco làm việc với device number (Trang 26)
Hình 1.14 Danh sách các thiết bị đang hoạt động trong hệ thống - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.14 Danh sách các thiết bị đang hoạt động trong hệ thống (Trang 27)
Hình 1. 15  Cấp phát tĩnh device number - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1. 15 Cấp phát tĩnh device number (Trang 28)
Hình 1.17 Tạo device file bằng công cụ mknod - MÔN HỆ ĐIỀU HÀNH đề tài lập trình driver cho USB
Hình 1.17 Tạo device file bằng công cụ mknod (Trang 30)

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w