从裸机编程到嵌入式Linux编程思想的转变------分而治之:驱动和应用程序
笔者学习嵌入式Linux也有一段时间了,很奇怪的是很多书讲驱动编程方面的知识,也有很多书将ARM9方面的知识,但是从以前51形式的(对寄存器直接操作,初始化芯片的功能模块)编程方法,和思维模式,变换为基于Linux操作系统编程,讲这个思想转变的书几乎没有,让初学者走了很多弯路,撞了很多难墙。
笔者因此写上自己的学习心得,希望能给和我一样转变做嵌入式Linux这块的朋友一点帮助,早点入门,于愿足矣。
让我们一起回顾一下51形式的编程方法,以一个简单的LED例子:通过串口向其发送一串指令,让LED灯闪烁,闪烁频率由串口发送的指令决定。
于是我们开始编程:一开始各种初始化晶振,初始化要用的功能模块:UART,GPIO,定时器。那么就会通过设置寄存器的各种位,把UART配置为中断模式,GPIO对应的LED引脚为输出模式,用于控制LED灯的暗灭,最后初始化定时器,来控制暗灭的频率。相信有过嵌入式裸机编程经验的朋友们一定都觉得这很简单,但是如果跑上了操作系统,那又应该怎么办?
嵌入式Linux分为驱动层和应用程序层。什么意思?大家一定偶尔听过,对Linux设备的操作就像操作文件一样简单,打开,写入,关闭。听起来是很简单,听完就算了,也不知道到底说什么。
驱动层就相当于我们在51形式编程中的初始化功能模块,在Linux中,已经把所有函数封装好了。举例:笔者用的at91sam9260的芯片,现在我要把PB1 引脚设置为输出模式,且初始值为低电平,则调用系统封装好的函数:
- at91_set_gpio_output(AT91_PIN_PB1, 0);
这个函数位于Linux内核源代码 arch/arm/mach-at91,(我用的是at91的芯片)要用到什么函数进去找。在arch/arm下有很多文件夹,以后需要自己根据自己的需求去选择相应的芯片找函数,这个笔者认为是Linux不人性化的地方,需要改进,只有有经验的工程师才能轻松找到,初学者真的要费很大精力。
而我们那些晶振时钟初始化就不用写了,在Linux操作系统运行的时候已经帮你初始化好了。还有串口也已经初始化好了,在Linux有专门的操作函数,大家可以看看Linux下串口操作的相关资料,这里不赘述。当然驱动层完成的还不只这些工作,剩下的工作在讲玩应用程序层之后再介绍。
应用程序层:这是一个完全与硬件无关的层次,就相当于我们51形式编程的逻辑层一样。那么我们怎么和驱动层打交道呢?大家回忆那句话:像操作文件一样,操作硬件设备。没错,我们就是操作文件。每个硬件设备驱动会有一个设备文件(一般要手动生成,自动生成要在驱动中写好也行)。例如我们为LED灯取一个设备文件名字为leds,然后在dev/leds生成这个设备文件,应用程序用open方法打开文件后,得到文件描述符fd,那么以后操作LED这个设备就是操作这个fd。
- fd = open (“dev/leds”, flags);
到底怎么操作fd才能像操作文件一样操作硬件设备呢?就是命令机制!通过一个非常重要的函数ioctl。看过我上几篇文章的朋友们一定知道这个函数,这就是应用程序和驱动程序的接口之一。
假设我们定义了命令 LED_ON和LED_OFF(定义命令的方法见前几篇文章),那么我们要让LED闪烁,在应用层只要写:
- while(1)
- {
- ioctl(fd,LED_ON);
- sleep(1);
- ioctl(fd,LED_OFF);
- sleep(1);
- }
是在应用层看来这个是不是很简单?但是却苦了驱动层了。刚刚说到驱动层做的事情不只是初始化模块功能,不错她还有一个功能就是完善ioctl,根据相应的命令进行相应的动作。(ioctl是比较复杂的,这里只是举了一个最简单的例子,朋友们还是要多看一些书籍和实验),这里是不是连定时器的初始化都不用我们自己写,直接调用系统的休眠函数来达到延迟的目的咯~~~
让我们再次回到驱动层,驱动层就要完善这个ioctl了,因为驱动层可以直接对硬件操作,让输出高电平和低电平。
驱动的操作就比较复杂了,这里只能简单讲下概念了,因为这时已经是Linux设备驱动开发的内容了。
关于Linux设备驱动的总结文章,会在以后再写,建议大家可以看看国嵌的Linux视频,在电驴上资源很多,很多关于设备驱动开发的视频,搜的时候关键字为:嵌入式Linux
这篇文章的主要目的是让大家思想上从51形式的编程转变到嵌入式Linux编程思想,希望大家能转变过来思想,踏入嵌入式Linux之门!
从裸机编程到嵌入式Linux编程思想的转变------分而治之:驱动和应用程序的更多相关文章
- 基于嵌入式Linux的千兆以太网卡驱动程序设计及测试
一. 引言 千兆以太网是一种具有高带宽和高响应的新网络技术,相关协议遵循IEEE 802.3规范标准.采用和10M以太网相似的帧格式.网络协议和布线系统,基于光纤和短距离同轴电缆的物理层介质,更适用于 ...
- 韦东山嵌入式Linux学习笔记02--如何给开发板烧录程序
购买韦东山嵌入式开发板jz2440 v3会标配两根usb线和一根网线,OpenJtag需要单独购买, 我暂时还没买到该工具. 下面介绍usb烧录以及通过网线烧录程序. 1.usb烧录程序: 借助DNW ...
- C语言嵌入式系统编程修炼
C语言嵌入式系统编程修炼 2008-08-19 作者:宋宝华 来源:天极网 C语言嵌入式系统编程修炼之背景篇 本文的讨论主要围绕以通用处理器为中心的协议处理模块进行,因为它更多地牵涉到具体的C语言编程 ...
- C语言嵌入式系统编程修炼之一:背景篇
不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言开发过程的复杂性,它并不是嵌入式系统开发 ...
- 嵌入式linux启动信息完全注释
嵌入式linux启动信息完全注释 from:http://www.embedlinux.cn/ShowPost.asp?ThreadID=377 摘要 我们在这里讨论的是对嵌入式linux系统的启动过 ...
- 作为一个新人,怎样学习嵌入式Linux,(韦东山)
很早以前在网上看到的韦东山老师写的文章,复制到自己的博客,方便自己以后看. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学到什 ...
- 作为一个新人,如何学习嵌入式Linux?
作为一个新人.如何学习嵌入式Linux?我一直在问太多次,特写文章来回答这个问题. 在学习嵌入式Linux之前.肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会).C语言要 ...
- 作为一个新人,怎样学习嵌入式Linux
作为一个新人,怎样学习嵌入式Linux?被问过太多次,特写这篇文章来回答一下. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学 ...
- 嵌入式Linux内核tasklet机制(附实测代码)
Linux 中断编程分为中断顶半部,中断底半部 中断顶半部: 做紧急,耗时短的事情,同时还启动中断底半部. 中断底半部: 做耗时的事件,这个事件在执行过程可以被中断. 中断底半部实现方法: taskl ...
随机推荐
- javascript:类数组 -- 对象
在javascript中,对象与数组都是这门语言的原生规范中的基本数据类型,处于并列的位置. 类数组:本质是一个对象,只是这个 对象 的属性有点特殊,模拟出数组的一些特性. 一般来说,如果我们有一个 ...
- Linux find查找指定文件 按照名称 然后cp拷贝到指定目录且指定文件名
最近有一个需求,需要将指定目录下的文件(已知文件名)复制到另一个指定的目录且重命名文件. 要求: 在var目录下会定义系统的启动日志相关信息,请查找对应的boot.log文件,并把它备份一份到var/ ...
- Java程序流程控制:判断结构、选择结构、循环结构
本文内容: 判断结构 if 选择结构 switch 循环结构 while do-while for for each break.continue return 首发时间:2017-06-22 21: ...
- Python笔记(十):正则表达式
正则表达式对比工具 https://pan.baidu.com/s/1XIPyF1vFSj5PACPx9zW8_g (一) 正则表达式符号和特殊字符 符号 说明 示例 | 或 re1|re2 ...
- CSS 小结笔记之变形、过渡与动画
1.过渡 transition 过渡属性用法: transition :ransition-property transition-duration transition-timing-func ...
- LeetCode题解之Max Consecutive Ones
1.题目描述 2.问题分析 遍历一次数组,以每个1 为起点向后数,数到0 时比较当前1的个数和最大1 的个数,然后将遍历的起点放到当前0 的后面. 3.代码 int findMaxConsecutiv ...
- 使用MonkeyTest对Android客户端进行压力测试
目录 monkey命令简介 monkey命令参数说明 自动化实例 如何通过日志定位问题 1.monkey命令简介 Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它 ...
- pyhon类继承
1,python类的继承 class A(object): name ='eason' age = '22' def __init__(self): print '我是A的构造函数!!!' def g ...
- Sql Server 中如果使用TransactionScope开启一个分布式事务,使用该事务两个并发的连接会互相死锁吗
提问: 如果使用TransactionScope开启一个分布式事务,使用该事务两个并发的连接会互相死锁吗? 如果在.Net中用TransactionScope开启一个事务. 然后在该事务范围内启动两个 ...
- [CentOS7] [VMWARE] 增加磁盘空间后扩大逻辑分区
Learn to rescan disk in Linux VM when its backed vdisk in vmware is extended. This method does not r ...