【Linux笔记】LED驱动实验(总线设备驱动模型)

前言

继续来点灯~学了一段时间的嵌入式Linux发现LED程序挺香的。。

从LED程序中我们可以榨取很多知识:基本的驱动框架、驱动的简单分层、驱动的分层+分离思想、总线设备驱动模型、设备树等。

这大多都是结合韦老师的教程学的,这篇笔记结合第5个demo来学习、分析:

框图

LED程序的几个层次结构图:

本篇笔记基于第④个图来分析。

程序分析

关于总线设备驱动模型的理论知识我们在上一篇笔记【Linux笔记】总线设备驱动模型中也有简单地学习过了。这篇笔记我们来分析、学习程序。

下面分析主要基于上面的框图4:

应用程序ledtest.c:

int main(int argc, char **argv)
{
 int fd;
 char status;
 
 /* 1. 判断参数 */
 if (argc != 3) 
 {
  printf("Usage: %s <dev> <on | off>\n", argv[0]);
  return -1;
 }

/* 2. 打开文件 */
 fd = open(argv[1], O_RDWR);
 if (fd == -1)
 {
  printf("can not open file %s\n", argv[1]);
  return -1;
 }

/* 3. 写文件 */
 if (0 == strcmp(argv[2], "on"))
 {
  status = 1;
  write(fd, &status, 1);
 }
 else
 {
  status = 0;
  write(fd, &status, 1);
 }
 
 close(fd);
 
 return 0;
}

运行测试命令:

./ledtest /dev/100ask_led0 on
./ledtest /dev/100ask_led0 off

int main(int argc, char **argv)形式的main函数相关笔记:main()函数有哪几种形式?

驱动层leddrv.c

这一层主要是放一些通用的驱动操作函数,核心代码如:

驱动程序入口函数:

open、write函数:

其它代码:

其中led的操作结构体如下:

硬件层2:chip_demo_gpio.c

这一层主要是一些寄存器相关的操作,及platform_driver相关。

驱动初始化函数:

probe函数:

platform_driver与platform_device匹配时会执行此函数获取资源。

led寄存器操作相关的代码:

/* 寄存器物理地址 */
#define CCM_CCGR1_BASE    (0X020C406C) 
#define SW_MUX_GPIO5_IO03_BASE  (0X02290014)
#define GPIO5_DR_BASE    (0X020AC000)
#define GPIO5_GDIR_BASE    (0X020AC004)

/* 映射后的寄存器虚拟地址指针 */
static void __iomem *CCM_CCGR1;
static void __iomem *SW_MUX_GPIO5_IO03;
static void __iomem *GPIO5_DR;
static void __iomem *GPIO5_GDIR;

/* 初始化LED, which-哪个LED */    
static int board_demo_led_init (int which)    
{   
 int group, pin;
 unsigned int val;

group = GROUP(g_ledpins[which]);
 pin = PIN(g_ledpins[which]);
 printk("init gpio: group %d, pin %d\n", group, pin);

/* 100ask_IMX6uLL_Board LED:GPIO5_3 */
 if ((5 == group) && (3 == pin))
 {
  /* 相关寄存器物理地址与虚拟地址之间的映射 */
  /* 1、地址映射:时钟寄存器 */
  CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);  
  /* 2、地址映射:模式寄存器 */ 
  SW_MUX_GPIO5_IO03 = ioremap(SW_MUX_GPIO5_IO03_BASE, 4); 
  /* 3、地址映射:数据寄存器 */
  GPIO5_DR = ioremap(GPIO5_DR_BASE, 4); 
  /* 地址映射:方向寄存器 */
  GPIO5_GDIR = ioremap(GPIO5_GDIR_BASE, 4);

/* 使能GPIO5时钟 */
  val = readl(CCM_CCGR1); /* 读出当前CCM_CCGR1配置值 */
  val &= ~(3 << 30);  /* 清除以前的设置 */
  val |= (3 << 30);  /* 设置新值 */
  writel(val, CCM_CCGR1);

/* 设置GPIO5_IO03的为IO模式 */
  writel(5, SW_MUX_GPIO5_IO03);
  
  /* 设置GPIO5_IO03方向为输出 */
  val = readl(GPIO5_GDIR); 
  val &= ~(1 << 3);   
  val |= (1 << 3);   
  writel(val, GPIO5_GDIR);
 }
 else
 {
  printk("This is not 100ask_IMX6ULL_Board!\n");
 }
 
 return 0;
}

/* 控制LED, which-哪个LED, status:1-亮,0-灭 */
static int board_demo_led_ctl (int which, char status) 
{
 int group, pin;
 unsigned int val;

group = GROUP(g_ledpins[which]);
 pin = PIN(g_ledpins[which]);
 printk("init gpio: group %d, pin %d\n", group, pin);

/* 100ask_IMX6uLL_Board LED:GPIO5_3 */
 if ((5 == group) && (3 == pin))
 {
  /* 点灯 */
  if (1 == status)
  {
   printk("<<<<<<<<led on>>>>>>>>>>\n");
   val = readl(GPIO5_DR);
   val &= ~(1 << 3); 
   writel(val, GPIO5_DR);
  }
  /* 灭灯 */
  else if (0 == status)
  {
   printk("<<<<<<<<led off>>>>>>>>>>\n");
   val = readl(GPIO5_DR);
   val|= (1 << 3); 
   writel(val, GPIO5_DR);
  }
  else{}
 }
 else
 {
  printk("This is not 100ask_IMX6ULL_Board!\n");
 }
 
 return 0;
}

