嵌入式实践教程--设备树下的LED驱动开发

简介: 嵌入式实践教程--设备树下的LED驱动开发

1、修改设备树文件


在根节点/创建一个LED的子节点


image.png


2、驱动编写


(1)入口函数

static int __init led_init(void)
{
  u32 val=0;
  int ret;
  u32 regdata[14];
  const char *str;
  struct property *proper;
  /* 获取设备树中的属性数据 */
  //1、获取根节点下的设备节点 muggle_led
  dtsled.nd = of_find_node_by_path("/muggle_led");
  //判断获得的节点是否正确
  if(dtsled.nd == NULL)
  {
  printk("muggle-led node  can not found!\r\n");
  return -EINVAL;
  }
  else
  {
  printk("muggle-led node has been found!\r\n");
  }
  //2、获取compatible属性内容
  proper = of_find_property(dtsled.nd, "compatible", NULL);
  if(proper == NULL)
  {
  printk("compatible property find failed!\r\n");
  }
  else
  {
  printk("compatible = %s\r\n", (char*)proper->value);
  }
  //3、获取status属性内容
  ret = of_property_read_string(dtsled.nd, "status", &str);
  if(ret < 0)
  {
  printk("status read failed!\r\n");
  }
  else
  {
  printk("status read success: %s\r\n", str);
  }
  //4、获取reg属性内容
  ret = of_property_read_u32_array(dtsled.nd, "reg", regdata,  10);
  if(ret < 0 )
  {
  printk("reg read failed!|r\n");
  }
  else
  {
  u8 i = 0;
  printk("reg data:\r\n");
  for(i = 0; i < 10; i++)
  {
    printk("%#X", regdata[i]);  //打印地址数据
  }
  printk("\r\n");
  }
  /* 初始化LED */
#if 0
  //寄存器地址映射
  IMX6U_CCM_CCGR1 = ioremap(regdata[0], regdata[1]);
  SW_MUX_GPIO1_IO03 = ioremap(regdata[2], regdata[3]);
  SW_PAD_GPIO1_IO03 = ioremap(regdata[4], regdata[5]);
  GPIO1_DR = ioremap(regdata[6], regdata[7]);
  GPIO1_GDIR = ioremap(regdata[8], regdata[9]);
#else
  IMX6U_CCM_CCGR1 = of_iomap(dtsled.nd, 0); //映射reg的数据
  SW_MUX_GPIO1_IO03 = of_iomap(dtsled.nd, 1);
  SW_PAD_GPIO1_IO03 = of_iomap(dtsled.nd, 2);
  GPIO1_DR = of_iomap(dtsled.nd, 3);
  GPIO1_GDIR = of_iomap(dtsled.nd, 4);
#endif
  //使能GPIO1时钟
  val = readl(IMX6U_CCM_CCGR1);    //读取数值
  val &= ~(3<<26);        //引脚清0
  val |= (3<<26);        //设置新值
  writel(val, IMX6U_CCM_CCGR1);    //写入数值
  //设置GPIO_IO03的复用功能,将其复用为GPIO_IO03最后设置IO属性
  writel(5, SW_MUX_GPIO1_IO03);
  writel(5, SW_PAD_GPIO1_IO03);
  //4、设置GPIO_GDIR输出功能
  val = readl(GPIO1_GDIR);
  val &= (1<<3);
  val |= (1<<3);
  writel(val, GPIO1_GDIR);
  //5、默认关闭LED
  val = readl(GPIO1_DR);
  val |= (1<<3);
  writel(val, GPIO1_DR);
  /* 注册字符设备驱动 */
  //1 创建设备号
  if(dtsled.major)
  {
  //针对已定义设备号
  dtsled.devid = MKDEV(dtsled.major, 0);
  register_chrdev_region(dtsled.devid, DTSLED_CNT, DTSLED_NAME);
  }
  else
  {
  alloc_chrdev_region(&dtsled.devid, 0, DTSLED_CNT, DTSLED_NAME); //申请设备号
  dtsled.major = MAJOR(dtsled.devid);        //获取分配的主设备号
  dtsled.minor = MINOR(dtsled.devid);        //获取分配的次设备号
  }
  printk("dtsled major = %d,minor=%d\r\n", dtsled.major, dtsled.minor);
  //2 初始化 cdev
  dtsled.cdev.owner = THIS_MODULE;
  cdev_init(&dtsled.cdev, &dtsled_fops);
  //3 添加一个cdev
  cdev_add(&dtsled.cdev, dtsled.devid, DTSLED_CNT);
  //4 创建一个类
  dtsled.class = class_create(THIS_MODULE, DTSLED_NAME);
  if(IS_ERR(dtsled.class))
  {
  return PTR_ERR(dtsled.class);
  }
  //5 创建设备
  dtsled.device = device_create(dtsled.class, NULL, dtsled.devid, NULL, DTSLED_NAME);
  if(IS_ERR(dtsled.device))
  {
  return PTR_ERR(dtsled.class);
  }
  return 0;
}


(1.1)是遍历设备树的根节点,获取compatible、status、reg属性,获取到reg中引脚的地址数据,然后of_iomap映射备用。


(1.2)使能GPIO引脚,写入数据。


(1.3)注册字符设备驱动:创建设备号、初始化cdev、添加cdev时加入dtsled_fops结构体、创建一个类最后创建设备


(1.4)编写dtsled_fops中open、read、write和release函数


(1.4.1)open函数主要实现私有数据的设置


(1.4.2)write函数从用户空间获取数据,操作LED关停


(2)出口函数

static void __exit led_exit(void)
{
  //取消映射
  iounmap(IMX6U_CCM_CCGR1);
  iounmap(SW_MUX_GPIO1_IO03);
  iounmap(SW_PAD_GPIO1_IO03);
  iounmap(GPIO1_DR);
  iounmap(GPIO1_GDIR);
  /* 注销字符设备驱动 */
  cdev_del(&dtsled.cdev);/* 删除 cdev */
  unregister_chrdev_region(dtsled.devid, DTSLED_CNT);/*注销设备号*/
  device_destroy(dtsled.class, dtsled.devid);
  class_destroy(dtsled.class);
}


相关文章
|
9月前
|
传感器 C语言 芯片
「入门指南」轻松学习嵌入式 GPIO:从原理到应用一步到位
「入门指南」轻松学习嵌入式 GPIO:从原理到应用一步到位
|
9月前
|
Linux 图形学 Windows
嵌入式课程实现Linux操作系统LVGL移植操作
嵌入式课程实现Linux操作系统LVGL移植操作
|
Linux 开发工具 git
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十二)LED模板驱动程序的改造:设备树
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十二)LED模板驱动程序的改造:设备树
297 1
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十二)LED模板驱动程序的改造:设备树
|
Linux 芯片
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程(上)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程
368 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程(上)
|
Ubuntu Linux 程序员
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程(中)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程
706 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程(中)
|
Linux 芯片
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程(下)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程
206 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程(下)
|
Linux 调度 开发工具
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石(上)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石
234 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石(上)
|
Linux 程序员 调度
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石(中)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石
195 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石(中)
|
存储 Ubuntu Linux
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石(下)
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石
198 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石(下)
|
Linux
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十九)驱动进化之路:总线设备驱动模型
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十九)驱动进化之路:总线设备驱动模型
145 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十九)驱动进化之路:总线设备驱动模型

热门文章

最新文章