自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(136)
  • 论坛 (2)
  • 收藏
  • 关注

原创 linux设备驱动中的异步通知机制

前言异步通知的意思是:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,这一点非常类似于硬件上“中断”的概念,比较准确的称谓是“信号驱动的异步I/O”.信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。应用层实现...

2020-09-05 11:47:15 49

原创 移值linux3.4.2内核之内核裁剪

前言由上图可知,留给kernel分区的大小只有2M但是我们制作出来的内核已经超过了2M首先裁剪内核里无关的CPU/单板文件如上图所示,我们可以AT2440EVB单板去掉执行make menuconfig后按下’/’,进行搜索条目找到该配置选项的路径,然后选择对应单板相关的即可,其余可以去掉裁剪无关的文件系统ext2、ext3、ext4裁剪光盘文件系统CD-ROM进入File systems->CD-ROM/DVD Filesystems裁剪不常用的杂项文件系统进入F

2020-08-07 19:26:57 42

原创 移值linux3.4.2内核之修改分区

前言内核启动后的打印信息如下所示看到内核中有8个分区,但是我们的uboot只有4个分区修改内核分区我们搜索"Boot Agent"字段,可以发现在以上文件出现过,我们可以断定应该是要修改common-smdk.c文件,因为它是一个比较通用的文件,我们进去查看该文件,可以看到里面有个数组smdk_default_nand_part[],内容如下所示:所以我们必须修改该数组,修改为和我们uboot对应分区一致的分区布局上面部分宏的定义,如下所示:MTDPART_OFS_RETAIN: 填

2020-08-03 16:55:03 39

原创 移值linux3.4.2内核之框架及初步修改

前言先类比下Windows PC的启动流程,一上电后BIOS会去引导扇区读取系统引导程序引导windows内核的启动,内核启动过程中会去识别C盘,D盘,装载驱动程序,启动应用,对于嵌入式LINUX来说,BIOS称为Bootloader,它主要完成的工作有如下3步1.装载内核到内存中2.设置TAG参数3.启动内核,将参数传递给内核,r0=0,r1=机器ID,r2=TAG参数的地址内核启动中主要完成的工作有如下3步1.根据r1判断能该内核能否支持该机器,若支持的话调用相应的单板初始化函数2.装载

2020-08-03 13:01:54 34

原创 二叉树的线索化

前言线索化二叉树就是将二叉树转换为双向链表的过程,也就是从非线性到线性的转化,对于结点的先后访问次序每次都去遍历的话效率太低,所以得引入双向链表来反映某种二叉树的遍历次序,利用结点的right指针指向遍历中的后继结点,利用结点的left指针指向遍历中的前驱结点,那么如何在遍历时记录结点间的访问次序,我们可以使用队列来进行操作,遍历结束后队列记录了访问次序,循环访问队列连接队列中的结点,如下图所示...

2020-07-28 20:58:05 34

原创 二叉树的操作(三)

二叉树的比较与相加二叉树的克隆操作克隆操作就是将当前的二叉树复制一份出来,其复制接口的返回值为堆空间中的一颗新二叉树,这个二叉树的地址是不一样的,但是这颗树的其他属性和数据元素在对应位置都是相当的,接口的定义如下所示sharedPointer <BTree<T>> clone()const设计思路在堆空间里面先创建一个二叉树结点出来,然后把数据元素复制到新创建的二叉树结点中,接下来就递归的克隆左子树和右子树,然后指定左右子树的父亲,也就是新创建出来的结点,递归公式如下

2020-07-26 16:52:06 16

原创 二叉树的操作(二)

