linux驅動學習之LED篇(二)

2021-06-17 21:39:39 字數 4677 閱讀 2852

上篇講了下led的原理,這篇就開始寫**:

如果是新手我建議先把《linux裝置驅動開發詳解》的裝置驅動那章看下或者網上了解下裝置驅動的模版,不然驅動的整體結構不懂的話就比較糾結了。

#include /* 所有核心模組必須有的標頭檔案 */

#include /* 所有 核心模組必須有的標頭檔案*/

#include /* printk() */

#include /* struct fops */

#include /* error codes */

#include /* cdev_alloc()  */

#include /* ioremap()  */

#include /* request_mem_region() */

#include /*用於產生 ioctl command  */

#ifndef __kernel__

#include /* user space head file for macro _io() to generate ioctl command */

#endif

#define drv_author             "yangxu"

#define drv_desc                  "s3c24xx led driver"

#define dev_name                  "led"

#define led_num                     4

#ifndef led_major

#define led_major   

0  /*主裝置號*/

#endif

#define drv_major_ver             1

#define drv_minor_ver              0

#define drv_rever_ver             0

#define disable                   0

#define enable                    1

#define gpio_input                   0x00

#define gpio_output               0x01

#define platdrv_magic          0x60

#define led_off                   _io (platdrv_magic, 0x18)/*定義的魔數,防止和其他巨集重複,有興趣可以研究下*/

#define led_on                    _io (platdrv_magic, 0x19)

#define s3c_gpb_base              0x56000010

#define gpbcon_offset             0

#define gpbdat_offset              4

#define gpbup_offset                8

#define s3c_gpb_len               0x10        /* 0x56000010~0x56000020  */

int led[led_num] = ;  /* four leds use gpb5,gpb6,gpb8,gpb10 我的板子是這些埠,你們的如果不一樣自己查開發板的底板原理圖*/

static void __iomem *s3c_gpb_membase;/*__iomem是linux2.6.9核心中加入的特性。是用來個表示指標是指向乙個i/o的記憶體空間。主要是為了驅動程式的通用性考慮。由於不同的cpu體系結構對i/o空間的表示可能不同。當使用__iomem時,編譯器會忽略對變數的檢查(因為用的是void __iomem)。若要對它進行檢查,當__iomem的指標和正常的指標混用時,就會發出一些警告。*/

#define s3c_gpio_write(val, reg) __raw_writel((val), (reg)+s3c_gpb_membase) /*對i/o的寫操作*/

#define s3c_gpio_read(reg)       __raw_readl((reg)+s3c_gpb_membase)           /*對i/o的讀操作*/

int dev_count = array_size(led); /*巨集array_size,用來求裝置結構體中裝置的個數*/

int dev_major = led_major;

int dev_minor = 0;

int debug = disable;

static struct cdev      *led_cdev; /*cdev結構體可以用來描述乙個字元裝置*/

static int s3c_hw_init(void)/*記憶體和gpio初始化函式供後來的led裝置新增函式的呼叫*/

if( !(s3c_gpb_membase=ioremap(s3c_gpb_base, s3c_gpb_len)) )

/*用來將i/o記憶體資源的物理位址對映到cpu核心虛位址空間,因為cpu並不能直接使用硬體指定的實體地址直接訪問i/o。*/

for(i=0; i

/* 設定gpbcon埠為輸入或輸出模式  */

gpb_con = s3c_gpio_read(gpbcon_offset);

/*讀取gpbcon暫存器的各個位的狀態*/

gpb_con &= ~(0x3<<(2*led[i]));

/* 清零要修改的位*/

gpb_con |= gpio_output<<(2*led[i]);

/* 設定gpio為output模式 */

s3c_gpio_write(gpb_con, gpbcon_offset);

/*寫入暫存器*/

/ * gpbup暫存器設定,這裡用不到上拉電阻,所以我們禁用*/

gpb_up = s3c_gpio_read(gpbup_offset);

//gpb_up &= ~(0x1<

/* 設定gpio口的電平,來控制燈的亮滅,開始讓它滅*/

gpb_dat = s3c_gpio_read(gpbdat_offset);

//gpb_dat &= ~(0x1<

/*改變燈狀態的函式*/

static void turn_led(int which, unsigned int cmd)

static int led_release(struct inode *inode, struct file *file)/*如果在應用程式空間呼叫close函式,就會呼叫led_release,關閉節點*/

static void print_help(void)

/*沒什麼用列印一些資訊*/

static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

return 0;

}static struct file_operations led_fops =;

static int __init s3c_led_init(void) /*led裝置的新增函式*/

if (0 != dev_major) /*  如果我們開始設定了主裝置號這裡就可以靜態使用了 */

else

/*  分配失敗 */

if (result < 0)

led_cdev->owner = this_module;

cdev_init(led_cdev, &led_fops);   /*cdev_init()函式用於初始化cdev的成員,並建立cdev和file_operations之間的連線*/

result = cdev_add(led_cdev, devno, dev_count);/*向系統新增乙個cdev完成字元裝置的註冊*/

if (0 != result)

printk(kern_err "s3c %s driver[major=%d] version %d.%d.%d installed successfully!\n",

dev_name, dev_major, drv_major_ver, drv_minor_ver,drv_rever_ver);

return 0;

error:

printk(kern_err "s3c %s driver installed failure.\n", dev_name);

cdev_del(led_cdev);

unregister_chrdev_region(devno, dev_count);

return result;}

static void __exit s3c_led_exit(void)   /*led裝置的解除安裝函式*/

/* these two functions defined in */

module_init(s3c_led_init);

module_exit(s3c_led_exit);

module_param(debug, int, s_irugo);

module_param(dev_major, int, s_irugo);

module_author(drv_author);

module_description(drv_desc);

module_license("gpl");

linux驅動之 led驅動

練手,第乙個字元驅動.用模組載入方法 華清遠見 嵌入式linux裝置驅動開發詳解 的 拿來改的.編譯過程發現很多錯誤.最後發現 這本書帶的驅動 都是基於linux2.4的.目前我用的linux2.6,部分需要做修改.我的板子是 友善之臂的 2410.vmware ubuntu nfs交叉編譯 首先 ...

(一)linux驅動之led

我採用的是正點原子的linux板子,覺得原子的板子還是很不錯的。由於正點原子使用的設計是通過電平拉低是點亮led,拉高則是關閉led。1.構建驅動載入和解除安裝函式 2.申請裝置號,裝置號可以指定,或者讓系統自動分配 3.初始化建立的cdev結構體。4.最後自動建立裝置節點 include incl...

Linux驅動學習之篇外

一些有用的tricks 隨時補充 sys firmware devicetree base,這個節點也會被鏈結到 proc device tree proc interrupts proc irq irq num sys class gpio 需要通過gpio export 或者gpio expor...