Cấu trúc chương trình character device driver dạng 1:

Một phần của tài liệu document (Trang 34 - 40)

I. Lập trình mã lệnh trong character driver:

1. Cấu trúc chương trình character device driver dạng 1:

/*Bước 1: Khai báo thư viện cho các hàm dùng trong chương trình, thư viện dùng trong kernel space khác với thư viện dùng trong user space. Thư viện trong driver là những hàm, biến, hằng số, ... được định nghĩa sẵn và hầu hết được lưu trong thư mục linux/ trong cấu trúc mã nguồn của linux. Do đó khi khai báo, chúng ta phải chỉ rõ đường dẫn đến thư mục này */

#include <linux/module.h> //Thư viện thứ nhất trong thư mục linux

#include <linux/fs.h> #include <linux/cdev.h> #include <asm/uaccess.h> ......

/*Bước 2: Định nghĩa những hằng số cần dùng trong chương trình driver*/

#define ... ...

/*Bước 3: Khai báo số định danh thiết bị (Device number); Cấu trúc (file structure); Cấu trúc (file operations); */

int device_devno;//Khai báo biến lưu số định danh thiết bị

struct cdev device_cdev;//Khai báo biến lưu cấu trúc tập tin

struct file_operations device_fops; //Khai báo biến lưu cấu trúc lệnh

/*Bước 4: Khai báo những biến, cấu trúc cần dùng trong chương trình driver*/

unsigned int variable_0; //Những biến này được định nghĩa tương tự trong

unsigned long variable_1;//mã lệnh C, và C++ struct clk *device_clock_0;//

....

/*Bước 5: Khai báo, định nghĩa những hàm con, chương trình con được sử dụng trong driver*/

/*Chương trình con thứ nhất, có hai tham số parameter_0 và parameter_1 cùng kiểu int*/

void sub_program_0 (int parameter_0, int parameter_1) {

/*Những lệnh thao tác cho chương trình con*/

lệnh_0; lệnh_1; lệnh_2; }

/*Hàm thứ nhất, trả về kiểu int, hai tham số con trỏ parameter_0 và parameter_1 kiểu int*/

int func_0 (int *parameter_0, int *parameter_1) {

/*Các thao tác lệnh cho hàm*/

lệnh_0; lệnh_1; lệnh_2;

}

/*Bước 6: Định nghĩa hàm init cho driver, hàm init là hàm được thực thi đầu tiên khi thực hiện cài đặt driver vào hệ thống linux bằng lệnh shell insmod driver_name.ko*/

/*Hàm init có một vai trị quan trọng trong lập trình driver. Ban đầu hàm sẽ gọi thực thi các hàm xác định số định danh thiết bị; Cập nhật các thông số của cấu trúc tập tin, cấu trúc lệnh; Đăng ký các cấu trúc vào hệ thống linux; Khởi tạo các thông số điều khiển ban đầu cho các thiết bị ngoại vi mà driver điều khiển*/ /*Hàm init có kiểu dữ liệu trả về dạng int, static trong trường hợp này nghĩa là hàm init chỉ dùng riêng cho driver sở hữu*/

static int __init at91adc_init (void) {

/*Khai báo biến lưu giá trị trả về của hàm*/

int ret;

/*Xác định số định danh động cho thiết bị, tránh trường hợp bị trùng khi cài đặt với các driver thiết bị khác đã có trong hệ thống*/

//Chỉ đến địa chỉ biến lưu số định danh đầu tiên tìm được;

ret = alloc_chrdev_region ( &device_devno 0, //Số Minor đầu tiên yêu cầu;

1, //Số thiết bị yêu cầu;

“device_name” );//Tên thiết bị muốn đăng ký; /*Kiểm tra mã lỗi khi thực thi hàm alloc_chrdev_region()*/

if (ret < 0) {

//In thông báo lỗi khi thực hiện xác định số định danh thiết bị;

printk (KERN_INFO “Device_name: Device number allocate fail”);

ret = -ENODEV;//Trả về mã lỗi cho biến ret;

return ret;//Trả về mã lỗi cho hàm init;

}

/*Khởi tạo thiết bị với số định danh đã xác định, yêu cầu hệ thống dành một vùng nhớ lưu driver thiết bị sắp được tạo ra;*/

cdev_init ( &device_cdev, //Trỏ đến cấu trúc tập tin đã được định nghĩa;

device_devno, //Số định danh thiết bị đã được xác định;

1 ); //Số thiết bị muốn đăng ký vào hệ thống; /*Chập nhật những thông tin cần thiết cho cấu trúc tập tin vừa được hệ thống dành ra*/

device_cdev.owner = THIS_MODULE; /*Cập nhật người sở hữu cấu trúc tập tin*/

device_cdev.ops = &device_fops; /*Cập nhật cấu trúc lệnh đã được định nghĩa*/

/*Đăng ký thiết bị vào hệ thống */

ret = cdev_add ( &device_cdev, //Trỏ đến cấu trúc tập tin đã được khởi tạo;

device_devno, //Số định danh thiết bị đã được xác định;

1 ); //Số thiết bị muốn đăng ký;

/*Kiểm tra lỗi trong quá trình đăng ký thiết bị vào hệ thống*/

if (ret < 0) {

//In thông báo khi lỗi xuất hiện

printk(KERN_INFO "Device: Device number allocation failed\n");

ret = -ENODEV; //Trả về mã lỗi cho biến; return ret;//Trả về mã lỗi cho hàm;

}

/*Thực hiện các công việc khởi tạo thiết bị vật lý do driver điều khiển*/

...

//Trả về mã lỗi 0 khi quá trình thực thi hàm init khơng có lỗi;

return 0; }

