前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【嵌入式】基于ARM的嵌入式Linux开发总结

【嵌入式】基于ARM的嵌入式Linux开发总结

作者头像
全栈程序员站长
发布2022-06-28 17:02:30
18.4K0
发布2022-06-28 17:02:30
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

前言

嵌入式知识点复习一

1、 嵌入式系统的一般组成结构

在这里插入图片描述
在这里插入图片描述

2、嵌入式硬件系统的结构 (1)嵌入式处理器+外围硬件 (2)常见的外围硬件:电源、时钟、内存、I/O、通信、调试; 3、嵌入式处理器 (1)ARM、S3C6410、STM32单片机、华为海思、高通骁龙等 (2)Intel /AMD 都不是嵌入式处理器 4、嵌入式操作系统 功能: 种类:嵌入式linux;WinCE;Vxworks;μC/OS-II;Android;IOS。注意:linux不是嵌入式操作系统;MAC OS WINDOWS XP/7/8/10都不是

嵌入式知识点复习二 –体系结构

1、ARM:ADVANCED RISC MACHINES,是一款嵌入式微控制器,也是一家嵌入式处理器设计厂商。设计高性能、低功耗的嵌入式处理器。 2、ARM微处理器工作状态:两种指令对应两种状态(通常情况) (1)Thumb状态、ARM状态; (2)32位定长ARM指令,16位定长Thumb指令。 (3)ARM1176支持ARM指令、Thumb指令、Jazelle指令,故有三种状态:ARM状态、Thumb状态、Jazelle状态。 3、异常: (1)处理器执行某些区别于用户指令的任务,如中断处理、复位、调试等;为了区分用户指令,因此称为异常; (2)异常的种类与类型(1176为例):7种,中断(IRQ)、快中断(FIQ)、未定义(Undef)、数据中止(DABT)、预取指中止(PABT)、软中断、复位(reset) 4、工作模式:根据系统执行正常或异常指令不同,分为8种工作模式:用户模式、系统模式、中断模式、快中断模式、未定义模式、中止模式(对应数据中止异常、预取指中止)、SVC管理模式(软中断、复位)、SM安全监视器模式。 5、寄存器: (1)ARM处理器均为32位寄存器; (2)ARM1176寄存器数量:40个 (3)ARM1176寄存器包括:未分组寄存器、分组寄存器、CPSR、SPSR; (4)未分组寄存器(所有模式通用):9个,R0~R7;R15(PC) (5)分组寄存器(不同工作模式下专用,不同模式稍有不同): ① R8~R14; ② 6个不同模式下的SPSR寄存器:SPSR_irq,SPSR_fiq,SPSR_abt, SPSR_und,SPSR_svc,SPSR_mon (6)可复用寄存器: ① SP堆栈指针寄存器-R13,用于保存子程序调用或异常处理的临时数据; ② LR连接寄存器-R14,用于保存子程序调用或异常处理时,主程序调用指令/中断跳转指令的下一条指令的入口地址,以便于恢复主程序; ③ PC程序计数器-P15,用于保存要执行的指令的地址。 (7)PSR程序状态寄存器: ① 包括CPSR当前程序状态寄存器和SPSR备份的程序状态寄存器; ② CPSP用于保存当前模式下处理器模式、状态、中断使能、大小端模式及条件位等信息; ③ SPSR用于备份异常发生前的CPSR寄存器的值,以便异常处理结束时能返回用户程序状态。 6、ARM支持两种中断:IRQ和FIQ 7、ARM数据存储格式:大端(big endian)和小端(little endian) 8、采用RISC架构的ARM微处理器一般具有如下特点: ① 体积小、低功耗、低成本、高性能; ② 支持Thumb(16位)/ARM(32位)双指令集,能很好地兼容8位/16位器件; ③ 大量使用寄存器,指令执行速度更快; ④ 大多数数据操作都在寄存器中完成; ⑤ 寻址方式灵活简单,执行效率高; ⑥ 指令长度固定; ⑦ 指令支持按 条件执行; ⑧ 内存访问采用load/store实现。

嵌入式知识点复习三 –ARM-LINUX嵌入式开发环境

