顯示具有 linux embeded system&cgi 標籤的文章。 顯示所有文章
顯示具有 linux embeded system&cgi 標籤的文章。 顯示所有文章

2025年8月6日 星期三

Linux kernel minor upgrade

 今天嘗試把 kernel v4.19.98 作微升級,要升級到 v4.19.325,因為我們原本的 kernel 並不是原生最乾淨的 Linux kernel v4.19.98(是拿MTK平台的 SDK),先講我打上了這兩個版本中間的 patch,但最終編譯,卻有一堆error,解不完

 但我認為,作這件事情,中間的過程,是值得作個記錄的,因此寫了這篇文章,來記錄中間所做的步驟。

1. 下載 Linux 的 branch,使用指令如下:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

2. 每個版本都有打上tag,因此我們可以先 checkout 到 v4.19.325
git checkout v4.19.325

3. git log 確認一下 v4.19.325 與 v4.19.98 分別的 commit hash 號碼是多少










4. 使用指令,把 98 ~ 325 這中間的 commit 都作成 patch 檔,指令如下:
git format-patch d183c8e2647a7d45202c14a33631f6c09020f8ac..a67e7cdde7cc7984ae24c3c81a70dc1aa34424b1 -o patch/

5. 可以看到,目前目錄底下,會產出資料夾 patch/ ,裡面有 19xxx個patch 檔,依序都做好了編號

6. 接著我們準備要來打 patch,先說明一下,我目前的目錄環境是這樣,
apps/src/kernel/linux/4.19/,我目前專案的 repository 是在 apps底下,也就是我可以在 apps底下執行 git log,可以看到以往的 commit 資訊,而目前是要把 linux patch 打到   apps/src/kernel/linux/4.19/ 底下

