2016年12月9日 星期五

把ethtool交叉編譯在arm平台上使用

首先去網站抓一包Source Code:
         http://ftp.kernel.org/pub/software/network/ethtool/

解壓縮之後,先在資料夾中新增一個檔案cross_configure.sh內容如下:
================= cross_configure.sh ==================

#!/bin/sh
ARM_TOOLCHAIN_DIR=/opt/arm/bin     #please type your toolchain path
export CROSS_COMPILE="${ARM_TOOLCHAIN_DIR}/arm-linux-gnueabi-"
export AR="${CROSS_COMPILE}ar"
export AS="${CROSS_COMPILE}as"
export LD="${CROSS_COMPILE}ld"
export NM="${CROSS_COMPILE}nm"
export CC="${CROSS_COMPILE}gcc"

export FC="${CROSS_COMPILE}gfortran "
export RANLIB="${CROSS_COMPILE}ranlib"
export STRIP="${CROSS_COMPILE}strip"
export OBJCOPY="${CROSS_COMPILE}objcopy"  
export CFLAGS="-Os -pipe -O2 -static"

./configure --target=arm-linux --host=arm-linux
===================================================

接下來幾個步驟分別為:
1. ./cross_configure.sh
2. make
3. cp ethtool 到目標板上
4. use "./ethtool -S eth0" to watch network status.


完成!!!


2016年12月7日 星期三

Cross-compile程式之後,放到板子上執行,卻顯示"/bin/ash: ./phyAccess: not found"(以我編譯phyAccess工具為範例)

今天編譯phyAccess tool準備要測試網路功能,編譯完成之後,放到板子執行時卻出現以下的錯誤訊息:
     



於是我先回到編譯的ubuntu電腦上使用file看一下編譯完成的檔案,是把程式編譯成甚麼CPU架構的,確認是ARM的無誤:




另外注意到了這個執行檔編譯完成後,是屬於dynamically linked(用file可看到如上圖),因此我用 readelf -l phyAccess | grep "program interpreter"(readelf -d phyAccess 也可看出需要哪些library) 來看看他動態連結了哪些library,發現他需要"ld-linux.so.3"的library(如下圖)
    



原來無法在板子上執行,是因為板子上缺少了這個library,因此最後的解決方法就是,編譯的時候在Makefile的 CFLAG參數裡面加上 -static(編譯成靜態)就解決此問題了。

2016年12月6日 星期二

Linux中devmem直接讀寫記憶體位置的用法

讀取
在位置0x98000000讀取32bit值
# devmem 0x98000000
0x11111111


在位置0x98000000讀取16bit值
# devmem 0x98000000 16
0x1111





寫入
在位置0x98000000寫入32bit值
# devmem 0x98000000 32 0x1111AAAA
# devmem 0x98000000
0x1111AAAA



另外如果出現以下訊息:
    devmem: can't open '/dev/mem': No such file or directory
表示Kernel端沒有開啟功能,請開啟下列選項:

=> Device Drivers                                                  
      => Character devices                                        
                       [*] /dev/mem virtual device support

這樣應該就可以了!!




2016年11月24日 星期四

linux中,格式化隨身碟的指令(ext4)

首先可以使用 "fdisk -l" 先確認好自己的隨身碟在檔案系統當中的名稱,可以在 /dev 資料夾底下找到,通常會是 /dev/sda 類似的 (/dev/sdb  or /dev/sdc 等等)

在確認完成之後就開始指令的部分了,假設我們的隨身碟是 /dev/sda:

1. sudo fdisk /dev/sda (作硬碟分割,可以做出partition table),進入fdisk後會要求你再下command,"h" 可以列出所有command,通常我們會先下"n"可以去增加一個partition,然後再下"p"會看到切出一個/dev/sda1的partition,最後再下"w"作儲存的動作

2. sudo mkfs.ext4 /dev/sda1 最後就是對剛剛切出的partition作檔案格式化,這邊的範例是格式化成ext4的格式.


作完以上步驟就可以了!!!

2016年11月17日 星期四

shell script的 字串處理,取代符號的用法,awk 以及 sed

awk

awk這個指令,可以用來處理字串,他的用法可以針對你想找的"符號"或"字串",來做切割然後可以單獨的取出,awk 使用說明如下