一、交叉开发模式 1、组成结构 (1)宿主机:开发主机,一般由PC、发行版linux系统、开发工具(本地及交叉编译)(代码编辑器Vi,编译器GCC、调试器GDB、工程管理器MAKE、NFS等)组成; (2)目标机:嵌入式系统,一般由ARM硬件、BOOTLOADER、内核、根文件系统构成; (3)连接工具:串口线、网线、USB线等。 2、理解编译工具链与交叉编译工具链的异同 (1)相同点: ① 用于支持的语言的编译、链接与调试,编译器用法相同; ② 通常都有编译器、链接器、调试器、库及其他二进制工具构成。 (2)不同点: ① 编译工具链一般用于本机编译、本机执行的开发模式; ② 交叉编译工具链用于宿主机编译,目标机运行的交叉开发模式; ③ 编译器一般Linux发行版都配备,直接调用gcc命令即可; ④ 交叉编译器一般需根据宿主机软硬件环境,进行gcc、相关库、工具进行有针对性的定制。 ⑤ 实验室使用的OK6410开发板定制的编译器为32位的,其交叉编译工具链主要arm-linux-gcc,arm-linux-g++arm-linux-gdb等构成。 二、开发工具的用法 1、Vi的工作模式及其切换-掌握使用Vi完成源代码编辑、保存及退出的常见按键操作; 2、GCC:GNU Compiler Collection,GUN编译器套件,特点: ① 支持绝大多数高级语言的编译,既支持传统的C/C++,Fortan,Objective-C ,也支持java,python,go等语言; ② 支持汇编语言; ③ 支持绝大多数的主流处理器平台; ④ 便于构建交叉编译工具链。 3、gcc/arm-linux-gcc用法: ① 基本用法:gcc hello.c;arm-linux-gcc hello.c;输出a.out ② 推荐用法:gcc hello.c -o hello/arm-linux-gcc hello.c -o hello ,可以指定输出文件名称; ③ 主要的编译参数 -Wall 打印全部警告信息; -O{0-3,s} 支持代码优化,0无优化; -g 支持gdb调试; -lpthread 支持多线程。

4、make及Makefile (1)make:工程管理器,利用执行Makefile文件实现工程管理(编译、链接、生成工程镜像、安装、清理、卸载等); (2)make用法:编写Makefile,在终端下执行make命令即可。 (3)Makefile文件编写示例: 一个工程,2个源文件testa.c ,testb.c,一个头文件testb.h,编译器为arm-linux-gcc,生成的可执行文件为test,需支持代码优化、打印警告信息,支持gdb调试等编译选项,其Makefile文件如下: SRC=testa.testb b.c testb.h EXEC=test CC=arm-linux-gcc CFLAGS=-Wall -O2 -g ( E X E C ) : (EXEC): (EXEC):(SRC) (CC) (SRC) -o (EXEC) (CFLAGS)

嵌入式知识点复习四 –arm-linux文件编程

1、linux文件编程概述 (1)文件描述符:Linux中文件分为4种:普通文件、目录文件、链接文件、设备文件要区分这些文件就要了解“文件描述符”; 文件描述符是一个非负的整数,他是一个索引值,并指向内核中每个进程打开文件的记录表。当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符,当需要读/写文件时,也需要把文件描述符作为参数传递给相应的函数。 (2)基本I/O操作 Linux的输入/输出(I/O)操作,通常为5个方面:打开,读取,写入,和关闭 对应的有5个系统调用: open,read,write,close,lseek 所需要的头文件: #include <sys/types.h> #include <unistd.h> 1.open函数 open函数的原型如下: int open(const char *pathname, int flags, mode_t mode) 函数传入参数含义如下: pathname:为字符串,表示被打开的文件名称,可以包含路径。 flags :为一个或多个标志,表示文件的打开方式,常用标志如表所示: O_RDONLY 只读方式打开 O_WRONLY 只写方式打开 O_RDWR  读/写方式打开 O_CREAT 如果文件不存在,就创建新的文件 O_EXCL 如果使用O_CREAT时文件存在,则可返回错误消息 O_TRUNC  如果文件已存在,且以只读或只写成功打开,则先全部删除文件中原有的数据 O_APPEND  以添加方式打开文件,在打开文件的同时,文件指针指向文件的末尾、 注意:在open函数中,flags参数可以用过“|”组合而成,O_RDONLY,O_WRONLY,O_RDWR这三种方式是互斥的,不可同时使用,因此这3个参数只能出现一个。