7. 因為第6.的關係,我們把 patch/ 移動到 apps底下,我們打patch 的指令會如下:
cd apps/
git am --directory=src/kernel/linux/v4.19 patch/* -3  

(加上 -3(或 --3way)後,如果直接套用失敗,Git 會嘗試用三方合併的方式來解決衝突,這樣有時候可以自動解決一些簡單的衝突)

8. 打patch 的途中,會遇到許多的 conflict,你會需要開啟檔案,去解衝突,但我發現 19xxx筆patch,要解的 conflict 實在太多了,後來遇到 conflict 直接使用以下command,意思是直接幫我把衝突的舊檔案的部分刪除,把新的patch 新增的內容,改到檔案裡面: 
git checkout --theirs $file (file帶入中途的檔案路徑 與 名稱)

9. 途中會遇到一些,甚麼都沒改的 patch,會需要手動執行 git am --skip 來繼續,另外解完 conflict 的檔案,要手動執行 git am --continue 來讓 git am 繼續跑

10. 另外有遇到一個,git am 打patch,我發現有一個限制,就是打到 9999個 patch的時候,你再輸入 git am --continue 會沒辦法繼續,如下圖,這時候你必須要先 git push,把先前打的patch 都git push,然後再繼續從第 10000筆繼續打,我的作法是




   







   a. 在作第4部的時候,也順便把檔案列表資訊,輸出到一個檔案:
git format-patch d183c8e2647a7d45202c14a33631f6c09020f8ac..a67e7cdde7cc7984ae24c3c81a70dc1aa34424b1 -o patch/ > patch_list.txt
   b. 想辦法使用 note 或是 Notepad++ 把這些列表改成
rm 0001-xxxx
rm 0002-xxxx
..
rm 9999-xxxx
   c. 切換到 patch/ 資料夾,把 0001~9999 的patch 檔案都刪除
   d. 在接著使用git am 的命令繼續打剩餘的 patch:
git am --directory=src/kernel/linux/v4.19 patch/* -3  


結論: 
   1. 我在這次的過程中,寫了以下兩隻script,當發生conflict,就使用git checkout --theirs $file 去解conflict,因此可以一直遞迴去處理patch,但遇到 git am --continue 無法繼續的空內容,目前就是手動去下 git am --skip
   2. 其實比較好的做法,應該要是以下步驟
        a. 先 git checkout 到 linux pure v4.19.98
        b. 把vendor最一開始給的 kernel 覆蓋到
 linux pure v4.19.98
        c. git diff 看一下改了那些檔案
        d. 直接把 
linux pure v4.19.98,checkout 到 v4.19.325,然後試著把 前一步驟,git diff 的改回去,但如果真的差異太大,就是一個很大的工程了....

以下分享我的兩個 shell script: (主要就是執行 ./for_loop.sh)

主程式:  for_loop.sh

#!/bin/sh
for i in {1..20000}
do
    ./fail_process.sh
    if [ $? -eq 2 ]; then
        echo "fail_process.sh failed, stopping loop."
        break
    fi
done

副程式:  fail_process.sh

#!/bin/sh

# Get the list of files marked as "both modified" from gg (git status)
files0=$(git status | grep "both modified:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files0; do
    echo "Processing $file ..."
    git checkout --theirs $file
    git add $file
done


# Get the list of files marked as "deleted by them:" from gg (git status)
files1=$(git status | grep "deleted by them:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files1; do
    echo "Processing $file ..."
    git add $file
done

# Get the list of files marked as "deleted by us:" from gg (git status)
files2=$(git status | grep "deleted by us:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files2; do
    echo "Processing $file ..."
    git add $file
done


# Get the list of files marked as "both added" from gg (git status)
files3=$(git status | grep "both added:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files3; do
    echo "Processing $file ..."
    git checkout --theirs $file
    git add $file
done

if [ -z "$files0" ] && [ -z "$files1" ] && [ -z "$files2" ] && [ -z "$files3" ]; then
        exit 2
fi

git status
git am --continue



2025年6月25日 星期三

core dump 以及透過 gdb 來debug,問題點出在哪

 今天我們拿 systemd-journald 的 core dump 來當範例
 解壓縮 core_systemd-journald.tar 可以看到資料夾內有以下檔案


我們這篇,主要是去拿 exe.lz4 與 core.lz4 來放到 gdb 裡面,來做debug

所以我們先把者兩個 lz4 檔案,放到linux 系統中使用以下 command 把他解開,得到兩個檔案,分別是 core 與 exe,
core 是 core dump 紀錄的錯誤資訊,exe 則是此執行檔(systemd-journald)
=>
lz4 -d core.lz4 core
lz4 -d exe.lz4 exe

接著我們把 core 與 exe 丟到有gdb 的 device上,如果編譯的時候,也有編譯出 symbol 的 library 或是 執行檔,也可以準備一下,等等 gdb 會使用到 (symbol 就是沒有被 strip 的檔案)
symbol資料夾如下:


接著到平台上,執行 gdb,command 如下:
=>
gdb exe core


可以看到Core was generated by `/lib/systemd/systemd-journald'.
Program terminated with signal SIGABRT, Aborted.
=> systemd-journald 因為 SIGABRT造成的 crash

接著可以用 bt full 印出完整的資訊

目前只能知道,在 libc.so.6 這個 library的 function,writev() 出了問題,下面指出
No symbol table info available
我們就去找 symbol folder,試試看用 systemd-journald 的 binary跑gdb 試試看


gdb systemd-journald core
會看到多了一些資訊,gdb似乎有載入一些資訊


此時,在重新執行剛剛的指令,可以看到更完整的資訊
=>
gdb exe core
  








2025年6月20日 星期五

指令,把read-only 的filesystem,remount 成 read/write

使用mount指令,先看一下,目前 / 掛載為 read-only,ext4 的 filesystem
root@:# mount
/dev/mmcblk0p16 on / type ext4 (ro,relatime,norecovery)


把 root folder 重新掛載成可 read/write
 mount -o remount,rw /

再用mount看一次
root@:~# mount
/dev/mmcblk0p16 on / type ext4 (rw,relatime,norecovery)

2024年12月6日 星期五

在adb shell 執行一個背景程式,如何讓 adb shell中斷後,此背景程式不會被中斷

 今天遇到有客人問一個問題
 他想要用 tcpdump 抓封包,指令如下:
tcpdump -i any -C 100 -W 10 -U -w /tmp/tcpdump.cap &

但因為,我們的device,在拔除usb之後,device可以進入 suspend
他想要在 wakeup的時候,抓到是甚麼樣的封包,

另外他想要透過 adb shell 去執行這個指令,所以當下完上面指令,adb shell 斷線之後
tcpdump 也終止了

查詢與嘗試了一下,可以使用以下指令解決
nohup tcpdump -i any -C 100 -W 10 -U -w /tmp/tcpdump.cap > /tmp/tcpdump.log 2>&1 &

只要確保 /tmp 目錄是可寫的,這樣 tcpdump 的輸出和錯誤信息將被寫入到 /tmp/tcpdump.log 文件中


2021年9月27日 星期一

vi / vim 常用的搜尋方法

以下方式都是在command 模式,(按小寫i 就會切換到編輯模式,在按一次ESC會切到command模式)

1. 將游標移到字串上,直接按"*" ,可以直接做向下搜尋

2. 輸入"/", 接著輸入字串,可以向下搜尋此字串,接著按"n",可以向下搜尋,按"N",可以向上搜尋

3. 按下"?", 接著輸入字串,可以向上搜尋字串,接著按"n",可以向上搜尋,按"N",可以向下搜尋

4. 按下":",輸入"set num",可以列出整篇文字檔的"行號" 

2021年8月23日 星期一

編譯遇到 error: braces around scalar initializer [-Werror] 的解決方法

首先 braces 中文意思為 "大括號",

而編譯出現這個錯誤訊息時,十之八九問題出在少了對稱的大括號,

因此請仔細檢查一下,是否漏了"{" 或是加錯地方.

2021年8月20日 星期五

當要 export GPIO, 或是使用 gpio_request 遇到 write error: Device or resource busy 的解決方法

 當使用  echo 0 > /sys/class/gpio/export
kernel卻拋出 -sh: echo: write error: Device or resource busy

這表示此GPIO正被某個driver占用,因此你沒辦法申請這個GPIO來使用
而這個問題的解決方法,只能找出是哪個driver code, 做完 gpio_request()之後 卻沒有做 gpio_free()的地方

另外可以使用下面指令來查看那些gpio被占用

cat /sys/kernel/debug/gpio

=======================================================

另外下面記錄一些gpio操作的指令

第一步可以先ls /sys/class/gpio,有的可以從這邊看到gpio的base值 

(例如base=268, gpio0在下面的操作就要echo 268+0, gpio10就會是 268+10)

1. request gpio
echo 0 > /sys/class/gpio/export

2. check dicrection value
cat /sys/class/gpio/gpio0/direction

3. change direction
echo out > /sys/class/gpio/gpio0/direction

4. check output value
cat /sys/class/gpio/gpio0/value

5. change output value to high
echo 1 > /sys/class/gpio/gpio0/value

6. free the gpio
echo 0 > /sys/class/gpio/unexport




2019年5月24日 星期五

u-boot底下使用指令 mw, md 來寫入/讀取 register的值

寫入
mw [位址] [value] [長度]

example:
    mw 0xf10a8180 1f9e1001 1   ==> 修改位址0xf10a818032bit改為1f9e1001



讀取
md [位址] [長度]

example:
    md 0xf10a8180 1  ==> 讀取位址0xf10a8180的值長度為1個32bit


2019年4月16日 星期二

制作initial RAM filesystem,以及讓kernel boot into RAM disk filesystem

首先會從u-boot的 bootargs參數開始,關鍵在於這兩個藍色字的參數,可以讓kernel booting到RAM disk

bootargs "root=/dev/ram0 rw console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 no_console_suspend init=/init rootdelay=3 rootfstype=ext4"


當u-boot開到kernel之後,Kernel就會去把你包的Initial RAM filesystem 掛載到 root參數(也就是/dev/ram0) ,前提是你的 Initial RAM filesystem要記得要建立/dev/ram0

再來當你的 Initial RAM filesystem 掛載好之後,會接著去跑第二個參數 init這個檔案,init通常是一支shell script,也是kernel轉換到filesystem後的第一個檔案,他的動作通常會去掛載一些資料夾之後就幫忙導到linuxrc(也就是busybox),接著就成功進入作業系統


先列出我Build Code環境,各個資料夾的樹狀結構


















下面列出各個階段Programer需要作的事情:

1. U-Boot
修改 bootargs 參數,修改的內容如上面所敘述

2. 編譯Busybox
下載一包Busybox,先去執行make menuconfig,接著去設定要安裝的路徑,如下圖:
 Settings  --->
     --- Installation Options ("make install" behavior)


















接著,可以把Busybox編譯成Static Library的方式,如下圖:
Settings  --->
    [*] Build static binary (no shared libs)

















上面步驟都設定完成後,離開並儲存,在去作make install,最後會生出一個簡易的root filesystem(還不完整)


3. 制作 Initial RAM filesystem
請先到上個步驟當中,安裝Busybox的路徑,會看到如下圖,皆為Busybox所產生:






接著我們要繼續補足 Initial RAM filesystem所缺少的,分別作以下幾個步驟:
3-1. 建立 proc資料夾,sys資料夾 (mkdir proc; mkdir sys)
3-2. 建立 init檔案,其內容如下:
#!/bin/sh -x
MOUNT="/bin/mount"
${MOUNT} -t proc /proc /proc
${MOUNT} -t sysfs /sys /sys
${MOUNT} -t usbfs none /proc/bus/usb
${MOUNT} -t devpts devpts /dev/pts
/linuxrc

3-3. 建立dev資料夾,以及所需要的device node,執行 makedev.sh來建立,內容如下:
(內容較多,我把他補充再文章最後) ...

以上三個小步驟完成後,就建立出基本的 Initial RAM filesystem,如下圖:




4. Kernel
首先要先作make menuconfig,並且把 Initial RAM filesystem選像打開,並且選擇已經編譯好的busybox(我編譯好的busybox在kernel資料夾的上一層資料夾 ../build/fs.initrd/),路徑如下:
General setup ---->
     [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
     (../build/fs.initrd/) Initramfs source file(s)

存檔離開後,執行make,便會把Initial RAM filesystem包進Kernel當中



當上面的Kernel都準備好了之後,讓U-Boot booting進入Kernel. 應該就可以順利進入RAM filesystem了。


如果遇到Failed to execute /init (error -2)的Kernel Panic情形,請確認下面幾件事情
1. Busybox選項是否有開啟mount指令
2. Busybox是否有開啟Static Build
3. 請在安裝完Busybox之後,把產生出的busybox執行檔,權限改為Superuser (chmod +s busybox)


















用法: ./makedev.sh (busybox安裝路徑)

##################  makedev.sh ############################
#!/bin/sh

if [ x$1 == "x" ]; then
        echo ""
        echo "Usage:   makedev ROOTDIR"
        echo ""
        echo "  ROOTDIR is the directory of root FS, please use full path."
        echo ""
        exit 0
fi

rm -rf $1/dev/*
cd $1/dev/

DEVINDEX=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
NODEINDEX=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
M_NUM=8
N_NUM=0
DEVNODE=sd
TYPE=b

major=${M_NUM}
minor=${N_NUM}

for i in ${DEVINDEX[@]} ; do
        mknod -m 660 ${DEVNODE}${i} ${TYPE} ${major} ${minor}
        let minor=minor+1

        for j in ${NODEINDEX[@]}; do
                mknod -m 660 ${DEVNODE}${i}${j} ${TYPE} ${major} ${minor}
                let minor=minor+1
        done

        if [ $minor -gt 255 ]; then
                let major=65
                let minor=0
        fi
done


mknod -m 600 mem        c 1 1
mknod -m 666 null       c 1 3
mknod -m 666 zero       c 1 5
mknod -m 644 random     c 1 8
mknod -m 444 urandom    c 1 9
mknod -m 600 tty0       c 4 0
mknod -m 600 tty1       c 4 1
mknod -m 600 tty2       c 4 2
mknod -m 600 tty3       c 4 3
mknod -m 600 tty4       c 4 4
mknod -m 600 tty5       c 4 5
mknod -m 600 ttys0      c 3 48
mknod -m 600 ttyS0      c 4 64
mknod -m 600 ttys1      c 3 49
mknod -m 600 ttyS1      c 4 65
mknod -m 600 ttys2      c 3 50
mknod -m 600 ttyS2      c 4 66
mknod -m 666 tty        c 5 0
mknod -m 600 console    c 5 1
mknod -m 755 ram0       b 1 0
mknod -m 755 ram1       b 1 1
mknod -m 755 ram2       b 1 2
mknod -m 755 ram3       b 1 3
mknod -m 755 ram4       b 1 4
mknod -m 660 loop0      b 7 0
mknod -m 660 loop1      b 7 1
mknod -m 660 loop2      b 7 2
mknod -m 660 loop3      b 7 3
mknod -m 644 crypto     c 10 70
mknod -m 644 cesa       c 10 71
mknod -m 660 rtc0       c 254 0

for i in $(seq 0 8)
do
mknod mtd$i c 90 $(expr $i + $i)
mknod mtdblock$i b 31 $i
done

mknod -m 660 fb0 c 29 0

mknod md0 b 9 0
mknod md1 b 9 1
mknod md2 b 9 2
mknod md3 b 9 3
mknod md4 b 9 4

mknod sg0 c 21 0
mknod sg1 c 21 1
mknod sg2 c 21 2
mknod sg3 c 21 3
mknod sg4 c 21 4
mknod sg5 c 21 5
mknod sg6 c 21 6
mknod sg7 c 21 7
mknod sg8 c 21 8
mknod sg9 c 21 9
mknod sg10 c 21 10
mknod sg11 c 21 11
mknod sg12 c 21 12
mknod sg13 c 21 13
mknod sg14 c 21 14
mknod sg15 c 21 15

mknod sr0 b 11 0
mknod sr1 b 11 1
mknod sr2 b 11 2
mknod sr3 b 11 3
mknod sr4 b 11 4
mknod sr5 b 11 5
mknod sr6 b 11 6
mknod sr7 b 11 7
mknod sr8 b 11 8
mknod sr9 b 11 9
mknod sr10 b 11 10
mknod sr11 b 11 11
mknod sr12 b 11 12
mknod sr13 b 11 13
mknod sr14 b 11 14
mknod sr15 b 11 15

mknod -m 666 ptmx       c 5 2

mknod ppp c 108 0

mknod fuse c 10 229

mkdir shm

#i2c
I2C_INDEX=(0 1 2)
for i in ${I2C_INDEX[@]}; do
        mknod -m 600 i2c$i c 89 $i
        mknod -m 600 i2c-$i c 89 $i
done

#for sshd
mknod ptyp0 c 2 0
mknod ptyp1 c 2 1
mknod ptyp2 c 2 2
mknod ttyp0 c 3 0
mknod ttyp1 c 3 1
mknod ttyp2 c 3 2

#pts
mkdir pts; cd pts
mknod -m 640 0          c 136 0
mknod -m 640 1          c 136 1
mknod -m 640 2          c 136 2
mknod -m 640 3          c 136 3
mknod -m 640 4          c 136 4
mknod -m 640 5          c 136 5
cd ..

mknod hiddev0   c 180 96
cd ..

cd ../../

exit 0
###############################################





2019年4月11日 星期四

Linux 進入rootfs之後,查詢u-boot bootcmd變數的方法

進入Kernel後,在檔案系統中,若想要查詢u-boot的bootcmd參數值,可以用下面的指令來查詢~

# cat /proc/cmdline


2019年1月17日 星期四

[Linux] 使用dd 來測試硬碟或是一些儲存裝置的讀寫速度(Read/Write), Throughput testing

我們寫了兩支script 來測試掛載在/mnt/public上的storage throughput(Read/Write)
Write 的部分,我們測試2G的檔案,每次作完dd,我們會去清除cache,sleep 10 秒後,再次執行,總共循環5次

=================== Using dd to test storage write throughput(RX) =================
#!/bin/sh
count="1"
while [ 1 ]
do
dd if=/dev/zero of=/mnt/public/2GGG bs=1M count=2048
sync
echo "sleep 10 sec"
sleep 10
echo 1 > /proc/sys/vm/drop_caches
sync
echo "sleep done"
if [ $count -eq "5" ]; then
 exit
fi
count=$(($count+1))
done
====================================================================


Read 的部分,我們測試2G的檔案,每次作完dd,sleep 5 秒後,再次執行,總共循環5次

=================== Using dd to test storage read throughput(TX) =================
#!/bin/sh
count="1"
while [ 1 ]
do
dd of=/dev/null if=/mnt/public/2GGG bs=1M count=2048
sync
echo "sleep 5 sec"
sleep 5
sync
echo "sleep done"
if [ $count -eq "5" ]; then
 exit
fi
count=$(($count+1))
done
==================================================================:

2019年1月3日 星期四

How to build iperf3 on ARM platform (static build)

1. apt-get install git-core  //install git tool
2. apt-get install make    //install make tool, to make iperf3
3. git clone https://github.com/esnet/iperf   //clone iperf3 source code
4. cd iPerf  //go to the iperf3 source code folder, and compile it
5. ./configure --enable-static --disable-shared ; make ; make install  //static build

按照以上步驟,便可以在你的平台上編譯好 iperf3 並且可以使用~

**若是沒有gcc,而導致configure的時候出錯,請先使用以下指令安裝
apt-get install gcc

2018年11月26日 星期一

在Linux底下,使用setpci 來設定/讀取 Intel CPU register值

假設我們今天想要更改Intel CPU的PowerResume,首先你必須知道你要改的是文件裡面的AG3E的Register值,其文件大概會如下圖所示:




















首先看到Type,確定他是屬於PCI Configuration Register,你才能夠使用setpci tool來作更改,接著我們可以看到,Offset: [B:0, D:31, F:2]+A4h

其中的英文分別代表 Bus, Device, Function,如文件所描述,我們要更改的為第0個bit,假設我們要把值設定為1,因此在Linux底下我們的指令下法為:

setpci -s 00:1F.2 A4.B=01     
*註(31=1Fh), A4.B意思是從A4寫1Byte

假設你想再把值讀出來看,在Linux底下我們的指令下法為:

setpci -s 00:1F.2 A4.B

2018年10月8日 星期一

C語言使用malloc配置一個struct記憶體空間

假設有一個struct如下所示:

struct foo {
     char *a;
     int b;
     char c[20];
};

當我們要用malloc配置記憶體時,通常會用下面的方式來作宣告:


struct foo *ptr = (struct foo *) malloc(sizeof(struct foo));


另一種較簡潔的寫法,如下所示:

struct foo *ptr = malloc(sizeof(*ptr));

2018年4月23日 星期一

[Linux Embedded System] Linux的Serial port(ttyS1) 無法登入&輸入訊息,但是透過VGA(tty1)的卻可以

今天遇到了一個很奇怪的問題,首先我的平台有兩個終端介面可以使用,一個是透過VGA輸出到螢幕的終端介面,可供我們對機器下指令。另一個則是透過Serial port(UART),利用Tera Term或是putty等軟體,來對機器下指令

今天遇到的問題是,進入Linux系統之後,VGA那邊的終端介面可以順利的輸入訊息,機器也能順利的給予回饋,而Serial port的部分則是無法輸入任何訊息,看起來就像是無法進到sh一樣(如下圖)。















我也嘗試了一下,從能夠下指令的VGA那方,輸入下面的指令
#echo "ls" | sh > /dev/ttyS1

結果在ttyS1那方還真有一些回饋訊息,看來問題是跟sh有所關係

















後來找了一些資料,發現可能的問題出在/etc/inittab

最後的解決方法,是去修改/etc/inittab 這之檔案,在裡面的內容多加一行 ttyS1::respawn:-/bin/sh

















重新啟動之後便能夠順利的進入shell 模式底下囉!!!


*註
若是進入到 Linux Kernel 底下,無Serial 訊息,請先確認您的硬體是使用UART1 或 UART2
UART1 就必須指定你的Console參數 ===>  Console=ttyS0
UART2 就必須指定你的Console參數 ===>  Console=ttyS1


2018年4月19日 星期四

#pragma pack() 的用途與用法


#pragma pack 會要求compiler 使用特別的對齊方式來包裝 Structure Member . 大多數的compilers, 當你宣告一個結構時, 將會在彼此成元之間插入 padding 來確保他們在記憶體中的對齊。下面舉個例子:

struct Test
{
   char AA;
   int BB;
   char CC;
};

 compiler 可能會在記體中選擇以下列的方式來排列對齊:

|   1       |   2       |   3       |   4       |  

| AA(1) | pad..............................|
| BB(1) | BB(2) | BB(3) | BB(4) |
| CC(1) | pad..............................|
雖然真正的資料只佔了6 (byte),但是 sizeof(Test) 結果會是 4 × 3 = 12(byte)



#pragma比較常使用的時機,是在與Hardware device作溝通的時候,你為了要確保compiler不會插入padding,這時候你就會使用 #pragma pack(1),而結構的排列就會如下:

|   1      |

| AA(1) |
| BB(1) |
| BB(2) |
| BB(3) |
| BB(4) |
| CC(1) |
sizeof(Test) 結果就會變成 1 × 6 = 6(byte).


如果是使用 #pragma pack(2), 結構的排列就會如下::

|   1       |   2       | 

| AA(1) | pad... |
| BB(1) | BB(2) |
| BB(3) | BB(4) |
| CC(1) | pad... |
sizeof(Test) 結果就會變成 2 × 4 = 8(byte).



下面是一個簡單的範例,我們使用#pragma pack(1),並印出structure 大小:
==================   pragma.c  ==========================
#include <stdio.h>

int main()
{
#pragma pack(1)
        struct test {
           char A;
           int B;
           char C;
        };

        typedef struct test Struct_Test;

        Struct_Test AA;
#pragma pack()
        printf("Sizeof Struct_Test is %d\n", (int)sizeof(AA));
        return 0;
}
====================================================

執行結果:


2018年3月27日 星期二

【Linux Tool】i2c-tools 的使用方法, i2cdetect 、 i2cdump、i2cset

i2c-tools是一套OpenSource,透過這個tools我們可以透過i2c 介面與 IC 去作溝通

我們可以到下面的網站去抓整包的SourceCode,然後再透過你的toolchain去編譯出你板子上可以使用的工具,而編譯的方式我這邊就不贅述,我們這篇著重在tool如何使用

Download Path:
https://i2c.wiki.kernel.org/index.php/I2C_Tools

====================================================================
編譯完成後你應該會有i2cdetect、i2cdump、i2cset 這幾個執行檔

i2cdetect  ===> 會列出 i2c的 Bus上所有的Device
i2cdump   ===> 會列出 Device上所有的 Register值
i2cset       ===> 可寫入到某個 Bus上的某個 Device上的 Register值


以下是實際操作的範例:
#./i2cdetect -l     ===> 列出總共有幾個 i2c Bus












從上圖我們可以知道,這台設備上總共有 0 ~ 8 個 I2C Bus


另外我們也可以使用 i2cdetect 來確認 Bus上有哪些 Device
#./i2cdetect -r -y 1   ===> 列出 Bus 1上的所有Device













從上圖我們可以知道,這台設備的 I2C Bus1上,有4個Device,位置分別在 0x37, 0x4a, 0x4b, 0x50


接著我們來使用i2cdump來把某個 Register的值列出來吧!
#./i2cdump -f -y 1 0x50  ===> 列出 Bus1 的 Device 0x50的 Register值














最後我們使用 i2cset來更改Register的值吧!
#./i2cset -y 1 0x50 0x36 0x05  ===> 寫入 Bus1 的 Device 0x50的 0x36 Register值 寫入 0x05

註: i2cset的用法:
#./i2cset -y <bus> <device> <register> <value>

2018年1月12日 星期五

error: dereferencing pointer to incomplete type ‘struct task_struct’

今天在編譯iqvlinux的時候,之前在kernel 4.10.17編譯時,都不會有什麼error產生

而今天改成在kernel 4.14.12編譯時出現了以下的錯誤訊息:

make: Entering directory '/home/danny/platform/project-4.14.12/linux-4.14.12'
  CC [M]  /home/danny/platform/project-4.14.12/sysapps/gmac/iqvlinux/src/linux/driver/linuxnaldriver.o
In file included from /home/danny/platform/project-4.14.12/sysapps/gmac/iqvlinux/src/linux/driver/linuxnaldriver.c:42:0:
./arch/x86/include/asm/uaccess.h: In function ‘set_fs’:
./arch/x86/include/asm/uaccess.h:33:9: error: dereferencing pointer to incomplete type ‘struct task_struct’
  current->thread.addr_limit = fs;
              ^

發生錯誤的流程如下說明:
編譯到linuxnaldriver.c的42行,這邊第42行是去include <asm/uaccess.h>,接著錯誤訊息就說明錯誤發生在 set_fs(),然後最後的錯誤是在 uaccess.h 的第33行,錯誤訊息就是如上面的error那行

查了一下google,很多人都說只要include header就可以解決,於是我先找了一下‘struct task_struct’的結構宣告在哪個檔案,google之後發現在<linux/sched.h>
















於是我在 linuxnaldriver.c 42行前面加了 #include <linux/sched.h>

再進行編譯,於是就編譯成功了

2017年9月8日 星期五

解決 ssh 輸入root帳號與密碼都無法登錄的問題

最近在Device上要使用ssh登入,看了一下Device上sshd都跑在背景了,我使用putty來做ssh連線

連上線之後,要輸入帳號密碼,ssh的帳號密碼應該會跟你透過UART登入使用同樣的帳號密碼,也就是說要改密碼直接使用passwd就行

但是我使用putty透過ssh連上Device後卻一直登入不了(Access Denied)








後來找到解法,發生這種問題,必須先去修改Device上sshd的config檔,位於/etc/ssh/sshd_config,請把位於Authentication底下的PermitRootLogin 後面的值改為 yes












然後重啟Device上的sshd










完成以上步驟之後,就可以順利透過ssh登入了!!!

2017年7月25日 星期二

【Linux cmd】linux系統下,壓縮解壓縮指令

附檔名為 tar.xz 的檔案

壓縮:  tar Jcvf file.tar.zx DirName

解壓縮: tar Jxvf file.tar.zx
============================================

附檔名為 zip 的檔案

壓縮:  zip file.zip DirName
           zip -r file.zip DirName

解壓縮: unzip file.zip
解壓縮到特定資料夾(ex:5566): unzip file.zip -d 5566
==============================================

附檔名為 tgz 的檔案

壓縮:  tar -zcvf file.tgz DirName

解壓縮: tar -zxvf file.tgz
=============================================

附檔名為 tar.tgz 的檔案

壓縮:  tar -zcvf file.tar.tgz DirName

解壓縮: tar -zxvf file.tar.tgz
==============================================

附檔名為 gz 的檔案

壓縮:  gzip file.gz DirName

解壓縮: gunzip file.gz    or    gzip -d file.gz
=============================================



附檔名為 tar.gz 的檔案

壓縮:  tar -zcvf file.tar.tgz DirName

解壓縮: tar -zxvf file.tar.tgz
==============================================

附檔名為 bz 的檔案

解壓縮: bzip2 -d file.bz    or    bunzip2 file.bz
=============================================

附檔名為 bz2 的檔案

壓縮:  bzip2 -z file.bz2 DirName

解壓縮: bzip2 -d file.bz2
==============================================

附檔名為 7z 的檔案

壓縮: 7z a file.7z DirName

解壓縮: 7z x file.7z 
*Ubuntu 7z 的安裝方式:  apt-get install p7zip-full