自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(36)
  • 收藏
  • 关注

原创 Uboot

NXP官网下载原始Uboot,配置ARCH和CROSS_COMPILE后编译配置1、u-boot.bin .bin文件不可以直接烧到Flash中,必须需要先添加头部文件形成u-boot.imx(镜像文件)。u-boot编译最后会通过/tools/mkimage软件添加头部信息,生成u-boot.imx。

2022-12-08 22:29:40 444 1

原创 CAN总线:Controller Area Network

不同速度的CAN总线可以通过链接(延长距离)和转换(传输速度)。CPU和CAN控制器是一体的,外接收发器芯片如Tja1050/82c250;如果没有CAN控制器,外扩一个MCP2515(SPI)或Sja1000。组网:1、环路:两端接上120Ω的匹配电阻;2、开环:终端接上120Ω的匹配电阻。

2022-11-27 22:10:58 410

原创 UART、I2C、SPI

在Linux中,操作设备的统一接口就是:open/read/ioctl。行规层(Line discipline):接受驱动程序的数据,再传递给应用程序;它可以对数据进行处理,如回写等。UART编程套路:1、open。2、设置行规层:波特率、数据位、停止位、校验位、RAW模式,有数据就返回。。可以使用ioctol,但是已经封装好了函数。

2022-11-20 17:02:20 417

原创 嵌入式Flash设备的文件系统:jffs/jfss2和yasffs/yasffs2

任何flash器件的写入操作只能在空或者已擦除的单元进行,在进行写入操作之前需要执行擦除。

2022-11-13 21:05:31 560

原创 文件系统(initramfs中间过渡用文件系统)

Linux内核启动 ------- initrd/initramfs(包含有根文件系统的设备驱动)------- Real Root Filesystem。

2022-11-06 21:06:59 566

原创 制作文件系统

1、启动初始函数init() —— 读取inittab中的动作 —— 没有inittab启用/etc/init.d/rcS—— 应用2、所以可以修改rcS(不仅仅是脚本也可以是C)定制系统。

2022-10-17 20:32:37 584

原创 Ubuntu和开发板的初始设置

需要两个网卡:一个桥接模式用于外网通讯;NAT用于和开发板通讯。TFTP服务安装NFS服务。

2022-10-12 21:10:43 133

原创 Qt交叉编译工具链

主要是到/Qt5.12.9/Tools/QtCreator/bin/qtcreator.sh里。这里只是添加了一个C++的编译器,实际上有很多编译器,根据需要取用。就是交叉编译工具链;注意现在使用的还不是它,是默认的。拷贝至Ubuntu,修改权限后直接运行。也就是使能的那个交叉编译软件。把之前配置的信息整合在一起。目录下,该目录有如下内容。该版本名称只是为了好找。防止引用别的环境变量。

2022-09-18 22:12:36 1145 1

原创 交叉编译工具链

默认当前路径下,可指定链接时库文件在哪?系统目录:交叉编译工具链的某个lib目录;运行时库文件在哪?就是板子上/lib、/usr/lib目录,运行程序用环境变量LD_LIBRARY_PATH指定。缺啥补啥在编程过程中,程序代码往往被拆成很多部分,每部分放在一个独立的源文件中,而不是将所有的代码放在一个源文件中。考虑一个简单的小例子:程序中有两个函数main()和abc()。main()函数位于main.cpp,abc()函数位于abc.cpp,main()函数中调用abc()函数。

2022-09-18 20:53:58 4914

原创 GPIO与IOMUX

比如和UART、IIC、SPI等外设相连作为通信外设的接口引脚,和定时器相连作为PWM输出引脚,等等。GPIO模式由IOMUX确定,由GPIO_GDIR确定输入还是输出;该功能由CPU内外设提供,具体是什么功能由IOMUX单元(I/O复用选择器)控制。以实例GPIO1组下端口IO1为例:Pad为GPIO1_IO01,模式为ALT5。• 使能核心通过读取pad寄存器对应的采样输入通讯信号(GPIO_PSR).当为输入模式bit=0,对应输入情况由GPIO_PSR位读取确定。但是,I/O引脚不仅和。...

