• 【Linux】【驱动】平台总线模式platform模型的编写,操作LED灯


    【Linux】【驱动】平台总线模式platform模型的编写,操作LED灯

    平台总线模式,将设备和驱动进行了区分,据说可以优化代码的可移植性
    device:实现对设备寄存器的申明
    dirver: 则从总线中取数据,取的时候可以检验是否被使用过,取完在去操作

    主要就是三个文件

    device

    #include 
    #include 
    #include 
    
    
    void beep_release(struct device *dev)
    {
    	printk("beep_release\n");
    
    }
    
    
    struct resource beep_res[] = {
    	
    	[0] ={
    		.start = 0x20AC000,
    		.end = 0x20AC003,
    		.flags = IORESOURCE_MEM,
    		.name = "GPIO5_DR"
    	},
    	
    	[1] ={
    		.start = 0x20AC000 + 0x04,
    		.end = 0x20AC000 + 0x04 + 0x03,
    		.flags = IORESOURCE_MEM,
    		.name = "GPIO5_GDIR"
    	},
    	[2] ={
    		.start = 0x2290014,
    		.end = 0x2290017,
    		.flags = IORESOURCE_MEM,
    		.name = "IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3"
    	},
    	[3] ={
    		.start = 0x20C406C,
    		.end = 0x20C406C + 0x03,
    		.flags = IORESOURCE_MEM,
    		.name = "CCM_CCGR1"
    	}
    };
    
    struct platform_device beep_device =
    {
    	.name          	= "beep_test",
    	.id 			= -1,
    	.resource 		= beep_res,
    	.num_resources 	= ARRAY_SIZE(beep_res),
    	.dev ={
    		.release = beep_release
    	}
    };
    
    
    
    //drivers for init
    static int device_init(void)
    {
    	printk("device_init \n");
    	return platform_device_register(&beep_device);
    	
    }
    
    //drivers for exit 
    static void device_exit(void)
    {
    
    	printk("device_exit \n");
    	return platform_device_unregister(&beep_device);;
    }
    
    module_init(device_init);
    module_exit(device_exit);
    
    MODULE_LICENSE("GPL");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    driver

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    
    
    
    
    struct resource *beep_mem;
    struct resource *beep_mem_tmp;
    struct resource *beep_GDIR;
    struct resource *beep_GDIR_tmp;
    struct resource *beep_CCM_CCGR1;
    struct resource *beep_CCM_CCGR1_tmp;
    struct resource *beep_IOMUXC;
    struct resource *beep_IOMUXC_tmp;
    
    
    static volatile unsigned int *GPIO5_DR ;
    static volatile unsigned int *GPIO5_GDIR ;
    static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 ;
    static volatile unsigned int *CCM_CCGR1 ;
    
    
    
    int misc_open(struct inode *inode, struct file *file)
    {
    	printk("misc_open\n");
    
    	return 0;
    }
    
    int misc_release(struct inode *inode, struct file *file)
    {
    	printk("misc_release\n");
    	return 0;
    
    }
    
    ssize_t misc_read(struct file *file,char __user *ubuf,size_t size,loff_t *loff_t)
    {
    	char kbuf[512] = "haha";
    
    	if(copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    	{
    		printk("error copying\n");
    		return -1;
    	}
    
    	return 0;
    
    }
    
    ssize_t misc_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loff_t)
    {
    
    	char kbuf[512] = {0};	
    	if(copy_from_user(kbuf,ubuf,size)!= 0)
    	{
    		printk("misc_write error\n");
    		return -1;
    
    	}
    
    	printk("kbuf = %d\n",kbuf[0]);
    	if(kbuf[0] == 1)
    		{
    			*GPIO5_DR |=(1<<3);//设置GPIO
    			printk(" kbuff  = 1\n");
    		}
    	else if(kbuf[0] == 0)
    	{
    		*GPIO5_DR &= ~(1<<3);//设置GPIO
    		printk(" kbuff  = 0\n");
    	}
    
    
    	return 0;
    
    }
    
    struct file_operations misc_fops = {
    	.owner	= THIS_MODULE,
    	.open	= misc_open,
    	.release = misc_release,
    	.read	= misc_read,
    	.write	= misc_write
    };
    
    
    struct miscdevice misc_dev = 
    {
    	.minor = MISC_DYNAMIC_MINOR,
    	.name = "hello_misc",
    	.fops = &misc_fops
    };
    
    
    
    int  beep_probe (struct platform_device *pdev)
    {
    	int ret = 0;
    	unsigned int val;
    	printk("beep_probe \n");
    	
    	//方案1,直接读取device中的数据
    	//printk ("beep_res is %s\n", pdev->resource[0].name);
    
    	//方案2 使用函数去读取
    	beep_mem = platform_get_resource (pdev,IORESOURCE_MEM,0); 
    	if(beep_mem == NULL){
    		printk("platform_get_resource null \n");
    		return -EBUSY;
    	}
    	beep_GDIR = platform_get_resource (pdev,IORESOURCE_MEM,1); 
    	if(beep_GDIR == NULL){
    		printk("platform_get_resource beep_GDIR null\n");
    		return -EBUSY;
    	}
    
    
    	beep_IOMUXC = platform_get_resource (pdev,IORESOURCE_MEM,2); 
    	if(beep_IOMUXC == NULL){
    		printk("platform_get_resource beep_IOMUXC null\n");
    		return -EBUSY;
    	}
    
    	beep_CCM_CCGR1 = platform_get_resource (pdev,IORESOURCE_MEM,3); 
    	if(beep_CCM_CCGR1 == NULL){
    		printk("platform_get_resource beep_IOMUXC null\n");
    		return -EBUSY;
    	}
    
    
    /***********************************************************************/
    	printk(" platform_get_resource is ok \n");
    	printk(" beep_res start is 0x%x \n",beep_mem->start);
    	printk(" beep_res end is 0x%x \n",beep_mem->end);
    
    	// //有用过则会声明失败
    	// beep_mem_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep");
    	// if( beep_mem_tmp == NULL){
    	// 	printk("request_mem_region is error \n");
    	// 	goto err_region;
    	// }
    	// beep_GDIR_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep_GPIO5_GDIR");
    	// if( beep_GDIR_tmp == NULL){
    	// 	printk("request_mem_region is error \n");
    	// 	goto err_region;
    	// }	
    	// beep_CCM_CCGR1_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep_CCM_CCGR1");
    	// if( beep_CCM_CCGR1_tmp == NULL){
    	// 	printk("request_mem_region is error \n");
    	// 	goto err_region;
    	// }	
    	
    	// beep_IOMUXC_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep_IOMUXC");
    	// if( beep_IOMUXC_tmp == NULL){
    	// 	printk("request_mem_region is error \n");
    	// 	goto err_region;
    	// }
    
    /***********************************************************************/
    	GPIO5_DR = ioremap(beep_mem->start,4);
    	if(GPIO5_DR == NULL)
    	{
    		printk("GPIO5_DR is error \n");
    		return -EBUSY;
    	}
    	printk("GPIO5_DR ioremap OK \n");
    
    	GPIO5_GDIR = ioremap(beep_GDIR->start,4);
    	if(GPIO5_GDIR == NULL)
    	{
    		printk("GPIO5_GDIR is error \n");
    		return -EBUSY;
    	}
    	printk("GPIO5_GDIR ioremap OK \n");
    
    	IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(beep_IOMUXC->start,4);
    	if(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 == NULL)
    	{
    		printk("IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 is error \n");
    		return -EBUSY;
    	}
    	printk("IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 ioremap OK \n");
    
    	
    	CCM_CCGR1 = ioremap(beep_CCM_CCGR1->start,4);
    	if(CCM_CCGR1 == NULL)
    	{
    		printk("CCM_CCGR1 is error \n");
    		return -EBUSY;
    	}
    	printk("CCM_CCGR1 ioremap OK \n");
    
    
    	*CCM_CCGR1 |= (3<<30);//使能 GPIO5
    	//设置 GPIO5_IO03 用于 GPIO
    	val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
    	val &= ~(0xf);
    	val |= (5);
    	*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = val;
    
    	//设置 GPIO5_IO03 作为 output 引脚
    	*GPIO5_GDIR |= (1<<3);
    /***********************************************************************/
    
    	ret = misc_register(&misc_dev);
    	if(ret<0){
    		printk("misc_register is error \n");
    		return -1;
    	}
    	printk("misc registe is successed \n");
    
    	return 0;
    
    
    // err_region:
    // 	release_mem_region(beep_mem->start,beep_mem->end - beep_mem->start + 1);
    // 	return -EBUSY;
    
    
    
    }
    
    int  beep_remove (struct platform_device *pdev)
    {
    	printk("beep_remove \n");
    	return 0;
    
    }
    
    const struct platform_device_id beep_id_table= {
    	.name = "beep_test",
    
    };
    
    
    struct platform_driver beep_device =
    {
    	/* data */
    	.probe = beep_probe,
    	.remove = beep_remove,
    	.driver = {
    		.owner = THIS_MODULE,
    		.name = "123"
    	},
    	.id_table = &beep_id_table
    
    };
    
    
    
    //drivers for init
    static int beep_driver_init(void)
    {
    	int ret = 0;
    	ret = platform_driver_register(&beep_device);
    	if(ret < 0){
    		printk("platform_driver_register ERROR \n");
    		return ret;
    
    	}
    	printk("platform_driver_register OK\n");
    	return 0;
    }
    
    
    //drivers for exit 
    static void beep_driver_exit(void)
    {
    	printk("beep_driver_exit exit \n");
    	platform_driver_unregister(&beep_device);
    	misc_deregister(&misc_dev);
    	iounmap(CCM_CCGR1);
    	iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3);
    	iounmap(GPIO5_GDIR);
    	iounmap(GPIO5_DR);
    }
    
    module_init(beep_driver_init);
    module_exit(beep_driver_exit);
    
    MODULE_LICENSE("GPL");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290

    app

    #include "stdio.h"
    #include "unistd.h"
    #include "sys/types.h"
    #include "sys/stat.h"
    #include "fcntl.h"
    #include "stdlib.h"
    #include "string.h"
    
    
    /*
     * @description		: main主程序
     * @param - argc 	: argv数组元素个数
     * @param - argv 	: 具体参数
     * @return 			: 0 成功;其他 失败
     */
    int main(int argc, char *argv[])
    {
    	int fd;
    	char buf[64] = {0};
    
    	//fd = open(argv[1], O_RDONLY);
    	fd = open("/dev/hello_misc", O_RDWR);
    
    	if(fd < 0)
    	{
    		perror("open error");
    		return fd;
    
    	}
    	buf[0] = atoi(argv[1]);
    
    	write(fd,buf,sizeof(buf));
    	close(fd);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    操作指令

    编译app代码

    arm-buildroot-linux-gnueabihf-gcc -o app app.c
    
    • 1

    移动文件

    cp misc.ko /home/book/nfs_rootfs/
    
    • 1

    允许printk

    echo "7 4 1 7"> /proc/sys/kernel/printk
    
    • 1

    输入值到app中

    ./app 1
    
    • 1

    PS :待修正
    文中使用了request_mem_region代码的位置,可能由于已经在系统中声明过,所以会出现报错的问题,后面需要寻找方式去消除

     beep_mem_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep");
     if( beep_mem_tmp == NULL){
     	printk("request_mem_region is error \n");
     	goto err_region;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    InnoDB底层存储结构探秘
    环辛炔衍生物DBCO-NH2,amine,Acid,NHS,Maleimide无铜点击反应
    Go 学习之 io.Reader 从源码了解如何编写
    痞子衡嵌入式:MCUXpresso IDE下将源码制作成Lib库方法及其与IAR,MDK差异
    你需要知道的前端知识点,V8引擎是什么?采用哪些GC算法?
    如何使用JavaScript实现在线Excel附件的上传与下载?
    LeetCode_21_简单_合并两个有序链表
    Oracle 11g+PLSQL Developer安装及环境配置
    Web酒店管理系统(附源码及资源)
    『外卖好评(通用50字)』
  • 原文地址:https://blog.csdn.net/chen1658137632/article/details/133003111