awk -F'要找的字符' '{print $1}'  

舉個實際例子,假設有個字串 =>  str="danny:12345:man"
那我現在想要取出danny,該怎麼做呢? 使用awk可以很簡的把他取出來
你只需下這段指令:
        echo $str | awk -F':' '{print $1}'





如果要取出12345,
        echo $str | awk -F':' '{print $2}'




如果要取出man,
        echo $str | awk -F':' '{print $3}'




如果是要取最後,也可以使用
        echo $str | awk -F':' '{print $NF}'

取倒數第二,寫法是
         echo $str | awk -F':' '{print $(NF-1)}'
        
        

sed

sed指令可以用來針對字串作以下功能  
1.以行為單位的新增/刪除   
2.以行為單位的取代與顯示
3.部分資料的搜尋並取代的功能

假設現在有一個檔案,名為hello,他的內容如下:










1.以行為單位的新增/刪除

(新增)我要印出hello的內容,並在第3行後面(也就是第四行)新增一些文字,作法如下:
       cat hello | sed '3a danny' 










(刪除)我要印出hello的內容,並刪除2~5行,作法如下:
       cat hello | sed '2,5d' 








2.以行為單位的取代與顯示

(取代)我要把2~5行取代為別的內容,作法如下:
       cat hello | sed '2,5c HHHHHHHHHHH' 






(顯示)我只要顯示2~5行的內容,作法如下:
       cat hello | sed -n '2,5p'







另外補充 sed 帶入變數的取某一行的方法
例如我有個變數$count="2"
我要用這個變數來取第二行,作法如下:
sed -n "${count}p"  ==> 等同於 sed -n "2p"


3.部分資料的搜尋並取代的功能

作法如下:
sed 's/要被取代的字串/新的字串/g'


例如有個字串 => str="@danny",假設我想要改成 "Hi danny",作法如下:
       echo $str | sed 's/@/Hi /g'





假設我只想要改成"danny",作法如下:
       echo $str | sed 's/@//g'





另外補充 sed 帶入變數的取代法
假設我有有個字串 => str="0.1.20180709", 我有個變數 $Date="20180709",
現在我要把str後面的".20180709"去掉, 作法如下:
       echo $str | sed "s/.$Date//g"



最後附上一個shell script範例,此範例是從一個json格式的字串中截取出user_name, passwd然後再透過smbpasswd指令去更改Samba的密碼

=================== test.sh ==========================
#!/bin/sh

input='{"user":"danny","passwd":"1234"}'
user_name=$(echo $input | awk -F',' '{print $1}' | awk -F':' '{print $2}' | sed 's/"//g')
passwd=$(echo $input | awk -F',' '{print $2}' | awk -F':' '{print $2}' | sed 's/"//g' | sed 's/}//g' )
printf "$passwd\n$passwd\n" | smbpasswd -a -s "$user_name" > /dev/null

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




2016年10月3日 星期一

解決 apt-get install 遇到404 Not Found的問題

今天同事的Ubuntu 10.4版 要使用apt-get install 安裝套件的時候遇到了404 Not Found的問題,訊息大概如下:

Err http://archive.ubuntu.com quantal/main amd64 Packages
  404  Not Found [IP: 91.189.91.15 80]
Err http://archive.ubuntu.com quantal/restricted amd64 Packages
  404  Not Found [IP: 91.189.91.15 80]
W: Failed to fetch http://security.ubuntu.com/ubuntu/dists/quantal-security/main/binary-amd64/Packages  404  Not Found [IP: 91.189.91.15 80]
W: Failed to fetch http://security.ubuntu.com/ubuntu/dists/quantal-security/restricted/binary-amd64/Packages  404  Not Found [IP: 91.189.91.15 80]
Err http://security.ubuntu.com raring-security/main amd64 Packages      
  404  Not Found [IP: 91.189.91.15 80]
Err http://security.ubuntu.com raring-security/restricted amd64 Packages
  404  Not Found [IP: 91.189.91.15 80]
Err http://security.ubuntu.com raring-security/universe amd64 Packages  
  404  Not Found [IP: 91.189.91.15 80]
