全志A33linuxled驅動程式設計(附實測參考程式碼)
開發平臺
* 芯靈思SinlinxA33開發板
淘寶店鋪: https://sinlinx.taobao.com/
嵌入式linux 開發板交流 QQ:641395230
實驗原理
在芯靈思開發板上,沒有led燈模組,只能通過引腳電平觀察: 這裡我選擇LS-INT引腳。
全志A33一共有10組IO口,每組IO有9個相關功能控制器,LS-INT屬於PB7,相關暫存器如圖
本次實驗只用到這兩個暫存器,在程式中命名為gpio_con,gpio_dat ,設定為輸出引腳。
- 1)註冊 class_register(class) 將class註冊到核心中。呼叫前,必須手動分配class記憶體;呼叫後必須設定class的name等引數註冊 class_create(owner,name) 建立class並將class註冊到核心中。返回值為class結構體指標。登出 void class_unregister(struct class cls) 登出class,與class_register()配對使用。登出void class_destroy(struct class cls) 登出class,與class_create()配對使用核心中定義了struct class結構體顧名思義,一個struct class結構體型別變數對應一個類,核心同時提供了class_create(…)函式,可以用它來建立一個類,這個類存放於sysfs下面,一旦建立好了這個類,再呼叫device_create(…)函式來在/dev目錄下建立相應的裝置節點。這樣,載入模組的時候,使用者空間中的udev會自動響應device_create(…)函式,去/sysfs下尋找對應的類從而建立裝置節點.
- 2)void ioremap(unsigned long phys_addr , unsigned long size , unsigned long flags)用mmap對映一個裝置意味著使使用者空間的一段地址關聯到裝置記憶體上,這使得只要程式在分配的地址範圍內進行讀取或寫入實際上就是對裝置的訪問。解除對映void iounmap(void addr)//取消ioremap所對映的IO地址
-
3)register_chrdev(unsigned int major, const char name,const struct file_operations fops);
但其實這個函式是linux版本2.4之前的註冊方式,它的原理是:- (1)確定一個主裝置號,如果major=0,則會自動分配裝置號
- (2)構造一個file_operations結構體, 然後放在chrdevs陣列中
- (3)註冊:register_chrdev,cat /proc/devices檢視核心中已經註冊過的字元裝置驅動(和塊裝置驅動),注意這裡並不是驅動檔案裝置節點!
- 4) Linux使用file_operations結構訪問驅動程式的函式,這個結構的每一個成員的名字都對應著一個呼叫
- 5) class_device_create() 呼叫class_create為該裝置建立一個class,再為每個裝置呼叫 class_device_create建立對應的裝置。大致用法如下:struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “my_device”);這樣的module被載入時,udev daemon就會自動在/dev下建立my_device裝置件。
總體程式碼框架
1)先要有file_operations先要有引腳初始化函式myled_init(void),在myled_init裡面註冊class並將class類註冊到核心中
建立裝置節點,初始化引腳已經將暫存器地址對映到虛擬記憶體中,最後呼叫module_init(myled_init)驅動的載入就靠它
2)建立這個file_operations結構體
static struct file_operations myled_oprs = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
下面就圍繞這個結構體寫函式led_write() led_open() led_release()
3)最後要登出裝置
附實測程式碼,參考下
LED驅動程式碼:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
static int major;
static struct class *led_class;
volatile unsigned long *gpio_con = NULL;
volatile unsigned long *gpio_dat = NULL;
static int led_open (struct inode *node, struct file *filp)
{
/* PB7 - 0x01C20824 */
if (gpio_con) {
printk("ioremap 0x%x
", gpio_con);
}
else {
return -EINVAL;
}
return 0;
}
static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off)
{
unsigned char val;
copy_from_user(&val, buf, 1);
if (val)
{
*gpio_dat |= (1<<7);
}
else
{
*gpio_dat &= ~(1<<7);
}
return 1;
}
static int led_release (struct inode *node, struct file *filp)
{
printk("iounmap(0x%x)
", gpio_con);
iounmap(gpio_con);
return 0;
}
static struct file_operations myled_oprs = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int myled_init(void)
{
major = register_chrdev(0, "myled", &myled_oprs);
led_class = class_create(THIS_MODULE, "myled");
device_create(led_class, NULL, MKDEV(major, 0), NULL, "ledzzzzzzzz");
gpio_con = (volatile unsigned long *)ioremap(0x01C20824, 1); //0x01C20824
gpio_dat = gpio_con + 4; //0x01C20834
*gpio_con &= ~(7<<28);
*gpio_con |= (1<<28);
*gpio_dat &= ~(1<<7);
return 0;
}
APP程式碼:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
static int major;
static struct class *led_class;
volatile unsigned long *gpio_con = NULL;
volatile unsigned long *gpio_dat = NULL;
static int led_open (struct inode *node, struct file *filp)
{
/* PB7 - 0x01C20824 */
if (gpio_con) {
printk("ioremap 0x%x
", gpio_con);
}
else {
return -EINVAL;
}
return 0;
}
static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off)
{
unsigned char val;
copy_from_user(&val, buf, 1);
if (val)
{
*gpio_dat |= (1<<7);
}
else
{
*gpio_dat &= ~(1<<7);
}
return 1;
}
static int led_release (struct inode *node, struct file *filp)
{
printk("iounmap(0x%x)
", gpio_con);
iounmap(gpio_con);
return 0;
}
static struct file_operations myled_oprs = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int myled_init(void)
{
major = register_chrdev(0, "myled", &myled_oprs);
led_class = class_create(THIS_MODULE, "myled");
device_create(led_class, NULL, MKDEV(major, 0), NULL, "ledzzzzzzzz");
gpio_con = (volatile unsigned long *)ioremap(0x01C20824, 1); //0x01C20824
gpio_dat = gpio_con + 4; //0x01C20834
*gpio_con &= ~(7<<28);
*gpio_con |= (1<<28);
*gpio_dat &= ~(1<<7);
return 0;
}
Makefile程式碼:
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* ledtest on
* * ledtest off
* */
int main(int argc, char **argv)
{
int fd;
unsigned char val = 1;
fd = open("/dev/ledzzzzzzzz", O_RDWR);
if (fd < 0)
{
printf("can`t open!
");
}
if (argc != 2)
{
printf("Usage :
");
printf("%s <on|off>
", argv[0]);
return 0;
}
if (strcmp(argv[1], "on") == 0)
{
val = 1;
}
else
{
val = 0;
}
write(fd, &val, 1);
return 0;
}
相關文章
- 領域驅動設計最佳實踐--程式碼篇
- 程式設計模式-表驅動程式設計程式設計設計模式
- 領域驅動設計的參考建議 | heise Devdev
- 模擬考試參考程式碼
- 事件驅動程式設計事件程式設計
- Laravel最佳實踐–事件驅動程式設計Laravel事件程式設計
- Laravel 最佳實踐 -- 事件驅動程式設計Laravel事件程式設計
- Laravel最佳實踐 -- 事件驅動程式設計Laravel事件程式設計
- POCO庫中文程式設計參考指南(8)豐富的Socket程式設計程式設計
- Global.asa程式設計完全參考手冊程式設計
- ASP.NET中Cookie程式設計簡明參考ASP.NETCookie程式設計
- POCO庫中文程式設計參考指南(1)總覽程式設計
- linux驅動程式設計(轉)Linux程式設計
- 全志 A64開發板設定qt程式自啟動QT
- 《Java 程式設計任務驅動式實訓教程》pdf,附下載連結Java程式設計
- 程式設計師勵志名言程式設計師
- Android程式碼規範參考指南Android
- POCO庫中文程式設計參考指南(9)Poco::Net::DNS程式設計DNS
- POCO庫中文程式設計參考指南(7)Poco::Net::DatagramSocket程式設計
- POCO庫中文程式設計參考指南(6)Poco::Timestamp程式設計
- POCO庫中文程式設計參考指南(3)Poco::Net::Socket程式設計
- 程式設計技巧之-表驅動法程式設計
- 驅動篇——核心程式設計基礎程式設計
- Android事件驅動程式設計(二)Android事件程式設計
- Android事件驅動程式設計(三)Android事件程式設計
- Android事件驅動程式設計(一)Android事件程式設計
- 參考設計先行,浪潮資訊推動全液冷冷板伺服器普惠伺服器
- C#程式設計實驗考試C#程式設計
- 程式設計師勵志語錄程式設計師
- 程式設計師勵志小故事程式設計師
- 轉職成為TypeScript程式設計師的參考手冊TypeScript程式設計師
- POCO庫中文程式設計參考指南(11)如何使用Reactor框架?程式設計React框架
- Jupiter程式碼審查工具使用參考
- Cheeper:《CQRS By Example》一書的參考程式碼開源實現
- WDM驅動程式設計之設計開發篇 (轉)程式設計
- 虛擬裝置驅動程式的設計與實現 (轉)
- PHP程式設計考試PHP程式設計
- 一組動物主題APP介面設計參考APP