硬件层1:board_A_led

这一层主要是一些资源及platform_device相关的代码。

核心代码:

Makefile文件

运行测试

首先把编译生成以下几个文件上传到板子里:

board_A_led.ko

chip_demo_gpio.ko

leddrv.ko

ledtest

这里我们使用百问网开发的100ask_imx6ull_flashing_tool工具来上传,如:

(0)

相关推荐

  • 从这些知识点入手,学单片机就简单多了

    自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题.对于追求开发速度的业务场景下,使用快速配置软件是合理的,高效的,但对于学生的学习场景下,更为重要的是知其然并知其所以 ...

  • 【精品博文】stm32F4----DHT22(AM2302)数字温湿度传感器读取(六)

    经过了自己用FPGA来驱动DHT22,http://blog.chinaaet.com/xzy610030/p/5100051014 下面开始用STM32F4来读取温湿度了. 首先非常感谢他人的原创, ...

  • 缺货涨价潮下,使用GD32替代STM32的体验

    使用GD替代ST之初体验 (GD32F450ZGT6替代STM32F407ZGT) A先说点废话 大家都知道,ST涨价厉害,单位的物料成本也是频频告急.网上一直传,什么完美替代,直接就能用.说不心动吧 ...

  • GPIO 软件框架

    GPIO 八种工作模式详解 接着上一篇的讲,我们上一篇研究了 GPIO 的硬件结构,其来源于 STM32 官方手册,研究了 GPIO 的八种工作模式和推挽输出及开漏输出原理,接下来我们研究 GPIO ...

  • 对通用输入输出GPIO的深入理解

    http://bbs.21ic.com/blog-804662-97083.html GPIO的各种模式     GPIO管脚可以被配置为多种工作模式,其中有3种比较常用:高阻输入.推挽输出.开漏输出 ...

  • 【Linux笔记】总线设备驱动模型

    Linux内核中更是存在着更多的分离.分层思想的代码,platform平台设备驱动就是用了这样的思想.本篇笔记我们一起来学习一下platform驱动框架. Linux引入platform的原因 对于 ...

  • 点灯大师带你写一个Linux字符设备驱动

    [导读] 前一篇文章,介绍了如何将一个hello word模块编译进内核或者编译为动态加载内核模块,本篇来介绍一下如何利用Linux驱动模型来完成一个LED灯设备驱动.点一个灯有什么好谈呢?况且Lin ...

  • (原创)家庭实验室:小实验——隔空驱动酒杯

    小实验--隔空驱动酒杯 日期:2017.10.08  星期日 实验人:马泽毅 实验材料:两只高脚红酒杯.两根火柴 .水 实验方法与步骤: 1.将手指用水沾湿. 2.取两只高脚红酒杯. 3.在一个玻璃杯 ...

  • N181.最简单可行的共振实验——隔空驱动酒杯 ||趣味科学实验

    一 [实验现象]  [实验视频] 二 [实验材料]                  两只高脚红酒杯.两根牙签 .水 三[ 实验步骤]     [第1步]将手指用水沾湿.    [第2步]取两只高脚红 ...

  • 计算机安装错误及分析,安装设备驱动时驱动提示错误“拒绝访问”的解决办法...

    现象:安装打印机驱动时系统出现错误提示:Windows 安装设备的驱动程序软件时遇到一个问题.Windows 已找到设备的驱动程序软件,但在试图安装它时遇到错误"拒绝访问".(如下 ...

  • LED显示屏恒流驱动、恒压驱动

    恒流是指在驱动IC允许的工作环境内,恒定的输出设计时规定的电流值:恒压是指在驱动IC允许的工作环境内,恒定的输出设计时规定的电压值. LED显示屏之前都是恒压驱动,随着技术的发展,恒压驱动逐渐被恒流驱 ...

  • 厚积薄发,我们一起学RTT UART设备驱动框架

    UART简介 STM32 芯片具有多个 USART 外设用于串口通讯,它是 Universal Synchronous Asynchronous Receiver and Transmitter 的缩 ...

  • 【Linux笔记】pc机_开发板_ubuntu互ping实验

    最近入手了一块百问网imx6ul开发板,一方面想系统性地学一次嵌入式Linux,争取下一份工作往这个方向混一口饭吃,另一方面也想用一用NXP的芯片. 本篇笔记分享的是:pc机_开发板_ubuntu互p ...

  • 【Linux笔记】LED驱动程序

    前言 学STM32我们从点灯开始,学Linux驱动我们自然也要点个灯来玩玩,尽量在从这些基础例程中榨取知识,细抠.细抠,为之后更复杂的知识打好基础. 与硬件无关的LED驱动 回顾hello驱动程序,我 ...