Err http://security.ubuntu.com raring-security/multiverse amd64 Packages
  404  Not Found [IP: 91.189.91.15 80]



找了一下原因與解決方法,原因大概是因為,舊版的LTS(Long Term Support)版本,ubuntu只支援5年的時間(如果不是LTS版本只支援9個月),五年後ubuntu就會把更新的Server從標準的Server "http://archive.ubuntu.com/ubuntu/dist/" (apt-get 會去找的地方),移到別的地方了。

所以解決無法apt-get install的方法有兩個:

1. 更新你的ubuntu版本,使用指令 sudo apt-get dist-upgrade 去做版本更新。

2. 另一個方法你可以不要更新,可以使用 sed command 去更改 /etc/apt/sources.list 這個檔案,我們要把source.list裡面的 "archive.ubuntu.com" 和 "security.ubuntu.com" 替換成 "old-releases.ubuntu.com",在使用替換的指令之前,請先備份一下source.list檔案,如果下面方法失敗還可以把source.list復原,接著就可以執行sed替換指令,兩個步驟(command)如下:

     一. cp /etc/apt/source.list /etc/apt/back_source.list
     二. sudo sed -i -e 's/archive.ubuntu.com\|security.ubuntu.com/old-releases.ubuntu.com

當我們的source.list內容替換完成之後,請先執行update,update完成之後再作apt-get install 接下來應該就不會有404 Not Found的問題了! update的命令如下:

     sudo apt-get update

2016年8月19日 星期五

git觀念, ssh-keygen的使用方式, github註冊金鑰

今天要紀錄的是git觀念以及ssh-keygen的使用方式

git分成Server端與client端,基本上以往用常常用到git指令去github抓取open source的code,使用git抓取的人就是client端,把source code分享到他自己的github上就是server端。

當你要去抓取別人的github裡的source code時,你必須先在自己的電腦端使用ssh-keygen產生一組key,然後把這組key給server端的人,server端要幫你把這組key註冊到他的github裡,這樣你才會有權限去抓取(git clone)這個source code.

下圖是沒有註冊key去抓取github上的東西,所回應的錯誤訊息(白色是我打馬賽克的部分@@)






以上是觀念的部分,接下來是實際操作的部分



================  分隔線 ==================
首先在你的電腦端(client) 新增ssh key,輸入指令:
           ssh-keygen -t rsa -C "your_email@example.com"
 
    會出現下圖的情形,他會告知你將要產生id_rsa的金鑰檔案,請按Enter跳過




    再來會請你輸入密碼,這個密碼是當你要用git clone抓東西時,所要輸入的密碼:







   這樣就可以成功產生一個ssh key了:
















下圖是key的內容,也就是待會要向github作註冊的key






================  分隔線 ==================
接下來是github端的要做的部分

首先進入github網站,你可以自行註冊帳號,這樣你也可以放一些東西到github上,也可以用git指令去下載。

下圖是我們要把剛剛產生出來的key註冊到github server端,讓client端有權限可以作git clone.
請點選右上角的部分,然後選擇settings



















接著選擇左邊的ssh and GPG keys選項



















接著請點選New SSH key來註冊一組新的key,我們也可以看到,已經有註冊了兩組ssh key




















接著填入Title以及key的內容,按下Add SSH key即完成註冊key的動作


















    我們可以看到,現在已經註冊了三組key

















   這樣你就可以順利在你的電腦端(client)執行git clone的下載動作了。

2016年8月16日 星期二

交叉編譯 wpa_supplicant 移植到ARMv7板子

要交叉編譯wpa_supplicant,首先必須先編譯出for ARMv7的openssl

所以第一步先去抓最新版的openssl,到下面的官網下載,我這邊抓的是openssl-1.0.1t

https://www.openssl.org/

抓完之後就準備開始做openssl的cross compile了

=========== cross compile openssl for arm ================
1. ./config --prefix=/home/danny/ARMv7/

2.成功config完成之後,手動進入Makefile更改toolchain的路徑
      #++++++ Add+++
      CROSS_COMPILE=/home/danny/x-tool/armv7-rpi2-linux-gnueabihf/bin/armv7-rpi2-linux-gnueabihf-
      #======Modify =====
      CC=$(CROSS_COMPILE)gcc
      AR= $(CROSS_COMPILE)ar $(ARFLAGS) r
      RANLIB= $(CROSS_COMPILE)ranlib
      NM= $(CROSS_COMPILE)nm