2022-08-17 13:49:02 6731

原创 Linux信号驱动IO-SIGIO

Linux中的信号:由内核发送给应用程序处理方式:忽略:接收到信号后不做任何反应捕获:用自定义的信号处理函数来执行特定的动作(注册响应函数)默认:接收到信号后按系统默认的行为处理该信号,如Ctrl+C。给signum这个信号注册一个处理函数。内核能够接受用户层的信号注册函数需要支持Fasync方法,于file_operations里定义。实际使用实例fasync_helper:该函数负责启动fasync队列等,说白了就是初始化的必须;fasync_struct:它的作用就是储存内容的列表,

2022-08-15 22:49:38 736

原创 线程池的实现

notEmpyt是消费者的条件变量,notFull是生产者的条件变量;是相互控制的生产消费模型。对taskQ的添加删减都是循环列表,需要对总容量取余数。阻塞与否的判断条件都是队列是否满了。

2022-07-27 14:11:26 853 1

原创 多线程与线程同步(锁)

/初始化intpthread_cond_init(pthread_cond_t*restrictcond,constpthread_condattr_t*restrictattr);//销毁释放资源intpthread_cond_destroy(pthread_cond_t*cond);cond条件变量的地址attr条件变量属性,一般使用默认属性,指定为NULLcond内部包含着那些被阻塞线程的信息。..................

2022-07-16 22:11:27 541 1

原创 虚拟内存的结构

在用户空间中也有一些特殊的空间有特殊的用处,而应用程序能用的内存空间是如下的“默认区域”:于维护函数调用的上下文,离开了栈,函数的调用就办法实现了。栈通常在用户更高的地址空间处分配,通常有数兆字节的大小。栈主要用来存放局部变量,函数调用时会在栈上有一系列的保留现场(保存上下文)及传递参数的操作。堆用来容纳应用 程序动态分配的内存区域,当程序 使用malloc或new 的时候就是得到来自堆中的内存。堆统称在栈的下方(低地址方向,但是不是紧邻的)。堆一般比栈要更大一点,一般会达到几十甚至是数百兆字节。比如:

2022-07-05 21:15:00 741

原创 epoll

本质上红黑树 :节点多或少不影响epoll的效率。epoll 使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的 copy 只需一次。epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是 事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))优点1、select和poll工作过程中存在内核/用户空间数据

2022-07-02 22:18:15 444 1

原创 epoll的边沿触发的多线程

服务器的并发本质上都一样,都是将创建连接、收发数据的功能分配给子线程;父线程仅负责while循环下进行检测1、完成服务器的设置;2、创建epoll树和监听的epoll实例;3、完成while循环,并把参数传递给子进程。............

2022-07-02 20:53:20 230

原创 多线程select并发

父进程  负责监听,处理客户端的连接请求,也就是在父进程中循环调用 accept() 函数;  创建子进程:建立一个新的连接,就创建一个新的子进程,让这个子进程和对应的客户端通信;  回收子进程资源:子进程退出回收其内核 PCB 资源,防止出现僵尸进程。子进程  负责通信,基于父进程建立新连接之后得到的文件描述符,和对应的客户端完成数据的接收和发送;  与客户端建立链接;  收发数据:send() / write(),recv() / read()。1、创建线程:注意,第三个参数是void *

2022-06-28 22:56:18 1182

原创 I/O 多路复用select、poll

I/O 多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是 读就绪 或者 写就绪 ),能够通知程序进行相应的读写操作。select 、 poll 和 epoll 是 Linux API 提供的 I/O 复用方式。.本质上就是,把本应该由程序员的事情交给内核负责:检测这些读写缓冲区是否可用(需要调用阻塞函数);检测一轮以后内核将可操作的fd告诉我们,我们再去操作就不会再阻塞。服务器包含两种文件描述符,每一个都有两个缓存区:1、监听LFD:用于标志是否有数据是否能够读写数据

