一、 Makefile
三块 目标 依赖 命令(gcc)
程序编译过程
- 预处理(preprocessing):gcc -E xxx.c -o xxx.i
- 编译(compilation):gcc -S xxx.i -o xxx.s
- 汇编(assembly):gcc -c txxx.s -o xxx.o
- 链接(link)gcc xxx.o -o xxx
- 变量 $@:目标文件的完整名称
$<:第一个依赖文件的名称
$^:包含所有不重复的依赖项
$(CXX) = gcc/g++
@:执行命令并不在终端显示
-:此行失败后继续往下执行
%:通配符
CXXFLAGS:自动推导添加路径 例:CXXFLAGAS=-I../test_gcc
- 隐式规则 自动推导
- 伪目标:定义:.PHONY例:.PHONY:clean .PHONY作用:忽略时间戳的比较
- $(RM) = rm -f
- 编译静态链接库 ar -crv libmylib.a mylib.o
C:不显示创建
v:显示过程
R:创建静态库
-v: 显示make工具的版本信息
-w: 在处理makefile之前和之后显示工作路径
-C dir:读取makefile之前改变工作路径至dir目录
-n:只打印要执行的命令但不执行
-s:执行但不显示执行的命令
二、Shell
介绍:通过编写shell命令发送给linux内核去执行,操作计算机硬件,所以Shell命令是用 户操作计算机硬件的桥梁
Shell是命令,类似于windows系统Dos命令
Shell是一门程序设计语言,Shell里面含有变量,函数,逻辑控制语句等等。
通过Shell命令与编程语言来提高linux系统的管理工作效率
$SHELL:是全局共享的读取解析器类型环境变量,全局环境变量时所有的shell程序都可以 读取的变量
- Shell文件以.sh结尾,#!/bin/bash开头(首行:设置解析器类型)
- 单行注释:#
- 多行注释:
:<<!
注释内容
!
- 变量类型
1>系统环境变量:是linux系统加载Shell的配置文件中定义的变量,共享给所有的Shell 文件使用。全局配置文件 个人配置文件
$PATH命令搜索目录路径$HISTFILE显示当前用户执行命令的历史列表文件 $LANG设置
当前系统语言环境
- 自定义环境变量:
- 自定义局部变量:定义在脚本文件中的变量,只能在这个脚本文件中使用使用的变 量 语法:变量名=变量值(=两侧不能有空格,变量的值若有空格,必须用双 引号括起来)变量删除:unset 变量名
- 自定义常量:设置值后不可以修改,只读。语法readonly 常量名=常量值
- 自定义全局环境变量:可以在当前Shell环境与子Shell环境中都能使用。语法:export 变量名=变量值
- 特殊符号环境变量:
- $n:用于接收脚本文件执行时传入的参数($ 0代表获取脚本文件名称的,$1~$9代表获取第1个输入参数到第9个输入参数,第10个及以上参数获取参数格式:${数字},否则无法获取)
- $#:获取输入参数的个数
- $*、$@:获取所有输入参数,不一样:”$*”:获取所有参数为一个字符串,”$@”:获取一组参数列表
- $?:每个shell命令的执行都有一个返回值,这个返回值用于说明上一个 命令执行是否成功,一般来说,返回0表示执行成功,非0表示执行失败
- $$:用于获取当前Shell环境的进程ID号
- 执行非登录环境脚本文件 bash 然后执行脚本文件 执行登录脚本文件:sh -l 脚本文件名 或su切换用户登录时加载Shell登录环境变量:su 用户名 -l或su 用户名 --login
- echo $0:输出-bash为Shell登录环境 输出为bash为Shell非登录环境
- 字符串:
单引号’’:原样输出,在拼接字符串中使用变量是无效的
双引号””: 能够解析字符串,并不是原样输出(推荐使用)
不加引号:可以解析但不能有空格 空格后面的字符串会当作命令去执行
- 获取字符串的长度:${#变量名}
- export 全局变量的定义
- sh xx.sh 没有执行权限也会执行 source xxx.sh
执行脚本文件:sh 或bash或. 绝对路径或相对路径/脚本文件 或具有执行权限的文件./ 文件
bash或sh时使用Shell脚本解析器执行脚本 不需要执行权限
- 变量:${#xxx} xxx的长度
- 数组定义:数组名=(xx xx xx xx ........)或数组名=([索引1]=xx [索引2]=xx .........)
- 获取数组长度:${#数组名[*]} 数组拼接
- 数组 ${xxx[@]}或${xxx[*]}读出数组中所有元素 ${xxx[x]}读出数组中某一元素
- 删除数组某一个元素:unset 数组名[下标] 删除整个数组:unset 数组名
- 查看命令类型:type 命令
- Shell内置命令:
- 定义别名:alias 别名=”命令” 删除别名:unalias 别名 删除所有别名:unslias -a
- echo:默认自动换行,echo -n xxx 不换行 -e:解析转意字符 echo -e xxx\c:不换 行 \n:换行 \c:清除echo结尾的换行
- 读取控制台输入:read -p “提示信息” 变量 read -n 数字 变量:设置读取字符数
-s:静默模式(看不到输入) -t:限制时间输入
- 退出当前Shell环境进程结束进程,并返回一个状态码:exit 获取上一个Shell 脚本文件退出状态码:$?
0:正常退出 0~255:不同状态码
- 设置变量属性:declare i:设置为整形 +或-:取消或增加所设的属性
r:只读 -a:创建普通索引数组 -A:创建关联数组(数组下标为字符串) p: 查询所有函数的定义 -F:查询所有函数的名称列表
- 单行注释:# 多行注释::<<EOF..... EOF或::<<! ... !
- 运算符:
算术运算符: expr (+ - * / % = )例:ret=`expr 1 + 9`(反引号 运算符两边要空 格隔开,整数运算 )
关系运算符:(只支持数字 不支持字符串 真返回0 假返回1 例:[ 1 -eq 2 ] (注 意空格))
eq 相等
ne 不相等
gt 大于
lt 小于
ge 大于等于
le小于等于
其它:(($a < $b))(不需要空格)
字符串、小数的比较:[[ ]]或[] (==、!=、< 、>、)-z:字符串长度是否为0,-n:字符串的长度是否不为0,$:字符串是否不为空,不为空返回0(单[]的>、<需要用转义字符\转义)推荐使用[[]] 例[[ $a < $b ]](注意空格)
布尔运算符: -a与运算
-o或运算
!非运算
必须放在单[]内或与test命令一起使用 0=true 1=false
逻辑表达式: 不能与test命令一起使用
&&:命令1 && 命令2 //命令1执行成功,命令2执行;命令1执行不 成功,命令2也不执行
||: 命令1 || 命令2//命令1执行成功,命令2不执行;命令1执行失 败, 命令2执行。
!:非
&&、||必须放在[[]]或(())内,!可以用在[]、[[]]中,不可以在(())内
- -f:判断输入内容是否是一个普通文件
-d:判断输入内容是否是一个目录
-x:判断输入内容是否可执行
-w:判断文件是否可写
-r:判读文件是否可读
-s:判断文件是否为空
-e:判断文件是否存在
例:[[ -f $file1 ]]
- Shell计算命令:
- expr:整数求值、获取字符串的长度(expr length 字符串)、截取字符串(expr substr 开始 结束)、获取字符在字符串中出现的位置(expr index 被 查找的字符串 需 要查找的字符 //位置都是从1开始)、正则表达式(expr match 字符串 正则表 达式或expr 字符串:正则表达式)只能计算一个表达式
- (( )):例:((a=1+6))、 ((b=a-1))、a=$((1+6))、((a>7 && b>7))、((a=3+5,b=a+10))//(()) 可以自动解析变量,不用加$,中间有无空格都可以 特殊字符不需要转义 需要获 取值以后才能echo输出
- let: 用于赋值是最简洁的整数运算赋值命令,例:let a=1+6 不能直接输出
- $[]:只能对表达式进行计算并获取计算结果,不能赋值给变量 一个[]内只能放一个表 达式,不需要转义,不能多表达式计算
- bc:浮点运算、进制的转换 -q不显示欢迎信息 -l启动内置函数
使用管道进行bc表达式的运算 echo “表达式” | bc 例:echo “scale=2;10/3” | bc(scale 保留小数位数)quit退出
bc -q 文件名:计算文件中表达式的值 结果不能放在Shell中
将计算的结果赋值给变量 变量名=`echo 同上`或变量名=$(同上) 推荐使用``
bc输入重定向:变量名=`bc 参数 << EOF 第一个表达式 第二个表达式 .....EOF`或变量名=$(同左)//EOF为表达式的开始和结束标志,可以为其他
22.
23.计算表达式:$((计算表达式))let 计算表达式
24.重定向符号:> 覆盖/ >>追加
25.:标准正确输出 2:标准错误输出 2>&1:表示所有输出信息s
26.流程语句
If关键字:
if ((条件))
then
命令
elif ((条件))
then
命令
else
命令
fi
可以放入一行 if条件;then 命令;elif 条件;then 命令;else 命令;fi;
Shell的内置命令:test(对字符串的比较测试、对整数的比较测试、对文件的比较测试 与[]功能一样)
case关键字:
case 变量名 in
值1)
指令1
;;
值n)
指令n
;;
*)
指令x
;;
esac
For关键字:
for 值 in 列表 或for((i=start;i<=end;i++))或for 变量值 in {strat..end}(..为固定格式)
do
执行语句
done
while关键字:
while 条件
do
执行语句
done
无限循环:while : 或while true(条件为true进入循环)
until关键字:
until 条件
do
执行语句
done
(条件为false进入循环)
select关键字:交互式循环菜单选择输入
select 变量 in 菜单
do
命令
done
select是无线循环(死循环),输入空值或输入的值无效都不会结束循环,只有遇到break或按下ctrl+f组合键才能结束循环。#?代表可以输入选中的菜单编号。
27.循环退出
break:跳出当前循环
break n:跳出第n个循环(由内向外)
continue:跳出当前循环的本层
exit:退出当前程序
- Shell函数
系统函数:获取文件名:basename 文件绝对路径或相对路径
获取目录路径:dirname 文件绝对路径
自定义函数: function 函数返回值()(function可不写 )
{
命令
return 0~255
}
调用函数 函数名 参数1 参数2.......
当前shell进程ID号:$$
Shell命令会开启一个子进程运行命令,函数在当前shell环境中运行,没有开启新的进程
- 输入重定向:标准输入数据是数据从键盘流向程序,如果改变了它的方向,数据从其他地方流入,这就是输入重定向(<、<<tag(读取tag开始到tag结束作为输入,tag可以为任意))
- 输出重定向:标准输出是数据默认从程序流向显示器,如果改变了它的方向,数据就流向其它地方,这就是输出重定向(> 、>>//覆盖、追加)。2>&1:将标准输入和标准错误输出格式
- Shell工具:cut:切割提取指定列数据 cut 文件或数据 -d 分隔符切割 -f 提取第几列(-c 提取字符 -b提取字节 单词数据、bash进程ID号)
sed:文件增删改查操作
awk:文本分析工具 拼接字符串 默认空格切割
sort:排序
三、USB
发送数据顺序:低位在前,高位在后
- USB控制器:负责数据处理
- 根集线器:提供一个连接主控制器与设备之间的接口和通路
- 集线器智能扩展出更多接口的USB口,而不能扩展出更多的带宽,带宽是共享一个USB主控制器。
- USB使用的是NRZI编码方式:当数据为0时,电平翻转;数据为1时,电平不翻转。
- 设备描述符:一个USB设备只有一个设备描述符,设备描述符里决定了该设备有多少种配置,每种配置都有一个配置描述符。
- 配置描述符:定义了该接口有多少个端点,每个端点都有一个端点描述符。
- 端点描述符:定义了端点的大小,类型,等等。
- 接口描述符:
- 字符串描述符
- 一个设备描述符可以有多个配置,但是同一时刻只能有一个配置有效。每个配置下又可以有多个接口,当我们需要不同的功能时,只要选择不同的配置即可。
- 设备描述符->配置描述符->接口描述符->端点描述符
- 控制传输:USB枚举的过程都是控制传输。三个过程:建立过程,可选的数据过程,状态过程
- USB总线上传输数据是以包为基本单位的,一个包被划分成不同的域。不同的包有个共同特点:以同步域开始,紧跟着包标识符(PID),最终以包结束符(EOP)来结束这个包
同步域:同步主机端和设备端的数据时钟
包标识符:用来标识一个包的类型(令牌包(01)、数据包(11)、握手包(10)、特殊包(00))
1>.令牌包:用来启动一次USB传输,主机发送一个令牌包来通知哪个设备进行响应,如何响应,总是由主机发送。4种令牌包:输出(OUT)、输入(IN)、建立(SETUP)、帧起始(SOF):帧起始包在每帧或每微帧开始发送以广播的形式发送,所有的USB全速设备和高速设备都可以收到SOF包。USB全速设备每毫秒产生一个帧,高速设备每125微妙产生一个微帧。4个令牌包种,只有SOF令牌包之后不跟随数据传输。每个令牌包最后都有一个CRC5的校验,它只校验PID之后的数据,不包括PID本身,因为PID本身已经有4个取反的位进行校验了。
OUT、IN、SETUP令牌包结构:
同步域 8位包标识符PID 7位地址 4位端点号 5位CRC5校验 EOP
SOF令牌包的结构: 同步域 8位包标识符 11位帧号 5位CRC5校验 EOP
2>.数据包:用来传输数据 当数据包成功发送或者接收时,数据包类型切换。用来传送数据,可以从主机到设备,也可以从设备到主机,方向由令牌包来指定。
数据包结构:同步域 8位包标识符 字节0 字节1 ...........字节N 16位CRC16校验 EOP
3>.握手包:来表示一个传输是否被对方确认。握手包只有同步域,PID,EOP。发送者通常为数据的接收者,当数据接收正确后,发送握手包,
ACK:表示正确接收数据,并且有足够的空间来容纳数据。主机和设备都可以使 用ACK来确认,而NAK、STALL、NYET只有设备能够返回,主机不能使用这些 握手包。
NAK:表示没有数据需要返回,或数据正确接收但是没有足够的空间容纳他们
STALL:表示设备无法执行这个请求或端点被挂起,表示一种错误状态。需要主 机干预才能解除这种状态。
NYET:只在USB2.0的高速输出设备中使用,它表示设备本次数据成功接收,但 没有足够的空间来接收下一次数据。主机在下一次输出数据时,将先使用PING令 牌包来试探设备是否有空间接收数据,以避免不必要的浪费。
4>.特殊包:特殊场合使用的包
包结束符:
- 四种传输类型:批量传输,等时传输(或同步传输),中断传输和控制传输。其中批量传输、等时传输、中断传输每传输一次数据都是一个事务,控制传输包括三个过程,建立过程和状态过程分别为一个事务,数据过程则可能包含多个事务。
- 批量传输:通常用在数据量大,对数据的实时性要求不高的场合
- 中断传输:是一种保证查询频率的传输,中断断电在端点描述符中报告它的查询间隔,主机会保证在小于这个时间间隔的范围内安排一次传输。中断传输通常用在数据量不大,但是对时间要求较严格的设备中。
- 等时传输:用在数据量大,对实时性要求高的场合,不能保证数据100%正确,当数据错误时,不能进行重传操作,没有应答包
- 控制传输:分为三个过程:建立过程,可选的数据过程,状态过程。
建立过程:使用一个建立事务。建立事务是一个输出数据的过程。保证数据传输过程的数据完整性,只能使用DATA0包。
数据过程:此过程是可选的,即一个控制传输可能没有数据过程。如果有,一个数据过程可以包含一笔或多笔数据事务。所有的数据事务必须是同一个传输方向。数据过程的第一个数据包必须为DATA1包,然后每次正确传输一个数据包后就在DATA0和DATA1之间交替。
读传输:输入 写传输:输出
状态过程:一旦数据传输方向发生改变,就会认为进入状态过程。它的传输方向刚好跟前面的数据阶段相反,读传输:输出 写传输:输入。状态过程只使用DATA1包。
- 一个具体的端点只能工作在一种传输模式下,通常,我们吧工作在什么传输模式下的端点就叫做什么端点。
- 端点0是每个USB设备都必须具备的默认控制端点,设备的各种描述符以及主机发送的一些命令都是通过端点0传输的。
- 最大包长度:每次发送数据包,都不能超过端点的最大包长度。
- 关键字volatile在嵌入式系统中的意思是高速编译器,不要优化这个变量的操作,因为这个变量的值可能会被意外的修改而需要每次都重新读回或每次赋值都需要写回。
- 描述符:设备描述符:0x01
配置描述符:0x02
字符串描述符:0x03
接口描述符:0x04
端点描述符:0x05
报告描述符:是用来描述一个报告的结构以及报告里面的数据是干什么用的。
USB转的串口:DB9:插头对准自己,宽的一面在上。对于公头,上面一排从左往右刚好就是1~5脚,对于母头,从右往左数是1~5脚。下面的排序和上一排一样,为6~9脚。
公头:2脚:RXD,数据接收引脚;3脚:TXD,数据发送引脚;5脚:GND,地
母头:2脚:TXD,数据发送引脚;3脚:RXD,引脚数据接收脚:GND,地