網站首頁 編程語言 正文
平臺總線模型
- 1.平臺總線模型簡介
- 1.什么是平臺總線模型
- 2.平臺總線優缺點
- 3.怎么編寫以平臺總線模型設計的驅動?
- 2.平臺總線注冊一個device
- 3.平臺總線注冊driver
- 4.Makefile
- 5.app
- 5.編譯運行
- 1.執行make,然后將生成的driver.ko、device.ko以及app可執行文件移到樹莓派
- 2.先sudo dmesg -C 將內核雜志清楚
- 3.sudo insmod driver.ko
- 4.sudo insmod device.ko
- 5. dmesg可以查看打印信息
- 6.sudo ./app 1
- 7. sudo ./app 0
- 6 總結
我觀看訊為視頻寫的,其鏈接: link
1.平臺總線模型簡介
1.什么是平臺總線模型
平臺總線模型也叫platform總線模型。是linux內核虛擬出來的一條總線,不是真實的導線。
平臺總線模型就是把原來的驅動C文件給分成了倆個C文件,一個是device.c,一個是driver.c
把穩定不變的放在driver,c里面,需要變的就放在device,c里。
2.平臺總線優缺點
(1).可以提高代碼的重用性
(2).減少重復性代碼
設備 總線(連接設備和驅動) 驅動
device.c driver.c
3.怎么編寫以平臺總線模型設計的驅動?
一個是device.c ,一個是driver.c,然后分別注冊device.c和driver.c。
平臺總線就是以名字來匹配,實際上就是字符串比較。
2.平臺總線注冊一個device
device.c里面寫的是硬件資源,這里的硬件資源是指寄存器的地址,中斷號,時鐘等硬件資源。
device,c代碼
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
void led_release(struct device *dev)
{
printk("led_release \n");
}
struct resource led_res[] = {
[0] = {
.start = 0xfe200000,
.end = 0xfe200003,
.flags = IORESOURCE_MEM,
.name = "GPIO1_IO4DIR",
},
[1] = {
.start = 0xfe20001c,
.end = 0xfe20001f,
.flags = IORESOURCE_MEM,
.name = "GPIO1_IO4H"
},
[2] = {
.start = 0xfe200028,
.end = 0xfe20002b,
.flags = IORESOURCE_MEM,
.name = "GPIO1_IO4L"
},
};
struct platform_device led_device = {
.name = "led_test",
.id = -1,
.resource = led_res,
.num_resources = ARRAY_SIZE(led_res),
.dev={
.release = led_release,
},
};
static int device_init(void)
{
platform_device_register(&led_device);
printk("platform_device_register ok \n");
return 0;
}
static void device_exit(void)
{
platform_device_unregister(&led_device);
printk("goodbye! \n");
}
module_init(device_init);
module_exit(device_exit);
MODULE_LICENSE("GPL");
3.平臺總線注冊driver
driver.c代碼
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h> //注冊雜項設備頭文件
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/io.h>
unsigned int *vir_gpio4_dr=NULL;
unsigned int *vir_gpio4_h=NULL;
unsigned int *vir_gpio4_l=NULL;
struct resource *gpio4_dir;
struct resource *gpio4_h;
struct resource *gpio4_l;
struct resource *leddir_mem_test;
struct resource *ledh_mem_test;
struct resource *ledl_mem_test;
ssize_t misc_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t)
{
char kbuf[64] = {0};
if ( copy_from_user( kbuf, ubuf, size) != 0)
{
printk( "copy_from_user error\n ");
return -1;
}
printk( "kbuf is %s\n ", kbuf);
*vir_gpio4_dr |= (001<<(3*4));
if( kbuf[0] == 1)
{
*vir_gpio4_h |=(1<<4);
}
else if( kbuf[0]==0)
{
*vir_gpio4_l |=(1<<4);
}
return 0;
}
int misc_release( struct inode *inode, struct file *file)
{
printk( "hello misc_relaease bye bye \n ");
return 0;
}
int misc_open( struct inode *inode, struct file *file)
{
printk( "hello misc_open\n ");
return 0;
}
//文件操作集
struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.write = misc_write,
};
//miscdevice 結構體
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "hello_misc",
.fops = &misc_fops,
};
int led_probe( struct platform_device *pdev)
{
int ret;
printk( "led_probe\n");
ret = misc_register( &misc_dev); //注冊雜項設備
if (ret < 0)
{
printk( "misc registe is error \n");
}
printk( "misc registe is succeed \n");
gpio4_dir = platform_get_resource( pdev, IORESOURCE_MEM, 0);
gpio4_h = platform_get_resource( pdev, IORESOURCE_MEM, 1);
gpio4_l = platform_get_resource( pdev, IORESOURCE_MEM, 2);
vir_gpio4_dr = ioremap( gpio4_dir->start,4);
if( vir_gpio4_dr== NULL )
{
printk( "gpio4dr ioremap error\n");
return EBUSY;
}
vir_gpio4_h = ioremap( gpio4_h->start,4);
if( vir_gpio4_h== NULL)
{
printk( "gpio4h ioremap error\n");
return EBUSY;
}
vir_gpio4_l = ioremap( gpio4_l->start,4);
if( vir_gpio4_l == NULL)
{
printk( "gpio4l ioremap error\n");
return EBUSY;
}
printk( "gpio ioremap success\n");
return 0;
#if 0
leddir_mem_test = request_mem_region( gpio4_dir->start, gpio4_dir->end - gpio4_dir->start +1, "led_dir");
if( leddir_mem_test == NULL){
printk( "platform_get_resource iserror \n");
goto errdir_region;
}
ledh_mem_test = request_mem_region( gpio4_dir->start, gpio4_dir->end - gpio4_dir->start +1, "led_dir");
if( ledh_mem_test == NULL){
printk( "platform_get_resource iserror \n");
goto errh_region;
}
ledl_mem_test = request_mem_region( gpio4_dir->start, gpio4_dir->end - gpio4_dir->start +1, "led_dir");
if( ledl_mem_test == NULL){
printk( "platform_get_resource iserror \n");
goto errl_region;
}
return 0;
errdir_region:
release_mem_region( gpio4_dir->start, gpio4_dir->end - gpio4_dir->start +1);
return -EBUSY;
errh_region:
release_mem_region( gpio4_h->start, gpio4_h->end - gpio4_h->start +1);
return -EBUSY;
errl_region:
release_mem_region(gpio4_l->start, gpio4_l->end - gpio4_l->start +1);
return -EBUSY;
#endif
}
int led_remove( struct platform_device *pdev)
{
printk("led_remove\n");
return 0;
}
struct platform_driver led_driver ={
.probe = led_probe,
.remove = led_remove,
.driver = {
.owner = THIS_MODULE,
.name = "led_test"
},
};
static int led_driver_init( void)
{
int ret =0;
ret = platform_driver_register( &led_driver);
if( ret<0)
{
printk( "platform_driver_register error \n");
}
printk( "platform_driver_register ok \n");
return 0;
}
static void led_driver_exit(void)
{
misc_deregister( &misc_dev); //卸載雜項設備
printk( "misc gooodbye! \n");
iounmap( vir_gpio4_dr);
iounmap( vir_gpio4_h);
iounmap( vir_gpio4_l);
// platform 驅動卸載
platform_driver_unregister( &led_driver);
printk( "goodbye! \n");
}
module_init( led_driver_init);
module_exit( led_driver_exit);
MODULE_LICENSE( "GPL");
4.Makefile
在使用我寫的Makefile的時候記得改下KDIR,和ARCH,
obj-m +=device.o
obj-m +=driver.o
KDIR:=/home/kun/build_new/linux_kernel
PWD?=$(shell pwd)
all:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C $(KDIR) M=$(PWD) modules
clean:
rm *.mod.c *.order *.ko *.o *.mod *.symvers
5.app
編譯指令arm-linux-gnueabihf-gcc app.c -o app -static
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc,char *argv[])
{
int fd;
fd = open("/dev/hello_misc",O_RDWR);//打開設備節點
if(fd < 0)
{
perror("open error \n");
return fd;
}
buf[0]=atoi(argv[1]);
write(fd,buf,sizeof(buf)); //向內核層寫數據
close(fd);
return 0;
}
5.編譯運行
1.執行make,然后將生成的driver.ko、device.ko以及app可執行文件移到樹莓派
2.先sudo dmesg -C 將內核雜志清楚
3.sudo insmod driver.ko
4.sudo insmod device.ko
5. dmesg可以查看打印信息
6.sudo ./app 1
7. sudo ./app 0
6 總結
platform總線給我的感覺就是把硬件的信息放在一個文件,讓后另一個文件去獲取該文件的硬件信息,感覺就相當于一個.c文件,一個.h文件,.c文件去寫實現功能,.h去定義需要的文件,然后app可執行文件相當于main函數,去調用。(本人小白,剛學習驅動開發,個人愚見,如果不對的話,麻煩各位大佬提出,不勝感激)
原文鏈接:https://blog.csdn.net/weixin_42963900/article/details/127559895
- 上一篇:SQL Server常用的函數與查詢方法
- 下一篇:編寫字符設備驅動控制樹莓派io口
相關推薦
- 2023-04-22 關于Python字典的底層實現原理_python
- 2022-11-22 XML實體注入深入理解_XML示例
- 2022-03-06 C#中List用法介紹詳解_C#教程
- 2022-09-23 Go語言fmt.Sprintf格式化輸出的語法與實例_Golang
- 2022-04-17 Bootstrap typeahead自動補全插件的坑
- 2022-09-17 C++實現圖的遍歷算法(DFS,BFS)的示例代碼_C 語言
- 2023-03-22 Linux?rm命令詳解?Linux刪除文件目錄的操作方法_linux shell
- 2022-12-05 Linux中的grep?-v、-e、-E用法小結_linux shell
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支