目錄
為什麼學:
linux學習路線
晶片選型
ARM體系架構
ARM的授權方式
Cortex A7核心
Linux系統
Linux檔案目錄
常見的檔案類型
系統路徑
使用者管理
檔案權限:
Sheel
Linux層次結構
常用指令
環境變量
Linux 軟體包的組成
NFS服務
Makefile
檔案描述和打開方式
ARM_V7架構
I.MX6ULL啟動
裸機開發
U_Boot
為什麼學:
應用場景豐富
**了解不同伺服器的運作環境:www.netcraft.com
職業發展方向多
**兩個優秀的C語言解析器項目:picoc ; write-a-c-interpreter
**github開源項目含金量越高stars越大搜尋時可以加星量限定 例如:github stars>1000
linux學習路線
晶片選型
**主要參數名額
**i.MX 6ull
ARM體系架構
**RISC(複雜指令集):8051 \ x86
**CISC(精簡指令集):ARM \ MIPS \ RISC-V
**ARM指令集:ARMV1~ARMV8其中嵌入式常用的是ARMV7指令集
**ARMV7指令集包含 A(高性能要求場合),R(實時性要求場合),M(低功耗場景)三個系列
ARM的授權方式
**指令集授權:例如華為麒麟晶片獲得了ARMV8指令集永久授權
**核心授權:擷取核心授權的公司可以流片生産ARM核心晶片,如STM/TI等
**使用授權:最低授權,适用于小的生産廠商
Cortex A7核心
**比Cortex A8晚,性能由于Cortex A8
Linux系統
**Linux主要構成
Linux檔案目錄
**/:根目錄
**/bin:二進制指令檔案,所有使用者共用
**/boot:跟啟動相關的靜态檔案
**/dev:裝置檔案
**/cdrom:挂載CD鏡像(逐漸被淘汰)
**/etc:主要存放系統及應用程式的配置檔案
**/home:使用者主目錄
**/lib:系統及應用程式的庫檔案
**/media:挂載多媒體裝置
**/mnt:裝置及檔案系統的挂載
**/opt:主要用來做軟體開發時的測試,可将其内容完全删除,不會對系統造成影響
**/proc:存放程序運作時産生的臨時檔案,及系統運作的資訊
**/root:系統管理者的主目錄
**/run:存放系統運作時的資訊
**/sbin:存放進階指令二進制檔案
**/srv:網絡服務相關的資訊
**/sys:硬體操作的接口
**/tmp:臨時檔案
**/usr:系統大部分的軟體
**/var:存放一些易變的檔案
常見的檔案類型
**ls -l 檢視檔案詳細資訊
**-:普通檔案
**d:目錄檔案
**l:連接配接檔案
**c:字元裝置檔案
**b:塊裝置檔案
系統路徑
**絕對路徑:以/開頭
**相對路徑:不以/開頭
**./:目前目錄
**../上一級目錄
使用者管理
**UID:使用者表識
**GID:使用者組辨別
**使用者管理的三個重要檔案
**/etc/passwd:字段定義如下(圖)
使用者名:密碼(存放在/etc/shadow):UId:GID:使用者資訊說明:預設登陸路徑:預設sheel解析器
**/etc/shadow:字段定義如下(圖)
使用者名:密碼:最後一次修改時間(1970年1月1日算起的總天數):密碼有效期間:密碼需要變更前的警告天數:密碼過期後的寬限時間:賬号實效時間:保留字段
**/etc/group:字段定義如下(圖)
組名:密碼(存放在/etc/gshadow):GID:組成員資訊
檔案權限:
Sheel
Sheel<----->核心
Linux層次結構
常用指令
**echo:重定向輸出
echo xxx >> test.txt 将xxx追加到test.txt末尾
echo xxx > test.txt 删除tes.txt内容後,将xxx寫到test.txt中
echo $PATH 檢視系統環境變量
**wc:列印檔案行數,詞數和字元數
**ln:建立連接配接檔案(分為軟連接配接(直接使用ln,類似于同步備份功能)和硬連接配接(ln -s,類似于快捷方式功能))
**find:在指定目錄下查找
find / -name "123.txt" 在根目錄及其子目錄下查找123.txt
**grep:在指定檔案中查找指定字元穿
grep "linux" 123.txt
grep "linux" 123.txt 顯示行數
**adduser:建立一個使用者
sudo adduser xxx 建立一個名為xxx的使用者
sudo adduser xxx sudo 将名為xxx的使用者并将其添加到sudo組中
**su:切換到指定使用者
su xxx 切換到xxx使用者
**deluser:删除使用者
deluser xxx 删除xxx使用者
**passwd:修改使用者密碼
sudo passwd xxx 修改xxx使用者的密碼
**usermod:修改使用者到指定使用者組
sudo usermod xxx XXX 将xxx使用者指定到XXX使用者組中
**chmod:
sudo chmod 777 123.txt 修改123.txt權限
**chown:
sudo chown xxx 123.txt 将123.txt所有者改為xxx
**chgrp:
sudo chgrp xxx 123.txt 将123.txt使用者組改為xxx
**df:
df -h 展示磁盤使用情況
**du
du -sh 展示但前目錄使用情況
** mount/umount
mount [選項] [源] [目錄] 挂載
umount [選項] [源] 解除安裝
**ifconfig
sudo ifconfig enp2s0 192.168.1.123 修改網絡端口IP
sudo ifconfig enp2s0 down 關閉網卡
sudo ifconfig enp2s0 up 啟動網卡
**poweroff:關機
**!!:重複上次指令
**which
which xxx 檢視xxx的路徑
**type+指令:檢視指令屬性
shell
**下面是一個最簡單的shell腳本(hello.sh):(修改為可執行權限後可當做可執行檔案運作)
#!/bin/bash //指定shell解析器
echo "hello world" //shell内容
**shell啟動方式
1 當可執行檔案
./hello.sh
2 指定解析器
/bin/bash hello.sh
3 source
source hello.sh
4 .
. hello.sh
**變量的定義及引用
var1=value1 //不能有空格或tab符
var2='value2' //可以有空格或tab符
var3="value3" //可以引用其他變量
var4="${var1}value4" //${變量名}表示引用
**删除變量
unset var
**指令運作結果指派
var =`pwd`或var =$(pwd)
**特殊變量
**讀取鍵盤輸入
read var //将鍵盤輸入值存放到var變量中
read -p "input var" var //将鍵盤輸入值存放到var變量中,-p "input var"為提示資訊
**退出目前程序
exit 10 //10為退出時的值
**對整數進行數學運算
var1=1
var2=2
var3=$((var1+var2))
**邏輯與/或
cmd1||cmd2 //cmd1不成立執行cmd2
cmd1&&cmd2 //cmd1成立執行cmd2
**檢測某個條件是否成立
var1=1
var2=2
[${var1}eq${var2}] || echo "var1!=var2"
**管道:将兩個指令連接配接在一起,将前一個指令的輸出作為後一個指令的輸入
ls | grep "123.txt"
**if 語句
read -p "input a" a
read -p "input b" b
if [$a eq $b]
then
echo "a=b"
elif [$a gt $b]
then
echo "a>b"
else
echo "a<b"
fi
**case 語句
read -p "input a" a
case [$a] in
1)
echo "a=1"
;;
2)
echo "a=2"
;;
*)
echo "a=${a}"
;;
esac
**for語句
for n in {1..10}
do
echo "n"
done
**while語句
n=0
while ((n<10))
do
echo "n"
done
**函數
function myname(){ //定義
echo "cxw"
}
myname //調用
環境變量
**shell 執行順序
/etc/profile ----> ~/.profile //設定環境變量可以在這兩個檔案中進行
Linux 軟體包的組成
NFS服務
**關閉防火牆
sudo ufw disable
**安裝
sudo apt-get update
sudo apt-get install nfs-kernel-server
**配置
sudo gedit /etc/exports
在末尾添加:/home/cxw/imx6ull *(rw,sync,no_subtree_check,no_root_squash)
**更新配置
sudo exportfs -r
**檢視配置結果
showmount -e
**用戶端安裝
sudo apt-get install nfs-common
**檢視主機共享目錄
shoemount -e 192.168.1.1
**挂載
mount 192.168.1.1:/home/work /home/work
Makefile
**三要素:目标,依賴,指令
**格式:
目标:依賴的檔案或者其他目标
<tab>指令1
<tab>指令2
<tab>指令3
**.PHONY可以指定一個僞目标
**=延遲指派
**:=立即指派
**?=空指派
**+=追加指派
**自動化變量
$<:第一個依賴檔案
$^:全部依賴檔案
$@:表示目标
**模式比對
%:比對任意多個非空字元
**預設規則
所有的.o檔案預設由.c檔案編譯
**條件分支
ifeq(var1,var2)
.........
else
..............
endif
ifneq(var1,var2)
.........
else
..............
endif
**常用函數(待深入學習)
檔案描述和打開方式
**系統IO
主模式:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int fd;
fd=open("./test.txt",O_RDWR);
if(fd<0)
{
printf("open error\n\r");
}
printf("%d\n",fd);
close(fd);
return 0;
}
副模式:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int fd;
fd=open("./test.txt",O_RDWR|O_CREAT,0666);
if(fd<0)
{
printf("open error\n\r");
}
printf("%d\n",fd);
close(fd);
return 0;
}
讀寫操作
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(char argc,char **argv)
{
if(argc!=3)
{
printf("param error\n\r");
return -1;
}
int fd1;
int fd2;
fd1=open(argv[1],O_RDONLY);
fd2=open(argv[2],O_WRONLY|O_CREAT,0666);
if(fd1<0||fd2<0)
{
printf("open error\n\r");
return -2;
}
while(1)
{
char buf[512];
int read_size=read(fd1,buf,512);
if(read_size==0)
{
break;
}
write(fd2,buf,read_size);
}
close(fd1);
close(fd2);
return 0;
}
**标準IO :相對于系統IO增加了io緩沖區.
ARM_V7架構
**常用寄存器組
I.MX6ULL啟動
**不同鏡像媒體啟動偏移和讀取大小
**鏡像頭内容
主要包含IVT表,Boot Data和DCD表
裸機開發
**裸機 彙編+C語言 程式編譯及鏡像檔案生成過程
start.s
.global _start //總入口标号
//啟動程式
_start:
//設定CPU運作模式(特權模式)
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0x13
msr cpsr,r0
//清除bss段
ldr r2,=__bss_start__
ldr r3,=__bss_end__
mov r12,#0
bss_loop:
cmp r2,r3
stmltia r2!,{r12}
blt bss_loop
//設定堆棧指針
ldr sp,=0x82000000
//跳轉到C語言主函數
b main
main.c
#include"MCIMX6Y2.h"
#include "fsl_common.h"
#include "fsl_iomuxc.h"
void delay(void)
{
int j;
for(unsigned int i=0;i<0xfffff/2;i++)
{
j++;
}
}
int main(void)
{
//使能時鐘
CCM->CCGR0=0xffffffff;
CCM->CCGR1=0xffffffff;
CCM->CCGR3=0xffffffff;
CCM->CCGR4=0xffffffff;
CCM->CCGR5=0xffffffff;
CCM->CCGR6=0xffffffff;
//設定複用功能
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0x10b0);
//設定電氣屬性
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);
GPIO1->GDIR |= (1<<4);
while(1)
{
GPIO1->DR |= (1<<4);
delay();
GPIO1->DR &=~(1<<4);
delay();
}
return 0;
}
Makefile
bin:./Build/start.o ./Build/main.o
arm-linux-gnueabihf-ld -Ttext 0x80000000 $^ -o ./Build/sdk20-app.elf
arm-linux-gnueabihf-objcopy -O binary -g -S ./Build/sdk20-app.elf ./BurnTool/sdk20-app.bin
./Build/%.o : ./Source/%.c
arm-linux-gnueabihf-gcc -I ./Include -c $< -o $@
./Build/%.o : ./Source/%.s
arm-linux-gnueabihf-gcc -I ./Include -c $< -o $@
clear:
rm ./Build/*.o ./Build/*.elf ./BurnTool/sdk20-app.bin ./BurnTool/sdk20-app.img
.bin生成.img(燒錄工具從NXP官方sdk中扣出來的)插入SD卡執行下面指令:[email protected]:~/imx6ull/裸機工程/BurnTool$ ./mkimage.sh sd
#######################/BurnTool/mkimage.sh############################
#!/bin/bash
function usage()
{
echo "Usage: $0 target"
echo " target: ram -- the image will be loaded to RAM and run, the application must be built with ram link file"
echo " target: flash -- the image will be run on flash directly, the application must be build with flash link file"
echo " target: sd -- the image will be loaded from SD to RAM and run, the application must be build with ram link file"
echo "Example: $0 ram"
}
if [ "$#" -ne 1 ]; then
usage $0
exit 1
fi
SYSTEM=`uname -s`
if [ $SYSTEM == "Linux" ]; then
DCD_BUILDER=dcdgen.bin
IMG_BUILDER=imgutil.bin
else
DCD_BUILDER=dcdgen.exe
IMG_BUILDER=imgutil.exe
fi
./$DCD_BUILDER dcd.config dcd.bin
if [ "$1" == "ram" ]; then
./$IMG_BUILDER --combine base_addr=0x80000000 ivt_offset=0x1000 app_offset=0x2000 dcd_file=dcd.bin app_file=sdk20-app.bin ofile=sdk20-app.img image_entry_point=0x80002000
elif [ "$1" == "flash" ]; then
./$IMG_BUILDER --combine base_addr=0x60000000 ivt_offset=0x1000 app_offset=0x2000 dcd_file=dcd.bin app_file=sdk20-app.bin ofile=sdk20-app.img image_entry_point=0x60002000
elif [ "$1" == "sd" ]; then
./$IMG_BUILDER --combine base_addr=0x80000000 ivt_offset=0x400 app_offset=0x2000 dcd_file=dcd.bin app_file=sdk20-app.bin ofile=sdk20-app.img image_entry_point=0x80002000
else
echo "Unsupported target $1"
usage $0
fi
sudo dd if=sdk20-app.img of=/dev/sdc bs=512 seek=0
U_Boot
**md[.b .w .l] address [# of objects]
以[.b .w .l]形式,顯示address對應的[# of objects]個值.
**nm 修改記憶體
**mm 修改記憶體後位址自增
**mw 填充記憶體
**cp 拷貝
**cmp 比較
**開發闆在運作u-boot時通過網絡ping主機出現重新開機現象,主要是由于編譯器版本過高,使用低版本編譯器編譯u-boot後問題解決.
**u-boot使用nfs下載下傳檔案時出現如下情況(原因:主機nfs服務版本太高)
解決辦法:修改/etc/default/nfs-kernel-server檔案如下:
# Number of servers to start up
RPCNFSDCOUNT="-V 2 8"
# Runtime priority of server (see nice(1))
RPCNFSDPRIORITY=0
# Options for rpc.mountd.
# If you have a port-based firewall, you might want to set up
# a fixed port here using the --port option. For more information,
# see rpc.mountd(8) or http://wiki.debian.org/SecuringNFS
# To disable NFSv4 on the server, specify '--no-nfs-version 4' here
RPCMOUNTDOPTS="-V 2 --manage-gids"
# Do you want to start the svcgssd daemon? It is only required for Kerberos
# exports. Valid alternatives are "yes" and "no"; the default is "no".
NEED_SVCGSSD=""
# Options for rpc.svcgssd.
RPCSVCGSSDOPTS="--nfs-version 2,3,4 --debug --syslog"
**開發闆網卡位址
eth1:06:aa:91:5d:3a:d2
eth2:4a:60:11:04:01:57
**fatload 加載核心到記憶體的關鍵指令
**bootz addr initrd fdt
addr:鏡像在ram中的位址
fdt:裝置樹在ram中的位址
**boot
**/sys/bus/cpu/devices/cpu0/
核心啟動
setenv bootargs 'console=ttymxc0,115200 rw root=/dev/nfs nfsroot=192.168.1.2:/home/cxw/imx6ull/rootfs ip=192.168.1.3:192.168.1.2:192.168.1.1:255.255.255.0::eth0:off'
setenv bootcmd 'fatload mmc 0:1 80800000 zimage;fatload mmc 0:1 83000000 imx6ull-14x14-evk.dtb;bootz 80800000 - 83000000'