3. make
    在這個步驟之後,我遇到的情形,會出現如下面所秀出的一堆ERROR訊息
     x86cpuid.s: Assembler messages:
     x86cpuid.s:4: Error: unrecognized symbol type ""
     x86cpuid.s:5: Error: alignment too large: 15 assumed
     x86cpuid.s:8: Error: bad instruction `pushl %ebp'
     x86cpuid.s:9: Error: bad instruction `pushl %ebx'
     x86cpuid.s:10: Error: bad instruction `pushl %esi'
     x86cpuid.s:11: Error: bad instruction `pushl %edi'
     x86cpuid.s:12: Error: bad instruction `xorl %edx,%edx'
     x86cpuid.s:13: Error: bad instruction `pushfl'
     x86cpuid.s:14: Error: bad instruction `popl %eax'
     x86cpuid.s:15: Error: bad instruction `movl %eax,%ecx'
     x86cpuid.s:16: Error: bad instruction `xorl $2097152,%eax'
     x86cpuid.s:17: Error: bad instruction `pushl %eax'
     x86cpuid.s:18: Error: bad instruction `popfl'
     x86cpuid.s:19: Error: bad instruction `pushfl'
     x86cpuid.s:20: Error: bad instruction `popl %eax'
     x86cpuid.s:21: Error: bad instruction `xorl %eax,%ecx'
     x86cpuid.s:22: Error: bad instruction `xorl %eax,%eax'      ..................

     請在重新config一次並在後面加入一些參數如下面指令

     ./config --prefix=/home/danny/ARMv7/ shared no-zlib no-asm no-threads no-sse2 no-gmp no-rfc3779 no-krb5 no-rc5 no-zlib-dynamic no-hw no-cipher no-md2 no-mdc2 no-rc2 no-idea no-camellia no-ec no-ripemd no-rc4 no-bf no-cast no-perlasm

     config完成之後,請記得再遵照步驟2,手動修改一下Makefile裡的toolchain路徑



4. make
    make install

這樣openssl就編譯完成,並安裝在你指定的路徑了,openssl會編譯出兩個library  分別是openssl與crypt,而wpa_supplicant還需要另一個libnl
=================================================================


============== cross compile libnl for arm ==========================
libnl我是下載 libnl-3.2.28 載點如下
http://www.linuxfromscratch.org/blfs/view/svn/basicnet/libnl.html

1. ./configure ARCH=arm --prefix=/home/danny/ARMv7/ CC=/home/danny/x-tool/armv7-rpi2-linux-gnueabihf/bin/armv7-rpi2-linux-gnueabihf-gcc --host=arm-linux LD=/home/danny/x-tool/armv7-rpi2-linux-gnueabihf/bin/armv7-rpi2-linux-gnueabihf-ld

2. make
    make install

這邊比較不會有甚麼問題,也可以成功編譯出libnl的library

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




最後是編譯wpa_supplicant的部分
=============== cross compile wpa_supplicant for arm =================
首先新進入到下面的資料夾當中

1. cd wpa_supplicant-2.5/wpa_supplicant
 
2. cp defconfig .config

3. 進入Makefile做修改
    CROSS_COMPILE=/home/danny/x-tools/armv7-rpi2-linux-gnueabihf/bin/armv7-rpi2-linux-gnueabihf-
    CC=$(CROSS_COMPILE)gcc

    export LIBDIR ?= /home/danny/ARMv7/wpa_supplicant/lib/
    export INCDIR ?= /home/danny/ARMv7/wpa_supplicant/include/
    export BINDIR ?= /home/danny/ARMv7/wpa_supplicant/bin/
    LIBS += -L/home/danny/ARMv7/lib -lssl -lcrypto

4. make


Q1. 首先會出現錯誤訊息如下所示,這是因為找不到openssl的header檔
../src/crypto/tls_openssl.c:19:25: fatal error: openssl/ssl.h: No such file or directory

請進入Makefile修改增加下面這一行,路徑是先前openssl的安裝路徑
CFLAGS += -I/home/danny/ARMv7/include



Q2. 接著會出現錯誤訊息如下所示,這是因為找不到libnl的header檔
../src/drivers/driver_nl80211.c:17:31: fatal error: netlink/genl/genl.h: No such file or directory

請進入Makefile修改增加下面這一行,路徑是先前libnl安裝的include檔路徑
CFLAGS += -I/home/danny/ARMv7/include/libnl3



Q3. 接著會出現如下的undefined reference訊息
        ../src/drivers/driver_nl80211.o: In function `get_channel_width':
        /home/danny/wpa_supplicant-2.5/wpa_supplicant/../src/drivers/driver_nl80211.c:6492: undefined reference to `genlmsg_attrdata'
        /home/danny/wpa_supplicant-2.5/wpa_supplicant/../src/drivers/driver_nl80211.c:6492: undefined reference to `genlmsg_attrlen'
        ../src/drivers/driver_nl80211.o: In function `netdev_info_handler':
        /home/danny/wpa_supplicant-2.5/wpa_supplicant/../src/drivers/driver_nl80211.c:519: undefined reference to `genlmsg_attrdata'