mode 被打开文件的存取权限模式,可以使用八进制数来表示新文件的权限,也可以采用<sys/stat.h>中定义的符号常量,当打开已有文件时,将忽略这个参数,函数返回值:成功则返回文件描述符,出错返回-1。

文件模式符号常量: S_IRWXU   00700    所属用户读。写和执行权限 S_IRUSR   00400   所属用户读权限 S_IWUSR   00200   所属用户写权限 S_IXUSR   00100   所属用户执行权限

S_IRWXG  00070   组用户读,写和执行权限 S_IRGRP   00040   组用户读权限  S_IWGRP   00020  组用户写权限 S_IXGRP   00010  组用户执行权限

S_IRWXO  00007  其他用户读,写和执行权限 S_IROTH  00004  其他用户读权限 S_IWOTH  00002  其他用户写权限 S_IXOTH  00001  其他用户执行权限 2.read和write函数 函数原型如下: ssize_t read(int fd, void *buf,size_t count) ssize_t write(int fd,const void *buf, size_t count) 函数传入参数含义如下: fd 文件描述符 buf 指定存储器独处数据的缓冲区 count 指定读出或写入的字节数 3.close函数 当使用完文件时可以使用close关闭文件,close会让缓冲区中的数据写回磁盘,并释放文件所占的资源,close的原型如下: int close(int fd) 函数传入参数:fd文件描述符 函数返回值:若文件顺利关闭则返回0,发生错误则返回-1,并置errno,通常文件在关闭时出错是不常见的,但也不是不可能的情况,他别是在关闭通过网络访问的文件时就会出现这种情况。 4.lseek函数 主要用于移动文件读写指针,主要用于获取文件大小和拓展文件(先分配空间、然后再填充内容),函数原型如下: off_t lseek(int fd, off_t offset, int whence) 参数 fd:文件描述符。 offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移) whence (当前位置基点): SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小。 SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量。 SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小。 返回值 成功:文件的当前位移 -1:出错

实例:(1)参考实验2:linux文件编程; (2)网盘:/linux编程源代码/IO(readwrite、fcntl)下相关代码

嵌入式知识点复习五 –arm-linux进程编程

一、Linux进程编程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配和调度的基本单位,是操作系统结构的基础。 1 进程控制 子进程创建:fork()函数 在Linux中创建一个新进程的唯一方法是使用fork()函数。fork()函数是Linux中一个非常重要的函数,和以往遇到的函数有一些区别,因为fork()函数看起来执行一次却返回两个值。 1)fork()函数说明 fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。 使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程的上下文、代码段、进程堆栈、内存信息、打开的文件描述符、符号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等。 因为子进程几乎是父进程的完全复制,所以父子两进程会运行同一个程序。这就需要用一种方式来区分它们,并使它们照此运行,否则,这两个进程不可能做不同的事。 实际上是在父进程中执行fork()函数时,父进程会复制一个子进程,而且父子进程的代码从fork()函数的返回开始分别在两个地址空间中同时运行,从而使两个进程分别获得所属fork()函数的返回值,其中在父进程中的返回值是子进程的进程号,而在子进程中返回0。因此,可以通过返回值来判断该进程的父进程还是子进程。 2)fork()函数语法

在这里插入图片描述
在这里插入图片描述

进程等待函数 1)wait()函数,无条件等待,父进程阻塞直到子进程结束

在这里插入图片描述
在这里插入图片描述