二叉树的属性操作1.二叉树结点的数目对于二叉树结点数目的计算需要用递归来解决,在node为根节点的二叉树中统计结点数目的递归公式如下所示 return 0; node == NULLcount(node) count(node->left)+count(node->right)+1; node!=NULL;代码如下:int count(BTreeNode<T>* node)const{

2020-07-24 22:07:32 21

原创 二叉树的操作(一)

二叉树的查找二叉树也有两种查找方式,一种是基于数据元素值的查找和基于结点的查找,之前说过通用树结构的查找,一样也是一个递归调用的过程,递归公式如下图所示值查找的递归公式基于值的查找virtual BTreeNode<T>* find(BTreeNode<T>* node,const T& value)const{ BTreeNode<T>* ret = NULL; if(node!=NULL) { if(node-&

2020-07-20 23:03:55 21

原创 在LCD显示摄像头图像

框架我们将从摄像头读到数据在LCD上显示,首先将摄像头数据读出到一块内存上,然后设置好LCD控制器从这块内存读取数据到LCD显示屏上,对于摄像头数据格式来说有YUV,MJPEG,RGB,而我们的LCD只支持RGB格式的数据格式,所以这里面还要将读取到的摄像头头数据进行一数据格式的转化,除了数据格式的转换外还需要分辨率的转化,如下图所示流程:...

2020-06-29 11:56:00 198

原创 LINUX驱动之IIC驱动

前言1.Linux的I2C体系结构分为3个组成部分1.1 I2C核心层提供了I2C总线驱动和设备驱动的注册,注销方法,I2C通信方法上层的即Algorithm)与具体适配器无关的代码以及探测设备,检测设备地址的上层代码等,主要用于提供统一的I2C操作函数1.2 I2C适配器层对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部,主要用于IIC设备的硬件操作1.3 I2C设备驱动层I2C设备驱动(也称为客户驱动)是对设备端的实现,设备一般挂接在受CPU控制的

2020-06-27 16:45:46 61

原创 二叉树的定义

前言定义:二叉树是由n(n>=0)个结点组成的有限集合,该集合或者为空,或者是由一个根结点加上两颗分别称为左子树和右子树的,互不相交的二叉树组成在此之前我们已经实现过了通用树结构,通用树结构中的每个结点都可以有任意多的孩子,都可能具有无线形态,所以很复杂,我们可以简化结点中孩子的数量,之前实现的通用树结构是用双亲孩子表示法来实现的,如下图所示,每个结点都有一个指向双亲的指针,每个结点都有若干个指向其孩子的指针除此之外还有一种树结构模型叫孩子兄弟表示法,如下图所示,每个结点都有一个指向其第一个

2020-06-25 09:30:00 109

原创 树的操作(三)

树的属性操作树的属性操作具体指的就是树中结点的数目,树的高度,树的度数等…1.树中结点的数目查找树中结点数目的操作是递归完成的,是递归就有递归出口,当结点为空或者结点的子链表长度为0时就为递归出口,上图就是递归公式的提炼,我们看到下图,要求出该树的结点数可以分为3个部分,count(B)表示求以B为根结点的树的结点数,count©表示求以C为根结点的树的结点数,count(D)表示求以D为根结点的树的结点数,看得count(A)的同时又用到count©这就是一个递归调用的过程代码演示int c

2020-06-21 23:52:03 32

原创 树的操作(二)

树的清除操作树这种数据结构可以看做是一种容器,树的清除操作就是将树中的所有结点清除,也就是释放堆中的结点,如上图所示,假设我们要将树中数据元素清除,可以先将根结点里面的每一棵子树给清除掉,最后再将根节点清除即可,在清除子树的时候又用到清除树的操作所以这是一个递归调用的过程,出口就是树只有一个根节点且没有子树,公式定义如下代码实现void free(GTreeNode<T>* node){ if(node!=NULL) { for(node->ch

2020-06-20 21:43:48 43

原创 树的操作(一)

树的查找在之前树的定义中我们可以知道,我们提供的查找操作有基于数据元素值的查找和基于结点的查找,树是一种非线性结构,当我们查找根据数据元素值查找时需要用到递归调用,从根节点出发自顶向下对子节点进行查找对于树中数据元素和结点的查找如下基于数据元素值的查找基于结点的查找插入操作对于插入操作有插入新结点和插入新元素两种操作,树是非线性的,无法采用下标的形式定位数据元素,每一个树结点都有唯一的前驱结点(父节点),因此,必须先找到前驱结点才能完成新结点的插入对于插入新结点的流程图如下所示对于插入数

2020-06-20 12:41:49 36

原创 树的定义

前言树是一种非线性的数据结构,树是由n(n>=0)个结点组成的有限集合,如果n=0称为空树,如果n>0则包含根结点,根结点只有直接后继,但没有直接前驱,除根以外的其他结点划分为m(m>=0)个互不相交的有限集合T0,T1…Tm-1,每个集合又是一颗树,并且称之为根的子树(sub tree),可以看出树也是递归的一种树中度的概念1.树的结点包含一个数据及若干指向子树的分支2.结点拥有的子树数目称为结点的度 度为0的结点称为叶结点 度不为0的结点称为分支结点3.树的度定义为

2020-06-18 09:40:30 59

原创 终端与控制台

前言我们知道一个进程的输入输出它是需要终端设备协助下才能去完成的,终端就是计算机外围设备,用来处理用户信息输入和结果输出,终端本身无计算能力,只是一个连接设备(如通过串口连接),后来将通过串口连接的各种设备都称为终端设备,比如串行端口终端:dev/ttySn,伪终端/dev/pty,虚拟终端/dev/tty,控制台/dev/console,对于控制台的概念如下图所示演变终端,控制台慢慢从硬件概念演化成软件概念,就是所谓的虚拟终端,使用软件来模拟以前的硬件终端设备,Linux系统中的6虚拟终端(tty

2020-06-13 12:22:23 58

原创 项目中的排序工程

前言struct Test : public Object{ int id; int data1[1000]; double data2[500];}..................Test t[1000]Sort::Bubble(t,1000,false);如上述代码所示,如果当待排数据元素为体积庞大的对象时,如何提高排序的效率,大家肯定会想到用更高效的排序方法来提高效率,但是发现效率的提高是微不足道的,问题的关键在于排序过程中不可

2020-06-12 15:20:08 47

原创 归并排序和快速排序

前言之前文章提到过的希尔排序它有划时代的意义,打破了一个认知——排序算法的复杂度不可能超过O(n*n),之后各种各样更高效的排序算法就开始出现了,比如这次文章中提到的归并排序和快速排序归并排序基本思想:将两个或者两个以上的有序序列合并成一个新的有序序列,有序序列V[0]…V[m]和V[m+1]…V[n-1]合并成V[0]…V[n-1],这种归并方法称为2路归并,以此类推,将多个有序序列归并为一个新的有序序列,称为多路归并,特别注意的是,要归并的序列必须是有序的,如下图所示,归并排序其实是一个递归调用

2020-06-12 13:07:52 63

原创 冒泡排序和希尔排序

冒泡排序基本思想每次从后向前进行(假设为第i次),j=n-1,n-2,…,i,两两比较V[j-1]和V[j]的关键字,如果发生逆序则交换V[j-1]和V[j]的值,如下图所示从无序序列区域最后一个元素开始冒泡,若发现逆序则交换元素,一次冒泡过后有序序列区域增加一个元素且仍有序下图是动画演示过程,Exchang用来标记无序序列是否已经有序,若已经有序则Exchang置为0避免再次冒泡比较浪费时间,时间复杂度为O(n*n)且是稳定排序代码演示 template <typename T&gt

2020-06-11 17:37:10 172

原创 选择排序和插入排序

前言所谓排序就是计算机内经常进行的一种操作,其目的就是将一组"无序"的数据元素调整为"有序"的数据元素,排序也存在稳定性的定义:如果在序列中有两个数据元素R[i]和R[j],它们的关键字(排序的依据)K[i]==K[j],且在排序之前,对象R[i]排在R[j]前面,如果在排序之后,对象R[i]仍在对象R[j]的前面,则称这个排序方法是最稳定的,否则称这个排序方法是不稳定的,在排序中也有多关键字排序,所谓多关键字排序就是有多个排序依据,且它们的优先级不同,当优先级相同时则看一下关键字,对于多关键字排序,只要

2020-06-11 12:31:48 47

原创 git学习篇之文件操作

忽略文件有些文件不必提交到版本库中,如可执行文件,日志文件,临时文件,库文件,在工作目录下手动创建.gitignore文件,如以下所示我们忽略.bin文件的提交从下图可以看出我们.bin文件就被忽略,检查不到.bin的变化,但是.o,.a文件没有被忽略所以能够看到变化下面我们把.o,.a文件给忽略掉再次查看git状态,可以看出.a,.o文件已经被忽略下图是忽略匹配规则撤销修改在版本提交的过程中我们可能会做出错误的修改,提交到版本库中撤销工作区的修改对工作区的readme进行

2020-06-10 16:49:13 38

原创 I/O缓存与内存映射

前言一般来说我们的CPU速度是比较快然而磁盘速度明显是低于CPU的,所以引入了缓存来解决这种速度上的差异,计算中的缓存无处不在,如上图所示,缓存就是为了缓和两个模块之间速率的冲突,也就是说我们去读写磁盘的时候可以将磁盘上的数据先放到缓存中,我们CPU去读写硬盘数据的时候不会去直接读取硬盘的数据而去缓存中读写,在应用层也存在缓存,比如我们在接受串口数据的时候可以开辟一个环形缓冲区来缓存串口的数据,这是在嵌入式系统设备中常有的做法,其目的都是为了更高效的运行页高速缓存页缓存是操作系统层面的概念,其英文

2020-06-07 18:07:30 99

原创 递归的思想与应用

前言递归是一种数学上分而自治的思想,将原问题分解为规模较小的问题进行处理,分解后的问题与原问题的类型完全相同,但规模较小,通过小规模问题的解,能够轻易求得原问题的解,但是问题的分解是有限的,当边界条件满足时,递归结束直接求解否则递归继续进行,在程序设计中递归函数就是递归的体现,递归模型的一般表示法如下递归思想的应用1.求解:Sum(n) = 1 + 2 + 3 +…+ n#include <stdio.h>#include <stdlib.h>unsigned int

2020-06-05 17:59:28 50

原创 多维指针和多维数组

多维指针指针的本质是变量,指针会占用一定的内存空间,可以定义指针的指针来保存指针变量的地址值,即二级指针,那为什么需要指向指针的指针呢?因为指针的本质也是变量,对于指针也同样存在传值调用与传址调用1.二级指针#include <stdio.h>#include <stdlib.h>int reset(char **p,int size,int newsize){ int ret = 1; int i = 0; int len = 0;

2020-06-05 13:47:27 35

原创 函数与指针分析

前言C语言中的函数有自己特定的类型,函数的类型由返回值,参数类型和参数个数共同决定,比如 int add(int i,int j)的类型为int(int,int),C语言中通过typedef为函数类型重命名typedef type name(parameter list)例如typedef int f(int,int);typedef void p(int);深入分析函数指针就是一个指向函数的指针,可以通过函数类型定义函数指针:FuncType pointer,也可以直接定义type (po

2020-06-04 22:15:03 92

原创 数组参数和指针参数

前言我们都知道C语言中的数组参数会退化为指针,那有没有想过为什么呢?由于C语言当初开发是为UNIX操作系统的,对于操作系统来说效率是非常重要的,当参数传递的时候如果拷贝整个数组执行效率将大大下降而且参数位于栈上,太大的数组拷贝将导致栈溢出,所以会将数组名看做常量指针传数组首元素地址,其实二维数组参数同样存在退化的问题,二维数组可以看做是一维数组且每个元素是一维数组,如下void f(int a[5])<->void f(int a[])<->void f(int *a)void

2020-06-04 18:17:30 52

原创 数组指针和指针数组

数组指针C语言中的数组有自己特定的类型,数组的类型由元素类型和数组大小共同决定,例如int array[5]的类型就为int [5],也就是说array这个数组名所代表的数组它的元素类型为int,数组大小为5个元素,C语言中通过typedef为数组类型重命名,如下所示数组类型:typedef int(AINT5)[5];数组定义:AINT5 iArray数组指针用于指向一个数组,数组名时是数组首元素的起始地址,但不是数组的起始地址,通过将取地址符&作用于数组名可以得到数组的起始地址,可

2020-06-04 13:10:13 22

原创 指针和数组的分析

前言:数组是一段连续的内存空间,数组的空间大小为sizeof(array_type)array_size,数组名可看做指向数组第一个元素的常量指针* ,指针是一种特殊的变量,与整数的运算规则为p+n等价于(unsigned int)p+n*sizeof(*p),指针之间只支持减法运算,参与减法运算的指针类型必须相同,即p1-p2等于((unsigned int)p1 - (unsigned int)p2)/sizeof(type),特别注意的是只有当两个指针指向同一个数组的元素时,指针的相减才有意义,指针

2020-06-04 00:18:50 66

原创 ASOC框架(二)

前言在前面ASOC框架(一)我们知道ASOC被分为Machine,Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的代码,ASoC的一切都从Machine驱动开始,包括声卡的注册,绑定Platform和Codec驱动等等,我们之前说过写一个ALSA声卡驱动的步骤有如下三步:1 . snd_card_create 2 . 初始化:创建逻辑设备 snd_pcm_new3 . snd_card_register我们说过AS

2020-05-26 20:16:24 36

原创 ASOC框架(一)

前言ASoC–ALSA System on Chip,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系,我们使用ASOC框架的话就不用调用snd_card_create等函数来创建我们的声卡,目前已经被整合至内核的代码树中:sound/soc,ASOC把声卡的驱动分为三部分,分别为machine,platform,codec如上图所示,我们对machine,platform,codec三部分做简要的介绍machine:单板相关,表明platform

2020-05-26 16:56:57 44

原创 ALSA声卡原理介绍及其框架

声卡原理介绍ALSA是Advanced Linux Sound Architecture 的缩写,目前已经成为了linux的主流音频体系结构, 在内核设备驱动层,ALSA提供了alsa-driver,同时在应用层,ALSA为我们提供了alsa-lib,应用程序只要调用 alsa-lib提供的API,即可以完成对底层音频硬件的控制,内核空间中,alsa-soc其实是对alsa-driver的进一步封装,他针对嵌入式设备提供了一系列增强的功能.从alsa在linux中的设备文件结构如下图所示,我们可以看到

2020-05-25 12:06:25 43

原创 使用C语言实现协程

前言协程是一个比较新的概念,它的使用场景越来越广泛,一些服务器的后台,高并发的场景,有时候就会就会用到协程,协程简单理解就是对进程,线程的一些改进和优化,其实对于线程也存在一定的开销,其包括创建,销毁,上下文切换,同步,条件变量,读写锁都涉及到用户态到内核态之间的切换,协程的改进点在于它调度开销小,不存在同步,死锁,资源竞争等问题,这是因为协程的调度是由我们用户态自定义完成的,是主动调度,而进程和线程的调度由内核完成,是被动调度,对于C语言来说有不少的协程库,比如libtask,libco,libgo,实

2020-05-24 14:49:22 241

原创 CMOS摄像头硬件原理

前言如上图所示,此过程为视频数据流的流向过程,输入信号为自然景观等的模拟信号,输出信号为RAW RGB格式或者YUV格式的数字信号,RGB和YUV是两种完全不同的颜色空间,它们之间可以相互转换,而且图像的分辨率主要有VGA(640480),QVGA(240320),CIF(352288)三种, 或者更低的分辨率,下面我们看下摄像头的数据手册参数1.重要参数讲解active array size: 摄像头的有效感光阵列的大小,为656488,即30w像素len sizes: 镜头的大小为1/5寸

2020-05-20 15:06:52 175

原创 USB摄像头驱动之设置属性

前言对于摄像头的属性有亮度,曝光度等等…,那怎么去获得/设置这些属性呢,在应用层使用ioctl命令:VIDIOC_QUERYCTRL,VIDIOC_G_CTRL,VIDIOC_S_CTRL来查询,获取,设置当前摄像头的属性,所以在底层驱动中中我们必须来实现这些函数的定义,该函数原型如下int (*vidioc_queryctrl)(struct file *file, void *fh,struct v4l2_queryctrl *a);int (*vidioc_g_ctrl)(struct fil

2020-05-16 22:28:19 160

原创 System V IPC(二)

System V 消息队列数据结构struct msqid_ds { struct ipc_perm msg_perm; /* Ownership and permissions */ time_t msg_stime; /* Time of last msgsnd(2) */ time_t msg_rtime; /* Time of last msgrcv(

2020-05-15 19:07:25 29

原创 System V IPC(一)

1 前言如上图所示是System V IPC相关的接口表,System V IPC未遵循“一切都是文件”的Unix哲学,而是采用标识符ID和键值来标识一个System V IPC对象.每种System V IPC都有一个相关的get调用(表中的“创建或打开对象”一行),该函数返回一个整型标识符ID,System V IPC后续的函数操作都要作用在该标识符ID上.System V IPC对象的作用范围是整个操作系统,内核没有维护引用计数.调用各种get函数返回的ID是操作系统范围内的标识符,对于任何进程,

2020-05-15 16:15:33 43

原创 UVC摄像头驱动程序框架

前言USB video class又称为USB video device class or UVC就是USB device class视频产品在不需要安装任何的驱动程序下即插即用,包括摄像头,数字摄影机,模拟视频转换器,电视卡及静态视频相机,V4L2就是用来管理UVC设备的并且能够提供视频相关的一些API摄像头插入后内核打印出此信息,这是UVC机制的支持,即插即用不用我们自己写usb的驱动程序根据此信息可以定位到drivers\media\usb\uvc\uvc_driver.c文件,该层为硬件相关

2020-05-13 10:35:40 100

原创 __V4l2(VideoForLinuxVersion2)框架

前言__V412术语的意思是:video for linux version2,是Linux内核中关于视频设备的内核驱动框架,为上层的访问底层的视频设备提供了统一的接口.凡是内核中的子系统都有抽象底层硬件的差异,为上层提供统一的接口和提取出公共代码避免代码冗余等好处.,我们的摄像头驱动程序是属于字符设备驱动程序,对于复杂的字符设备驱动程序它引入了分层的概念,在我们之前写过的LCD驱动文章就是利用这种分层的概念,如下图所示,上一层的fbmem.c构造了一个fops结构体,里面有打开,读写函数,注册该结构体,

2020-05-12 11:35:49 96

原创 进程间通信---管道

前言管道是最早出现的进程间通信的手段,比如我们在shell执行命令时经常会将上一个命令的输入作为下一个命令的输入就是通过管道来实现的,如下图,进程who的标准输出,通过管道传递给下游的wc进程作为标准输入,从而通过相互配合完成了一个任务,读取管道内容是消耗型的行为,即一个进程读取管道内的一些内容后,这些内容就不会继续在管道之中了管道的作用是在亲缘关系的进程之间传递信息,所谓有亲缘关系,是指有一个共同的祖先,所以管道并非只能用于父子进程之间,也可以用在兄弟进程之间,还可以用于祖孙之间甚至叔侄进程之间,总

2020-05-10 12:04:27 38

原创 设备树的中断

中断的概念对于中断流程不了解的伙伴可以去看看我之前写过的文章,点击文章的链接出,我这里简单描述下,一般来说,中断是属于异常的一种,但是中断是可以屏蔽的,对于异常它是不可以屏蔽的,如下图所示,对于中断我们需要设置其中断源,图中的按键,定时器,网络数据…就是会触发中断的中断源,我可以在中断控制器中设置其是否屏蔽该中断,而对于异常部分一般是系统的出错,这种出错必须告知CPU,所以是不可以屏蔽的,当发送...

2020-05-06 13:29:54 55

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人 TA的粉丝

提示
确定要删除当前文章?
取消 删除