遇到這個問題,請修改.config檔,把原本被註解掉的這兩個項目打開
CONFIG_LIBNL20=y
CONFIG_LIBNL32=y


Q4. 遇到如下的錯誤訊息
      Package libnl-3.0 was not found in the pkg-config search path.
      Perhaps you should add the directory containing `libnl-3.0.pc'
      to the PKG_CONFIG_PATH environment variable
      No package 'libnl-3.0' found

請在terminal底下,設定如下環境變數,路徑為libnl安裝的資料夾底下lib有一個pkgconfig資料夾
export PKG_CONFIG_PATH=/home/danny/ARMv7/lib/pkgconfig


Q5. 遇到找不到libcrypto的問題,錯誤訊息如下
     ...armv7-rpi2-linux-gnueabihf/bin/ld.bfd: cannot find -lcrypto collect2: error: ld returned 1 exit status

請在Makefile中搜尋 -lcrypto,把找到的項目 前面都指定 先前編譯好安裝的openssl路徑,例如
LIBS += -L/home/danny/ARMv7/lib -lcrypto
LIBS_p += -L/home/danny/ARMv7/lib -lcrypto
總共有兩個地方要加



最後就可以順利make成功了!!!


       

  

apt-file search 的使用

當你在Ubuntu上做一些open source的編譯時

如果遇到類似這樣的訊息 ===> fatal error: openssl/ssl.h: No such file or directory

有可能是你host端(PC)缺少了一些套件

可以先使用apt-file search /openssl/ssl.h 他會跟你說你缺少的套件名稱

你就可以使用apt-get install去做安裝

2016年7月28日 星期四

如何撰寫Linux Kernel中的Timer機制

想要在kernel中寫Timer的機制,首先要些對一些專有名詞有一些初步的了解,分別是HZ, Tick, Jiffies.

HZ:Linux kernel 每隔固定週期會發出timer interrupt,HZ就是用來定義每一秒有幾次timer interrupts。例如:500 HZ 就是CPU每一秒會發出500個interrupt的意思。這個值是可以在Kernel的menuconfig當中來做設定.

Tick:Tick是HZ的倒數,意即timer interrupt每發生一次中斷所花的時間。如HZ為500時,tick為2毫秒 (millisecond)。

Jiffies:Jiffies為Linux核心變數(32位元變數,unsigned long),它被用來紀錄系統自開幾以來,已經過多少的tick。每發生一次timer interrupt,Jiffies變數會被加一。


接下來開始介紹Timer API的做法,我們先來看以下定義所代表的意義:

首先先宣告一個Timer的Struct:
struct timer_list timer;

這個Struct當中有幾個比較重要的值,我們要去做設定分別是:
timer.function    <===== timer 啟動後所設定的expires時間到後,會去做此參數所指定的function
timer.data             <===== timer 傳入function的參數值
timer.expires      <===== timer 延遲的時間,也就是延遲多久後去做 timer.function 所指定的函式

而下面這部分則是想要timer delay多久的寫法
Jiffies + HZ;   <=====  1秒之後 

Jiffies  + HZ/2;       <=====   半秒之後

Jiffies  + 20*HZ;     <=====  20秒之後


接下來就是實做一個Timer的Code.
/**************** Kernel_Timer *************/
struct timer_list danny_timer;

static int danny_do(void)
{
    danny_timer.expires = jiffies + HZ;
    add_timer(&danny_timer);
}

static void danny_timer_init(void)
{
    /* Timer 初始化 */
   init_timer(&danny_timer);

   /* define timer 要執行之函式 */
  danny_timer.function = danny_do;

  /* define timer 傳入函式之 Data */
  danny_timer.data = ((unsigned long) 0);

  /* define timer Delay 1秒的時間 */
  danny_timer.expires = jiffies + HZ;

  /* 啟動 Timer*/
  add_timer(&danny_timer);
}
/*********************************************/

結論:

所以當呼叫 danny_timer_init();之後,delay 1秒之後,會去做danny_do();

而danny_do()裡面也加了add_timer()的函式,所以會不斷的迴圈,每隔1秒鐘都會去做danny_do()的函式.



 

2016年5月19日 星期四

Linux_Driver入門-寫一個HelloWorld module

因為是driver的初學者,所以先練習寫一支HelloWorld的module,這個module的行為是當insmod這個module的時候,會印出"Hello World!"的字眼,而在rmmod的時候會印出"Goodbye, hello world"

首先描述一下整個編譯環境,以及要掛這個module的平台:
首先說明要掛這個module的平台
- arm64平台(DB410C),系統是linux

編譯平台
- PC,系統是ubuntu,DB410C的kernel與toolchain都準備好了

這邊先說明一下,當你要作交叉編譯時,一定要有Target Board(DB410C)的toolchain,以這邊的例子為例,我在PC上面編譯,我利用toolchain把程式編譯成Target Board可讀的檔案

另外要注意的是,要編譯driver,必須要拿到與Target Board相同的Kernel Source Code(版本要相同),Source code必須整包放在要進行編譯的PC端,編譯時必須參考到裡面的一些header檔

接著就來看我們的HelloWorld.c

///////////////////////////////////////////  HelloWorld.c  ///////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)
{
    printk("Hello world!\n");
    return 0;
}

static void hello_exit(void)
{
    printk("Goodbye, hello world\n");
}

module_init(hello_init);
module_exit(hello_exit);
///////////////////////////////////////////////////////////////////////////////////////////////////////////

這程式很單純,在module被insert的時候就會執行hello_init的function
在module被remove時會執行hello_exit的function



接著是Makefile的部分

obj-m += hello.o

KERNEL=/home/danny/DB410C/kernel/kernel

all:
make -C $(KERNEL) M=$(shell pwd) modules ARCH=arm64

clean:
make -C $(KERNEL) M=$(shell pwd) clean


編譯之前這邊要注意兩個部分,首先是必須給系統CROSS_COMPILE環境變數,必須給他toolchain的完整路徑,請使用export指令:
export CROSS_COMPILE=/home/Danny/DB410C/toolchain/gcc-linaro-4.9-2014.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
(請依照你的toolchain給定CROSS_COMPILE的值)

另外一部分是Makefile中KERNEL這個參數,必須要指定到PC上,Target Board(DB410C)的Kernel Source Code,這樣編譯時才不會出錯!


接著只需下make,hello.ko就會被產生出來,接著把hello.ko複製到Target Board上,接著執行
sudo insmod hello.ko

sudo rmmod hello.ko

輸入dmesg就可以看到driver印出的訊息囉!






Linux中設定root的密碼

當要使用su指令切換成root的時候 ,會請求你輸入root的密碼,但是都沒有設定過root密碼要怎麼處裡呢?

請直接輸入下面的指令:
sudo passwd root

他會要求你設定密碼,設定完成後就可以順利使用su切換root了!

2016年5月13日 星期五

Linux中設定環境變數的方法

當你需要作cross-compiler時,須要先安裝Toolchain在你的工作電腦上(Ubuntu, Fedora, Debiab etc.), 與其說安裝其實就是把Toolchain包解壓縮到某個路徑。接著要作交叉編譯時,需要指定編譯工具的路徑,此時為了不用每次都輸入一整串的路徑來指定編譯工具,就會去設定PATH。例如:我的編譯器arm-linux-gnueabihf-gcc路徑是在 "home/danny/workspace/DB410C/Toolchain/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin",此時有三個方法來設定環境變數:

1.用export指令
export PATH=$PATH:/home/danny/workspace/DB410C/Toolchain/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin
輸入之後可以使用export指令來查看環境變數是否有輸入進去。

*此修改重開機後,就必須再作一次

2.修改profile
profile的路徑是在 "/etc/profile"
直接修改profile這個檔案在裡面加入
export PATH=$PATH:/home/danny/workspace/DB410C/Toolchain/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin

*此修改必須在重開機之後,才會有作用


3.修改.bashrc
.bashrc的路徑是在"/home/danny/.bashrc"
在檔案最後面加入
export PATH=$PATH:/home/danny/workspace/DB410C/Toolchain/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin

*此修改只需關掉Terminal在開啟後,就都會被設定



***
另外發現也可以直接去修改 /etc/enviroment  這檔案裡面包含原本PATH變數的資料, 要增加請在最後面用:加上你要加入的路徑即可, 例如:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/danny/workspace/DB410C/Toolchain/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin"









2016年5月11日 星期三

網路概論,OSI七層,以及各層封包的英文名稱

下圖是OSI七層的架構圖,TCP/IP則將七層簡化為五層,另外圖片最右邊則是各層相對應的應用


















其中每一階層都會對封包有個別的名稱,其對應稱謂如下所示
 - 應用層(Application Layer)        Message
 - 傳送層(Transport Layer)           Segment
 - 網路層(Network Layer)             Datagram
 - 鏈結層(Data Link Layer)           Frame

了解以上稱謂,我們就可以清楚的知道是在講哪一層的封包處理




Router實作了OSI底下三層,如下圖










而Switch實作OSI底下兩層,如下圖










2016年2月5日 星期五

在Linux上使用類似system("PAUSE")的方法

system("PAUSE");
上面的語法使用在windows上的功能,可以等待使用者按了任意Key再繼續動作

然而這段語法放在Linux上是沒有任何作用的,如果在Linux上想使用類似的功能請使用如下的語法,可以讓使用者按了Enter再繼續:

====================================================
#include <stdio.h>

#define PAUSE {printf("Press Enter key to continue..."); fgetc(stdin);}

int main()
{
    PAUSE
    return 0;
}
====================================================

以上紅字的部分,就是使用方法~

2016年2月4日 星期四

Opencv,Mat的研究:depth(), channels(), elemSize(), dims, step

今天稍為花了一點時間 研究了一下使用Mat讀進了一張圖之後以下這些參數與函式所代表的意義   ===> depth(), channels(), elemSize(), dims, step


假設我們現在使用了下面這行程式碼讀了一張  780x1040(寬x高),彩色的圖片
Mat img1 = imread(test.jpg, IMREAD_UNCHANGED);


img1.depth(): 

代表每個pixel的位元(bit)數,在opencv中的Mat.depth()中得到的是一個0~6的數字,分別代表不同的位數,enum{ CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6}; 0和1都代表8位, 2和3都代表16位, 4和5代表32位,6代表64位,test.jpg為CV_8U因此img1.depth()=0。

img1.channels(): 

代表每個pixel的通到個數,以test.jpg為例為彩色的RGB圖,因此                                                   img1.channels()=3。

img1.elemSize(): 

img1.elemSize() = 3 (每一個元素包含3個uchar值), img1.elemSize1() = 1 (elemSize/channels); 矩陣中每一個元素的數據大小,如果Mat中的數據類型是CV_8U,則elemSize=1,若是CV_8UC3則elemSize=3,若是CV_16UC2則eleSize=4。

img1.dims: 

這張圖片的維度,以這張圖為例,寬x高是二為陣列的資料,所以img1.dims=2。

img1.step: 

step這個部分有兩個值可以取,第一個是img1.step[0],另一個是img1.step[1]。 img1.step[0]代表一列所有的數據大小,而img1.step[1]代表一個pixel的數據大小,所以img1.step[0]=img1 .cols * img1 .elemSize() = ˙780*3 = 2340,img1.step[1]=3,另外如果看到(int)img1.step這樣的寫法,也就是取img1.step[0]的意思。



以上~

2016年1月8日 星期五

OpenCV3.0 + VS2012 配置設定,並在此環境上編譯Depth_Map(SSCA專案)

看到Depth Map有一篇改善的Paper有附上原始碼,因此拿來編譯作測試。此專案需要使用到openCV的Library。
Paper名為: Cross-Scale Cost Aggregation for Stereo Matching
Source Code Path: https://github.com/rookiepig/CrossScaleStereo (VS2010專案)

要編譯此專案,首先必須先安裝好win7端的openCV(Extract到資料夾)以及VS2012,openCV部分我選擇比較新版的OpenCV 3.0版本,安裝部分我就不再贅述。

openCV的下載網址: http://opencv.org/downloads.html



下面開始說明如何讓一個Visual Studio專案檔能夠使用到openCV的Library,並且順利編譯專案:

1.配置Win7端的openCV環境變數
    電腦 =>(按滑鼠右鍵) 選內容 => 進階系統設定 => 進階(標籤)選環境變數 => 變數名Path上點     兩下 => 最後在變數值欄位的最後面加上自己的openCV路徑
假設opencv3.0安裝在 D:\opencv_win\    請加入值 ";D:\opencv_win\opencv\build\x64\vc11\bin;D:\opencv_win\opencv\build\x86\vc11\bin",如下圖所示:


















**這裡路徑裡的vc11代表是Visual Studio 2012。
另外其他的對應如下: vc8 = Visual Studio 2005, vc9=Visual Studio 2008, vc10=Visual Studio 2010,  vc11=Visual Studio 2012, vc12=Visual Studio 2013



2. 接下來就請開啟VS2012專案,專案名稱會是XXX.sln請使用VS2012把他開啟,由於我的專案當初是用VS2010撰寫的,所以會先跳出一個提示視窗,請直接選擇update,VS2012會幫你轉成VS2012可用的。





3. 再專案上按滑鼠右鍵,選擇Properties,如下圖:





4. 接著會出現如下圖的視窗,把Configuration選為All Configurations,另外Platform暫時不作更改維持Win32即可,如下圖所示:





5. 選擇左邊的 Configuration Properties  => C/C++  => General     點選右邊Additional Include Directories右邊的小箭頭會出現Edit選項,請點選Edit。接著會出現一個小視窗,請在空白地方填入 openCV的Include表頭檔的路徑,請分別填入下面3個路徑:

D:\opencv_win\opencv\build\include
D:\opencv_win\opencv\build\include\opencv
D:\opencv_win\opencv\build\include\opencv2

如下圖所示:

  


6. 選擇左邊的 Linker => General   點選右邊Additional Library Directories右邊的小箭頭會出現Edit選項,請點選Edit。接著會出現一個小視窗,請在空白地方填入 openCV的lib函式庫的路徑,請填入下面路徑:

      32位元請填:  D:\opencv_win\opencv\build\x86\vc11\lib(此SSCA專案填這個值)

      64位元請填:  D:\opencv_win\opencv\build\x64\vc11\lib(如果專案須用到64位元的請填這個)

如下圖所示:

  



7. 選擇左邊的 Linker => Input   點選右邊Additional Dependencies 右邊的小箭頭會出現Edit選項,請點選Edit。接著會出現一個小視窗,請在空白地方填入 openCV的dll函式庫名稱,請填入:
opencv_ts300.lib
opencv_ts300d.lib
opencv_world300.lib
opencv_world300d.lib

如下圖所示:

  


基本上照上面的步驟作完,Project就可以正常的編譯過了!!


附註:
############################################################ 
如果你編譯的Project跟作者一樣是 SSCA這個Project的話,記得要去修改兩個檔案才可以順利編譯過關,分別是:
SSCA\CAST\StereoDisparity.h
SSCA\CommFunc.h


裡面的Code原本是引用openCV 2.4.6 請把它改成引用 openCV 3.0的,請改成如下:
// Opencv Lib 3.0
#pragma comment( lib, "opencv_ts300.lib" )
#pragma comment( lib, "opencv_ts300d.lib" )
#pragma comment( lib, "opencv_world300.lib" )

#pragma comment( lib, "opencv_world300d.lib" )

#####################################################################