2)waitpid()函数,指定等待某个子进程结束以及等待的方式(阻塞或非阻塞) 所需头文件 #include <sys/types.h> #include <sys/wait.h> 函数原型 pid_t waitpid(pid_t pid, int *status, int options) 函数参数 pid pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。 pid=-1:等待任何一个子进程退出,此时和wait作用一样。 pid=0:等待其组ID等于调用进程的组ID的任一子进程。 pid<-1:等待其组ID等于pid的绝对值的任一子进程。 status 同wait options WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0 WUNTRACED:若某实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态。 0:同wait,阻塞父进程,等待子进程退出。 函数返回值 正常:结束的子进程的进程号 使用选项WNOHANG且没有子进程结束时:0 调用出错:-1 所需头文件 #include <sys/types.h> #include <sys/wait.h>

函数原型 pid_t waitpid(pid_t pid, int *status, int options) 函数参数 pid pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。 pid=-1:等待任何一个子进程退出,此时和wait作用一样。 pid=0:等待其组ID等于调用进程的组ID的任一子进程。 pid<-1:等待其组ID等于pid的绝对值的任一子进程。 status 同wait options WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0 WUNTRACED:若某实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态。 0:同wait,阻塞父进程,等待子进程退出。 函数返回值 正常:结束的子进程的进程号 使用选项WNOHANG且没有子进程结束时:0 调用出错:-1

进程结束:exit()和_exit()

所需头文件 exit:#include <stdlib.h> _exit:#include <unistd.h> 函数原型 exit:void exit(int status); _exit:void _exit(int status); 函数传入值 status是一个整型的参数,可以利用这个参数传递进程结束时的状态。 通常0表示正常结束;其他的数值表示出现了错误,进程非正常结束。 在实际编程时,可以用wait系统调用接收子进程的返回值,进行相应的 处理。

所需头文件 exit:#include <stdlib.h> _exit:#include <unistd.h> 函数原型 exit:void exit(int status); _exit:void _exit(int status); 函数传入值 status是一个整型的参数,可以利用这个参数传递进程结束时的状态。 通常0表示正常结束;其他的数值表示出现了错误,进程非正常结束。 在实际编程时,可以用wait系统调用接收子进程的返回值,进行相应的 处理。

两者的区别: (1)_exit()函数的作用最为简单:直接使进程终止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构; (2)exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。 (3)exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是”清理I/O缓冲”。 Linux下的进程间通信 进程间通信用于实现参数传递及通信功能;Linux支持的常用的进程间通信方法:管道、消息队列、共享内存、信号量、套接口等等。 实例:(1)实验三:Linux进程编程; (2)网盘linux编程源代码目录下fork文件下相关实例(FIFO、msgque、shm)。

嵌入式知识点复习六 –arm-linux网络编程

1、程序流程 (1)网络通信程序架构-客户端/服务器架构 (2)流程如下图:

在这里插入图片描述
在这里插入图片描述

TCP通信

2、函数说明 socket() Sockfd=socket(AF_INET,SOCK_STREAM,0);

Bind() s_add.sin_family=AF_INET;IPV4协议 s_add.sin_addr.s_addr=inet_addr(“192.168.1.123”);IP地址192.168.1.123 s_add.sin_port=htons(0x8888);端口号是8888

if(-1 == bind(Sockfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))