2022-06-28 13:39:39 496 2

原创 等待队列和阻塞的实现——wait queue

堵塞主要就是依赖于等待队列。阻塞接口condition为条件表达式,当 wake up 后, condition 为真时,唤醒阻塞的进程,为假时,继续睡眠。举例:应用程序调用read函数,read函数间接调用了wait_event;condition为0就是阻塞等待。举个栗子:实现阻塞以字符设备为例,在没有数据的时候,在 read 函数中实现读阻塞,当向内核写入数据时,则唤醒阻塞在该等待队列的所有任务。用户层注意: memset(buf,0,1024)会将buf的内存置为0(二进制下的0

2022-06-26 14:06:23 672 1

原创 Linux—IO模型

只要具有输入输出类型的交互系统都可以认为是 I/O 系统Input:输入数据到内存中Output:输出数据到IO设备(磁盘 、 网络等需要与内存进行数据交互的设备)中阻塞:不占用资源CPU,在原处休眠,等待数据唤醒。并不会等待函数的返回值;如果没有数据返回,执行其他任务。缺点:任务完成的响应延迟增大了,因为每过一段时间才去轮询一次 read 操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。当执行别的任务是来了数据,会无法读到数据。举个栗子:一个人十个杆子钓鱼,人正常在休眠,鱼

2022-06-25 21:02:06 485

原创 操作系统内存管理

内存管理主要解决:如何使进程的地址空间隔离,如何提高内存的使用效率,如何解决程序运行时的重定位问题?引入虚拟地址层。 每个程序都有其独立的虚拟的独立的进程地址空间,可以看到程序A和B的虚拟地址空间都是从0x00000000开始的。我们将两块大小相同的虚拟地址空间和实际物理地址空间一一映射,即虚拟地址空间中的每个字节对应于实际地址空间中的每个字节,这个映射过程由软件来设置映射的机制,实际的转换由硬件来完成。 1、解决地址空间隔离:比如A访问超过0x00A0000的虚拟地址,内核就会拒绝它; 2、解决重

2022-06-25 14:37:07 1779

原创 内核态和用户态

1、执行内核空间的代码,具有ring 0保护级别,有对硬件的所有操作权限,可以执行所有CPU 指令集,访问任意地址的内存,在内核模式下的任何异常都是灾难性的,将会导致整台机器停机2、在用户模式下,具有ring 3保护级别,代码没有对硬件的直接控制权限,也不能直接访问地址的内存,程序是通过调用系统接口(System Call APIs)来达到访问硬件和内存,在这种保护模式下,即时程序发生崩溃也是可以恢复的,在电脑上大部分程序都是在,用户模式下运行的每个进程的 4G 虚拟空间地址,高位 1G 都是一样的,即内核

2022-06-24 14:54:17 439

原创 内核自旋锁

锁一般都是用来保护一个临界资源(大抵是全局静态变量这种)的,防止一个在访问时,另外一个程序也来访问一般使用于运行和等待时间较短的内核当发生访问资源冲突的时候,可以有两种锁的解决方案选择:一个是原地等待 一个是挂起当前进程,调度其他进程执行(睡眠)。Spinlock 是内核中提供的一种比较常见的锁机制,自旋锁是“原地等待”的方式解决资源冲突的,即:一个线程获取了一个自旋锁后,另外一个线程期望获取该自旋锁,获取不到,只能够原地“打转”(仍然占用CPU,并不是休眠:忙等待)。所以自旋锁不会导致线程状态的切

2022-06-22 21:08:39 349

原创 内核原子操作、互斥锁、信号量

信号量是在并行处理环境中对多个处理器访问某个公共资源进行保护的机制, mutex 用于互斥操作。mutex 的语义相对于信号量要简单轻便一些,在锁争用激烈的测试场景下, mutex 比信号量执行速度更快,可扩展性更好,另外 mutex 数据结构的定义比信号量小。进入临界区,访问全局变量列表等时,必须先申请锁才有资格访问修改;如果申请不到程序进入休眠。互斥锁是用来保护两个锁之间的:在解锁之前的(全局)变量不会被修改和访问的。mutex_lock (struct mutex*)为指定的 mutex 上锁,

2022-06-21 20:17:50 290

原创 使用register_chdev注册多个次设备号

1、内存分配kmalloc返回是无类型指针;pmydev[i]是struct mydev的指针;2、设备号分配和储存利用cdev结构体中dev_t dev来储存主次设备号;register_chrdev和hello_class已经在sys下创建了对应目录了;device_create 第三个参数是需要使用次设备号的,这点和cdev_add不一样 (cdev_add(&cdev,devno,2);只在意主设备号,第三个参数来设定次设备号);设备创建完之后由udev在/dev下创建设备节点。3、open

2022-06-21 11:29:35 352

原创 部分操作命令

输出目前已经安装的模块输出模块信息可以进入所创建的设备类中,可以查看类下module可以查看已经安装的模块。

2022-06-21 10:05:02 26

原创 file、inode支持多位次设备号

1、inode是随着设备节点伴生的,每一个设备节点对应一个硬件,i_rdev包含有主次设备号信息;2、可以发现open时,有两个参数inode和file,由于inode含有主次设备号,因此open可以利用inode区分次设备号的不同;3、file结构体在inode之外还提供一个成员,可以去表征次设备号;所以open需要将inode资源信息(次设备)存入file的private_data。核心:通过一个的数组存放cdev数组的定义以及初始化1、cdev是关键;不同的mydev会有不同的cdev;cde

2022-06-19 12:09:25 192

原创 ioctl

ioctl

2022-06-18 11:10:56 189

原创 write、read

filp:待操作的设备文件file结构体指针;buf:待写入所读取数据的用户空间缓冲区指针;count:待读取数据字节数;f_pos:待读取数据文件位置,读取完成后根据实际读取自救书重新定位;__usr:是一个空的宏,主要用来显示的告诉程序员它修饰的指针变量存放的是用户空间地址。hello_drv.ctest.c1、kernel_buf是定义在内核中,buf是定义在用户空间的,两者不相通;2、参数struct file *file是用于管理进程打开的文件,当open时会被创建;打开的设备

2022-06-16 14:18:38 245 1

原创 自动创建设备节点

设备符号简易

2022-06-15 16:50:31 924 1

原创 字符设备的注册

字符设备注册

2022-06-14 10:49:40 246 1

原创 fd补充:file和inode的实现

它标识一个进程打开的文件,数组内指针所指向的,下面解释相关的几个最重要的字段:f_path :标识文件名f_inode :inode 这个是vfs的inode类型,是基于具体文件系统之上的抽象封装;f_op:驱动结构体。f_pos :就是当前文件偏移。f_pos 在 open 的时候会设置成默认值,seek 的时候可以更改,从而影响到 write/read 的位置。struct file 结构体里面有一个指向 inode 的指针。这个指向inode指针并没有直接指向具体文件,而是操作系统抽象出来的一层虚

2022-06-13 21:38:04 401

原创 fd(files Descriptor)

当打开一个文件时,内核向进程返回一个文件描述符( open 系统调用得到),后续 read、write 这个文件时,则只需要用这个文件描述符来标识该文件,将其作为参数传入 read、write 。用户使用系统调用 open、creat 来打开或创建一个文件,用户态得到的结果fd ,后续的 IO 操作全都是用 fd 来标识这个文件。进程的抽象是基于 struct task_struct 结构体:struct task_struct 是进程的抽象封装,标识一个进程,在 Linux 里面的进程各种抽象视角,都

2022-06-13 21:19:16 104

原创 字符设备架构

字符设备架构

2022-06-12 22:22:37 302

原创 字符设备号

字符设备号

2022-06-12 21:25:02 122

原创 模块传参.

模块传参

2022-06-12 12:08:44 122

空空如也

空空如也

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

TA关注的人

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