/*Bước 7: Khai báo và định nghĩa hàm exit, hàm exit là hàm được thực hiện ngay trước khi driver được tháo gỡ khỏi hệ thống bằng lệnh shell rmmod device.ko; Những tác vụ bên trong hàm exit được lập trình nhằm khơi phục lại trạng thái hệ thống trước khi cài đặt driver. Chẳng hạn như giải phóng vùng nhớ, timer, vơ hiệu hóa các nguồn phát sinh ngắt, ...*/

static void __exit device_exit (void) {

/*Các lệnh giải phóng vùng nhớ sử dụng trong driver*/

...

/*Các lệnh giải phóng nguồn ngắt, timer, ...*/

...

/*Tháo thiết bị ra khỏi hệ thống bằng hàm*/

unregister_chrdev_region( device_devno, /*Số định danh đầu tiên nhóm thiết bị;*/

1); //Số thiết bị cần tháo gỡ; /*In thông báo driver thiết bị đã được tháo ra khỏi hệ thống*/

printk(KERN_INFO "device: Unloaded module\n"); }

/*Bước 8: Khai báo hàm open, đây là hàm được thực thi ngay sau khi lệnh open trong user space thực thi. Những lệnh chứa trong hàm này thông thường dùng cập nhật dữ liệu ban đầu cho chương trình driver, khởi tạo mơi trường hoạt động ban đầu để hệ thống làm việc ổn định*/

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

{

/*Nơi lập trình các lệnh khởi tạo hệ thống*/

return 0; }

/*Bước 9: Khai báo và định nghĩa hàm release, đây là hàm được thực thi ngay trước khi driver bị đóng bởi hàm close trong user space*/

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

{

/*Nơi thực thi những lệnh trước khi driver bị đóng, khơng cịn sử dụng*/

return 0; }

/*Bước 10: Khai báo các hàm read(), write(), ioctl() trong hệ thống khi cần sử dụng*/ /*Hàm read() đọc thơng tin từ driver qua chương trình trong user*/

static ssize_t device_read (struct file *filp, char __iomem *buf, size_t bufsize, loff_t *f_pos) {

/*Định nghĩa các tác vụ hoạt động trong hàm read, để truy cập lấy thông tin từ thiết bị vật lý*/

... }

/*Hàm write() ghi thông tin từ user qua driver*/

static ssize_t device_write (struct file *filp, char __iomem *buf, size_t bufsize, loff_t *f_pos) {

/*Định nghĩa các tác vụ hoạt động trong hàm write(), để truy cập lấy thơng tin từ chương trình ứng dụng trong user*/

... }

/*Hàm ioctl định nghĩa các trạng thái lệnh thực thi theo số định danh lệnh từ chương trình ứng dụng bên user*/

static int

gpio_ioctl (struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) {

/*Khai báo biến lưu mã lỗi trả về cho hàm giao diện ioctl()*/

int retval = 0;

switch (cmd) { case LENH_0: /*Lệnh 0 được thực thi*/ break; case LENH_1: /*Lệnh 1 được thực thi*/ break; default:

/*Có thể thơng báo, khơng có lệnh nào để thực thi*/

retval = -EINVAL; break;

}

return retval; }

/*Bước 11: Gán các con trỏ hàm giao diện chuẩn vào cấu trúc lệnh file structure*/

struct file_operations gpio_fops = { .read = device_read, .write = device_write, .ioctl = device_ioctl, .open = device_open, .release = device_release, };

/*Bước 12: Gán các hàm exit và init vào hệ thống driver*/

Một phần của tài liệu document (Trang 34 - 40)

Tải bản đầy đủ (PDF)

(91 trang)