listen()服务器端侦听函数 listen(Sockfd,5)服务器侦听来自客户端的请求 accept()服务器端接受客户端连接请求 nfp = accept(Sockfd, (struct sockaddr *)(&c_add), sizeof(struct sockaddr);

send()数据发送函数 send(nfp,“hello,welcome to my server”,32,0) recv()数据接收函数 recv(nfp,buffer,1024,0) 关闭连接 Close(nfp) 关闭服务器 Close(Sockfd) 实例:(1)实验四:网络聊天室设计 (2)网盘/linux编程源代码/socket下相关代码

嵌入式知识点复习七 –linux字符型设备驱动初步

一、Linux字符设备驱动初步 1、Linux设备类型 (1)字符设备:只能一个字节一个字节的读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后顺序进行。字符设备是面向流的设备,常见的字符设备如鼠标、键盘、串口、控制台、LED等。 (2)块设备:是指可以从设备的任意位置读取一定长度的数据设备。块设备如硬盘、磁盘、U盘和SD卡等存储设备。 (3)网络设备:网络设备比较特殊,不在是对文件进行操作,而是由专门的网络接口来实现。应用程序不能直接访问网络设备驱动程序。在/dev目录下也没有文件来表示网络设备。

2、开发流程

3、关键函数讲解(以2.6以下版本内核为例) (1)驱动模块注册register_chrdev()函数 原型:register_chrdev(unsigned int major, const char *name,const struct file_operations *fops); major:主设备号,该值为 0 时,自动运行分配。而实际值不是 0 ; name:设备名称; fops:操作函数,实现驱动定义的open、read、write、close等内核函数与应用程序调用的open、read、write、close间的映射; 返回值: major 值为 0 ,正常注册后,返回分配的主设备号。如果分配失败,返回 EBUSY 的负值 ( -EBUSY ) 。major 值若大于 linux/major.h (2.4内核)中声明的最大值 (#define MAX_CHRDEV 255) ,则返回EINVAL 的负值 (-EINVAL) 。指定 major 值后,若有注册的设备,返回 EBUSY 的负值 (-EBUSY)。若正常注册,则返回 0 值 (2)驱动注销unregister_chrdev()函数 原型: #include <linux.fs.h> int unregister_chrdev (unsigned int major, const char *name) 变量: major 主设备号 name 设备文件 返回值: major 值若大于 linux/major.h (2.4 内核)中声明的最大值 (#define MAX_CHRDEV 255),返回 EINVAL的负值 (-EINVAL)。指定了 major的值后,若将要注销的 major 值并不是注册的设备驱动程序,返回 EINVAL的负值 ( -EINVAL )。正常注销则返回 0值。 (3)File_operation结构体 file_operations结构是建立驱动程序和设备编号的连接,内部是一组函数指针,每个打开的文件,也就是file结构,和一组函数关联,这些操作主要用来实现系统调用的 struct file_operations {   struct module *owner;//拥有该结构的模块的指针,一般为THIS_MODULES loff_t (*llseek) (struct file *, loff_t, int);//用来修改文件当前的读写位置 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//从设备中同步读取数据 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//向设备发送数据 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的读取操作 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的写入操作   int (*readdir) (struct file *, void *, filldir_t);//仅用于读取目录,对于设备文件,该字段为NULL unsigned int (*poll) (struct file *, struct poll_table_struct *); //轮询函数,判断目前是否可以进行非阻塞的读写或写入   int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //执行设备I/O控制命令   long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系统,将使用此种函数指针代替ioctl   long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系统上,32位的ioctl调用将使用此函数指针代替   int (*mmap) (struct file *, struct vm_area_struct *); //用于请求将设备内存映射到进程地址空间   int (*open) (struct inode *, struct file *); //打开   int (*flush) (struct file *, fl_owner_t id);   int (*release) (struct inode *, struct file *); //关闭   int (*fsync) (struct file *, struct dentry *, int datasync); //刷新待处理的数据   int (*aio_fsync) (struct kiocb *, int datasync); //异步刷新待处理的数据   int (*fasync) (int, struct file *, int); //通知设备FASYNC标志发生变化   int (*lock) (struct file *, int, struct file_lock *);   ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);   unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);   int (*check_flags)(int);   int (*flock) (struct file *, int, struct file_lock *);   ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);   ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);   int (*setlease)(struct file *, long, struct file_lock **); }; 实例:见网盘/linux编程源代码/ok6410ledrv

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/132741.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年6月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 嵌入式知识点复习一
      • 嵌入式知识点复习二 –体系结构
        • 嵌入式知识点复习三 –ARM-LINUX嵌入式开发环境
          • 嵌入式知识点复习四 –arm-linux文件编程
            • 嵌入式知识点复习五 –arm-linux进程编程
              • 嵌入式知识点复习六 –arm-linux网络编程
                • 嵌入式知识点复习七 –linux字符型设备驱动初步
                相关产品与服务
                专用宿主机
                专用宿主机(CVM Dedicated Host,CDH)提供用户独享的物理服务器资源,满足您资源独享、资源物理隔离、安全、合规需求。专用宿主机搭载了腾讯云虚拟化系统,购买之后,您可在其上灵活创建、管理多个自定义规格的云服务器实例,自主规划物理资源的使用。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档