用户工具

站点工具


fpga:petalinux

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
fpga:petalinux [2023/02/09 10:20] – [9. zynq设备上运行指定驱动的app程序] zhangguofpga:petalinux [2023/03/17 10:12] (当前版本) – 外部编辑 127.0.0.1
行 235: 行 235:
 ===== - linux 加载module ===== ===== - linux 加载module =====
  
-<code> +<code bash
-insmode blink.ko+insmod blink.ko
 # 如果有同名文件module已经加载,可以先lsmode查看 # 如果有同名文件module已经加载,可以先lsmode查看
  
-lsmode+lsmod   # 列出已经加载的module
  
-rmmode blink.ko  # 删除已加载的module, 可以在后面两次加载新的module.+rmmod blink.ko  # 删除已加载的module, 可以在后面两次加载新的module. 
 + 
 + 
 +</code> 
 + 
 + 
 +===== - module驱动代码实例 ===== 
 +==== - 一个简单的device module 驱动代码 ==== 
 + 
 +主要描述用户数据和内核数据之间如何互通,因为不能直接访问,需要通过copy_to_user & copy_from_user函数来完成。 
 + 
 +<code c> 
 + 
 + 
 +#include <linux/uaccess.h>  // copy_to_user copy_from_user 
 + 
 +#include <asm/uaccess.h> /* for get_user and put_user */  // raw_copy_to_user, raw_copy_from_user 
 + 
 + 
 + 
 +/* 
 +* This function is called whenever a process which has already opened the 
 +* device file attempts to read from it. 
 +*/ 
 +static ssize_t device_read( struct file *file, /* see include/linux/fs.h */ 
 + char __user * buffer, /* buffer to be filled with data */ 
 + size_t length, /* length of the buffer */ 
 + loff_t * offset) 
 +
 +    int ret; 
 + 
 +    char k_buffer[20] = {0}; // kernel core buffer 
 + 
 +    memcpy(k_buffer, "core_to_user_msg02", length); 
 + 
 +    ret = copy_to_user(buffer, k_buffer, length); 
 + 
 + 
 + return SUCCESS; 
 +
 +/* 
 +* This function is called when somebody tries to 
 +* write into our device file. 
 +*/ 
 +static ssize_t device_write(struct file *file, 
 + const char __user * buffer,  
 + size_t length,  
 + loff_t * offset) 
 +
 + 
 +    // user function 
 +    int ret; 
 +    char k_buffer[20] = {0}; // kernel core buffer 
 +    ret = copy_from_user(k_buffer, buffer, length); 
 + 
 +     
 +   printk("kernel:::  blink write: %s\n", k_buffer); 
 +    // end 
 + 
 + return SUCCESS; 
 +
 + 
 + 
 +</code> 
 + 
 + 
 + 
 +==== - gpio驱动led举例 ==== 
 + 
 +驱动部分: 
 + 
 +<code c> 
 +#include <linux/init.h>     //定义了module_init 
 +#include <linux/module.h>   //最基本的头文件,其中定义了MODULE_LICENSE这一类宏 
 +#include <linux/fs.h>       //file_operations结构体定义在该头文件中 
 +#include <linux/device.h> //class、device结构体的定义位置 
 +#include <linux/kernel.h> //printk头文件 
 + 
 +#include <linux/uaccess.h> //copy_from_user头文件 
 +#include <asm/io.h> //ioremap头文件 
 + 
 +#include <linux/ioport.h> 
 +#include <linux/of.h> 
 +#include <linux/delay.h> 
 + 
 +//定义主设备号  
 +static int major_num; 
 +//  定义设备文件名 
 +#define DEVICE_NAME "leds" 
 + 
 +//定义class、device结构体 
 +#define CLASS_NAME "mygpio"  
 +static struct class* gpio_class;     
 +static struct device* gpio_device;  
 + 
 +#define LEDS_BASE_ADDR (0x41200000) //GPIO的Base addr,用于映射 
 +  
 +static unsigned *leds; 
 + 
 +static int leds_drv_open(struct inode *Inode, struct file *File) 
 +
 + *leds = 0x0;  
 + return 0; 
 +
 +  
 +  
 +static ssize_t leds_drv_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 
 +
 + return 0; 
 +
 +  
 +static ssize_t leds_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 
 +
 + unsigned int ret = 0; 
 + unsigned int tmp_val; 
 +  
 + ret = copy_from_user(&tmp_val, buf, count); 
 +  
 + *leds = tmp_val & 0xf;  
 +  
 + return ret; 
 +
 +  
 +//  描述与设备文件触发的事件对应的回调函数指针 
 +static struct file_operations dev_fops = 
 +{  
 + .owner = THIS_MODULE,  
 + .open = leds_drv_open, 
 + .read = leds_drv_read,  
 + .write = leds_drv_write, 
 +}; 
 +  
 +//  初始化Linux驱动 
 +static int __init leds_drv_init(void) 
 +
 + int ret;  
 +  
 + leds = ioremap(LEDS_BASE_ADDR, 0x100); 
 +  
 + //获取主设备号 
 + major_num = register_chrdev(0,DEVICE_NAME, &dev_fops); 
 +  
 + //创建设备类 
 + gpio_class = class_create(THIS_MODULE, CLASS_NAME);     
 + 
 + if(IS_ERR(gpio_class)) 
 + {                 
 +    unregister_chrdev(major_num, DEVICE_NAME); 
 +    printk(KERN_ALERT "Failed to register device class\n"); 
 +    return PTR_ERR(gpio_class);           
 +    } 
 +    //注册设备 
 + gpio_device = device_create(gpio_class, NULL, MKDEV(major_num, 0), NULL, DEVICE_NAME); 
 +  
 + if(IS_ERR(gpio_device)) 
 + {                
 +    class_destroy(gpio_class);            
 +    unregister_chrdev(major_num, DEVICE_NAME); 
 +    printk(KERN_ALERT "Failed to create the device\n"); 
 +    return PTR_ERR(gpio_device); 
 +    } 
 +    printk(KERN_INFO "LED_GPIO_init: device created correctly\n"); 
 +  
 + return 0; 
 +
 +  
 +// 卸载Linux驱动 
 +static void __exit leds_drv_exit(void) 
 +
 + iounmap(leds); 
 +  
 + //  删除设备文件,后创建的先卸载   
 + device_destroy(gpio_class, MKDEV(major_num, 0));   
 + class_destroy(gpio_class);  
 + 
 + unregister_chrdev(major_num,DEVICE_NAME); //释放设备号 
 + 
 + //  输出日志信息 
 + printk("LED_GPIO_exit success!\n"); 
 +}  
 +  
 +//  注册初始化Linux驱动的函数 
 +module_init(leds_drv_init); 
 +//  注册卸载Linux驱动的函数 
 +module_exit(leds_drv_exit); 
 + 
 +MODULE_LICENSE("GPL"); 
 + 
 +</code> 
 + 
 +应用程序app部分: 
 + 
 +<code c> 
 +#include <stdio.h> 
 +#include <sys/ioctl.h> 
 +#include <sys/types.h> 
 +#include <sys/stat.h> 
 +#include <fcntl.h> 
 +  
 +  
 +  
 +int main(int argc, char** argv) 
 +
 +        int fd; 
 +         
 +        fd = open("/dev/leds", O_RDWR); 
 +         
 +        if(fd < 0) 
 +        { 
 +                printf("fd = %d open fialed!\n", fd); 
 +        } 
 + 
 +        unsigned int leds = 0; 
 + 
 +        while(1) 
 +        { 
 +        write(fd, &leds, 4); 
 +         
 +        leds++; 
 +        leds %= 0xf; 
 +                sleep(1); 
 +        } 
 + 
 +        close(fd); 
 + 
 +        return 0; 
 +}
  
  
 </code> </code>
fpga/petalinux.1675909211.txt.gz · 最后更改: 2023/03/17 10:12 (外部编辑)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki