2023年12月26日星期二

[shell script] 計算執行時間的一個example

 #!/bin/sh

start=$(date +%s)

#The thing you want to do
echo "testing the echo duration"
sleep 3

end=$(date +%s)
duration=$(( end - start ))
echo "The total excution time is ${duration} seconds."

最後會印出執行的秒數,如下圖:







Yocto 修改 recipe (bb檔),遇到 QA Issue,編譯失敗 (以NXP9098為例)

今天我想要新增幾個檔案,到root-filesystem當中

於是我在recipe (xxx.bb)的 do_install 裡面加了以下幾行 (綠色字體)

詳細說明:
我想把兩個檔案,regulatory.db 與 regulatory.db.p7s 放到 rootfs 裡面的 /llib/firmware/ 底下
於是我就增加三行

install -d ${D}/lib/firmware

install -m 0644 ${B}/regulatory.db ${D}/lib/firmware/regulatory.db
install -m 0644 ${B}/regulatory.db.p7s ${D}/lib/firmware/regulatory.db.p7s










然後進行編譯,結果出現以下的錯誤訊息(QA Issue)

ERROR: nxp9098-fw-1.0-r0 do_package: QA Issue: nxp9098-fw: Files/directories were installed but not shipped in any package: /lib/firmware/regulatory.db.p7s /lib/firmware/regulatory.dbPlease set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install. nxp9098-fw: 2 installed and not shipped files. [installed-vs-shipped]

如下圖:





這種錯誤是因為,你install了這些檔案,到root-filesystem,但是你沒把這些檔案一起包到他的package裡面造成的,所以解決方法是,在把這幾個檔案加到FILES_${PN},就可以順利編譯成功了!

因此你需要再加入這兩行到 FILES_${PN},如下圖:
















如果遇到的錯誤訊息為:
File 'xxx.bin' was already stripped, this will prevent future debugging! [already-stripped]
ERROR: xxx do_package: QA Issue: xxx: Files/directories were installed but not shipped in any package:

Solution:
加入下面這一行,可以解決
INSANE_SKIP_${PN} += "already-stripped"

2023年12月5日星期二

如何在chroot當中,reboot 或是 shutdown 你的裝置 (/proc/sysrq-trigger 的用法)

 今天有個需求,是必須在chroot當中,執行 power-off

想當然爾,第一個想到的是使用 shutdown now

於是馬上把shutdown 這個指令,移植到 chroot,執行後出現以下的訊息,但無法 poweroff

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
Failed to talk to init daemon

另外也試過,在chroot當中使用 kill -9 1 ,沒有出現錯誤訊息,但是一樣沒作用
(有在chroot當中kill某個 process,ex: kill -9 24, 是可以成功的)

google上面找到一個 /proc/sysrq-trigger 的方法,如下:

Step1:
先執行 echo 1 > /proc/sys/kernel/sysrq

Step2:
poweroff:
=>  echo "o" > /proc/sysrq-trigger

reboot:
=>  echo "b" > /proc/sysrq-trigger

更多用法可以參考
Ref: http://www.unixlinux.online/unixlinux/linuxjc/gylinux/201703/95680.html

# 立即重新啟動裝置
echo "b" > /proc/sysrq-trigger

# 立即關閉裝置
echo "o" > /proc/sysrq-trigger

# 導出內存分配的信息 (可以用/var/log/message 查看)
echo "m" > /proc/sysrq-trigger

# 導出當前CPU寄存器信息和標志位的信息
echo "p" > /proc/sysrq-trigger

# 導出線程狀態信息
echo "t" > /proc/sysrq-trigger

# 故意讓系統崩潰(kernel panic)
echo "c" > /proc/sysrq-trigger

# 立即重新掛載所有的文件系統
echo "s" > /proc/sysrq-trigger

# 立即重新掛載所有的文件系統為只讀
echo "u" > /proc/sysrq-trigger

Documentation for sysrq.c

Based on kernel version 2.6.38. Page generated on 2011-03-22 22:20 EST.

調整某個Daemon的 nice值(priority),從service 來調整 Linux Nice

當有個Daemon占據CPU太多的使用率時,我們可以透過調整nice值來降低其佔據CPU的使用率

今天我們以 mnld 這個daemon來當作範例,mnld是一個GNSS使用的Daemon

說明一下怎麼修改nice數值,也就是調整其優先順序

如下圖,我們可以在系統或是你的 Source Code 當中找到 mnld.service

然後我們可以修改如下圖,Nice值範圍為 -20 ~ 19 (高優先 ~ 低優先),default is 0









改完之後,下次重啟設備,我們可以使用指令,來觀察Nice值  =>  ps -fl -C "mnld"
command ref: 
https://www.thegeekstuff.com/2013/08/nice-renice-command-examples/







2023年11月29日星期三

編譯 Yocto SDK toochain 包含 Linux kernel 的 header 與 source (Build Yocto sdk include kernel header and source)

Step1:
我使用的
Yocto Project為2.6版,編譯SDK的指令如下: (以 MTK平台為例, xxxx 帶入自己的platform)
bitbake mtk-image-xxxx -c populate_sdk  


Step2:

用以上指令,編譯出來的Toolchain並不包含kernel header或是 kernel source,查詢網頁之後,得知需要再包含編譯這個Package “kernel-devsrc”


Step3:
接著我們在mtk-image-xxxx.bb 裡面,加上這個package,IMAGE_INSTALL_append += "kernel-devsrc"
Path: meta/meta-mediatek-mtxxxx/recipes-core/images/mtk-image-xxxx.bb
如下圖:





Step4:
接著編譯SDK,會遇到以下的錯誤訊息:

Fix kernel-devsrc package failing during install This issue is due to the upstream script hardcodes /bin/awk whereas we ship /usr/bin/awk. The installation check will break in this case. Fix it by changing the path in the script.

Step5:
從網路上,也看到有人在討論同樣的議題,有人提供patch方法,如下Link:

https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/11173/3/meta-agl-bsp/meta-ti/recipes-kernel/linux/linux-ti-staging_%2525.bbappend

於是我把這些修改加入meta/meta-mediatek-mtxxxx/recipes-kernel/linux/linux-mtk-extension_4.19.bbappend如下:





Step6:
接著繼續編譯SDK,結果出現以下的問題:
ERROR: mtk-image-xxxx-1.0-r0 do_populate_sdk: Could not invoke dnf. Command 
主要的錯誤訊息如下

Error:

 Problem: package target-sdk-provides-dummy-1.0-r0.sdk_provides_dummy_target conflicts with /bin/sh provided by busybox-1.29.3-r0.aarch64
- package kernel-devsrc-1.0-r0.autoxxxxevb_ivt_vp2 requires /usr/bin/awk, but none of the providers can be installed
- conflicting requests

Step7:
看了上面的錯誤訊息,其中一個錯誤是說,我們沒有安裝awk這個工具,因此我們試著安裝gawk. 我們接著到Yocto網站master branch底下,poky的路徑底下,搜尋awk

https://git.yoctoproject.org/poky/tree/?id=0a04692279f83637c0049cb1f91ac684f3fccf1f

於是可以看到如下的畫面,接著隨便點一個link,會到下面第二個頁面,我們可以從第二個頁面看到實際gawk的路徑為”meta/recipes-extended/gawk/”


















Step8:
接著就可以回到Yocto Tree的路徑,接著按照下圖步驟,可以找到gawk的reciepe. 

https://git.yoctoproject.org/poky/tree/meta?id=0a04692279f83637c0049cb1f91ac684f3fccf1f



















Step9:

我們選擇使用版本gawk-4.1.3,因為我們的Yocto為2.6版比較舊,選太新的recipe,有語法寫法不相同的問題(ex: gawk-5.x).於是分別把gawk_4.1.3.bb以及 gawk_4.1.3資料夾,放到我們的Yocto Project (這個網站不知道怎麼下載檔案,目前我是用複製內容,再vi gawk_4.1.3.bb 到Yocto Project當中)
path:meta/meta-mediatek-mtxxxx/recipes-extended/gawk_4.1.3.bb



Step10:

另外要記得,還要再從mtk-image-xxxx.bb那邊打開gawk,這樣才會編譯到gawk.去修改meta/meta-mediatek-mtxxxx/recipes-core/images/mtk-image-xxxx.bb






Step11:

再重新編譯一次,就可以成功編譯出包含kernel-devsrc的toolchain
*註:加入kernel-devsrc&gawk之後,整個 編譯後的 image增加了100MB

如何編譯Static library & 如何使用 (How to build a static library and share to others using)

這邊簡單寫一個example

====== printf.c ========

#include <stdio.h>
int print_hello()
{
    printf("This is a simple API example\n");
    return 0;

寫好這個API source code之後,先編譯出.o檔

gcc -c printf.c -o printf.o -I.


接著把.o檔,轉成.a檔

ar rcs printf.a printf.o


接著就可以寫一個主程式,去呼叫此API

如何使用此 Static Library,使用下面command編譯,可以產生test_main:

gcc main.c printf.a -o test_main -I.


也可以簡單寫一個 Makefile去做編譯(這邊解說Makefile 一小部分)
這邊是順帶的解說 Makefile語法,最主要還是要介紹,怎麼產生像是 printf.a 的 Static Library

###### Makefile 範例解說 #######

my_target: source_file.c header_file.h

gcc -o $@ $< -I.

$@: 表示目標,也就是 "my_target"

$<: 表示第一個依賴文件

2023年11月16日星期四

mpstat 的source code路徑,Yocto package名稱,與mpstat的用法

mpstat 與 top 指令,都是用來監控 CPU 使用率的工具
mpstat 是 Multiprocessor Statistics 的縮寫,它是 sysstat 這個套件裡面的一個工具

所以當我們要在Yocto裡面開啟這個工具,請記得是開啟 sysstat


如果要使用 mpstat這個工具,也可以用以下的 apt-get指令來安裝

apt-get install sysstat

sysstat 的opensource,我們可以從以下的網站來下載:
https://github.com/sysstat/sysstat


另外簡單介紹一下mpstat的使用方式

直接使用指令 mpstat:



使用指令 mpstat -P ALL 5 2:
參數所代表的意思為
    -P ALL: -P表示要監控哪個CPU,這邊帶入ALL,表示列出所有CPU的狀態
    5: 表示5秒印出一次
    2: 表示印2個回合



2023年11月15日星期三

Yocto Trace bb檔,了解其中參數,與debug的方法

假設在bb檔,或是 bbclass檔案裏面,有一些參數,我們會不知道實際的值
這時候,我們可以用 echo 印檔案的方式,導出到 deploy路徑底下的檔案,例如:

在某個bbclass檔案中,我們想知道, ${D} 與 ${STATE_DIR_FILE_PATH},這兩個參數的數值分別是什麼

此時,我們就可以在bbclass 檔案中加入下面兩行

echo ${D} > ${DEPLOY_DIR_IMAGE}/0001
echo ${STATE_DIR_FILE_PATH} > ${DEPLOY_DIR_IMAGE}/0002

最後我們編譯之後,再回到 Yocto Project 底下的這個路徑:
 build/tmp/deploy/images/你的platform名稱/

可以找到檔案 0001 與 0002
在使用 cat 把 0001 與 0002 的內容印出來,就可以知道參數的實際數值了!

2023年11月14日星期二

申請富邦快樂旅評卡,富邦旅遊不便險

 我之前就有申辦過富邦快樂旅平卡,所以每次要出國申辦旅遊不便險,就很方便
可以依據自己想要投保的金額來選擇,而且不只保自己的,還可以保家人的
以下來介紹一下保旅遊不便險的步驟


如果你沒申辦過快樂旅平卡,你必須先線上申請或臨櫃申請,如下圖:
線上申請網址,請到這個網址: 
https://www.fubon.com/insurance/b2c/content/prod_travel_compare/index.html 

點選下圖的,我要線上申辦 (不過還是需要列印填寫,並回傳資料)
需特別注意的是,雖然聲稱只需一個小時就可以辦妥旅平險,但申辦旅平卡,需要7個工作天







另外也可以依照富邦網站介紹的至臨櫃辦理,










當你有了富邦旅平卡之後,就可以開始申請旅平險
也是從這個網站的下圖,開始申請











Step1:
首先會需要填寫,你要保幾天的保險,計算方式說明如下:
*投保單位,以一天為單位

投保日期計算,舉個例子:
假設我的班機時間如下
2024/01/17 16:55 (台灣出發到日本)  ~    2024/01/23 9:00 (日本到台灣)

旅遊地區: 日本
因此可以投保 2024/1/17 16:00 ~ 2024/1/23 16:00  ,  共六天








Step2:
選擇大人投保金額,我是選擇100萬方案,詳細內容如下,可以接著點選套用到其他親屬:
















Step3:
小孩的投保方案,會自動被帶出最適合的,內容如下:














Step4:
2大2小,六天的總共保額,$912







Step5:
接著就下一步,可以選擇電子保單,或是紙本,然後可以直接線上信用卡付款
最後看到以下畫面就完成了!






2023年11月9日星期四

GPIO input high,遇到分壓的問題,基本電路,分壓的概念圖

 今天在做GPIO High/Low的測試,

我有個gpio input mode,我在電路板上面找一個1.8V電壓,外接一條電線
要用這個1.8V去讓GPIO偵測為 input high

硬體工程師說,最好在 GPIO PIN的前面,加入一個電阻,避免電流過大燒壞這個GPIO PIN

加入了之後,我用1.8V去碰觸這個 GPIO,從軟體端印出GPIO狀態,卻沒有被拉High

硬體工程師查了原因,可能因為是在1.8V的路上,有一個電阻
在GPIO PIN的前面,我們又加了一個電阻,造成分壓的情況,
導致電壓值沒有超過 GPIO PIN 所需要的上拉電壓值 (此數值需要看 GPIO Spec,這裡為1.3V)

分壓概念圖,大致如下:











另外分享一個分壓的計算網站,帶入你的每個電阻阻值,可以幫你算分壓

https://www.digikey.tw/zh/resources/conversion-calculators/conversion-calculator-voltage-divider










2023年11月5日星期日

解決 google blog 無法被搜尋的問題,關於sitemap

 之前一直從 google search console  要去解決無法被搜尋的問題

總是卡在 sitemap 的問題上,我在新增Sitemap 的部分,輸入我的blog 網址之後 ,點選提交,如下圖:





但審核總是有問題,大概的問題如下所示:







結果我發現,其實在新增Sitemap的時候,似乎要輸入 URL+"Sitemap.xml" 就可以成功,如下:
https://gigidandan.blogspot.com/sitemap.xml

後來我就可以看到,提交成功,還可以看到索引的網站個數:







我只能說,如果你們搜尋到我的這篇文章的話,就表示我這個修改方法成功了!

:D

Linux 更改 Mac Address 指令

 #先把ethernet0 停用
ifconfig eth0 down

#更改MAC Address
ifconfig eth0 hw ether AA:BB:CC:DD:EE:FF

#啟用ethernet0
ifconfig eth0 up


#最後在使用ifconfig 檢查
ifconfig

2023年10月25日星期三

GStreamer debug 的方式 - 第一次開機執行GStreamer command  會慢1~2秒

 這邊先記錄debug的方式

  我們可以在Linux作業系統底下,使用這個command

  =>  export GST_DEBUG="*:6"

實驗1:

我們使用gstreamer的debug mode發現幾件事情

1. 執行 get-lauch-1.0 之後,會在檔案系統中產生名為 “registry.aarch64.bin”的檔案

2. 這個cache檔案存放在 /home/root/.cache/gstreamer-1.0/

接著我們寫了簡單的script,會去執行這個command

=> /usr/bin/gst-launch-1.0 filesrc location=/etc/Track.awb ! decodebin ! audio convert ! audio resample ! audio/x-raw,rate=48000,channels=2,format=S16LE ! volume volume=2 ! alsasink device="hw:0,0"

接著我們計算有cache檔案的執行時間,去比較沒有cache檔案的執行時間

=> 有cache: 0.2 sec    沒有cache: 1 sec  (計算時間方式,使用teraterm的timestamp 去計算)







實驗2:

事先儲存好這個cache檔,重新更新這個device的韌體,刷新後把cache檔案放到 /home/root/.cache/gstreamer-1.0/

結果會跟實驗1當中,有cache的結果一樣,約執行0.2秒


2023年7月9日星期日

Sharp LC-40SF466T 電視,開不了機,綠燈恆亮,可以試試看這個方法

 今天電視突然無預警的沒有畫面,關閉電源再度開啟後,電視綠燈恆亮

 按電源按鈕開啟電視,都沒有反應,這台電視才使用4年,想說會不會是主機板的電源管理部分出了問題,於是上網找了一些資訊

  這台電視,只有一個主機板 + 邏輯版,主機板的部分,是三合一板 (),把電源板與主機板合在一起,然後找到下面方法,試了之後,還真的讓我的螢幕亮了起來

  接著按下電源按鈕之後,就可以讓電視回到紅燈狀態,資訊與步驟如下:


夏普液晶電視的很多機型主板有5次記憶保護,當背光或者電源發生故障時,只要開機5次以上,就形成保護記憶,解除方法步驟如下

Step1: 按住 信號源鍵(INPUT/AV/TV) 音量減鍵,同時拔掉電源插頭

Step2: 之前按住的鍵,到這步驟都不要放開,再度插上電源插頭


我完成以上兩個步驟後,電視就恢復正常了~ 不用花大錢了 :D

2023/11/09 更新最新狀況,後來還是遇到綠燈恆亮問題,上蝦皮買了一塊二手主機板 $1200
自行拆開更換後,正常服役中~

2023年7月3日星期一

[Linux Audio] 使用ALSA API 實作amixer command: amixer -c0 set i2s_clock on,Bug 修正

 之前有寫了一篇 ALSA API 實作amixer command:  amixer -c0 set i2s_clock on

 後來發現,有兩個 Bug 需要被修正,分別如下:

 1. 第一次如果使用 i2s_clock off,會造成 kernel 端出現 core_dump 錯誤,導致執行時間會變很長 (原本大概只需要 20ms,結果時間拉長到 200ms)

 2. 發現這個上層的API程式,呼叫Linux Kernel 層,去triger I2S,出現 non-blocking的現象(application 呼叫底層程式,但沒有等待底層做完,就直接繼續執行application層的事情)


因此加入底下一些程式,來解決這兩個問題 (用不同顏色標出)

#include <stdio.h>

#include <alsa/asoundlib.h>


int set_mixer_onoff(const char *control_name,
                            int option)
{
    const char *device = "hw:0";  // 音訊設備的名稱或識別符號
    //const char *control_name = "i2s_clock";  // 控制元素的名稱, 由API參數帶入

    snd_ctl_t *handle;
    snd_ctl_elem_id_t *elem_id;
    snd_ctl_elem_value_t *elem_value;
    int err;
    int ori_value;
    int i2s_is_set = 0;

    // 打開音訊設備的控制界面
    err = snd_ctl_open(&handle, device, 0);
    if (err < 0) {
        printf(":Cannot open device interface: %s\n", snd_strerror(err));  //無法打開音訊設備的控制界面
        return err;
    }


    // 分配並初始化 snd_ctl_elem_id_t 結構
    snd_ctl_elem_id_alloca(&elem_id);
    snd_ctl_elem_id_set_name(elem_id, control_name);


    // 獲取控制元素的索引
    snd_ctl_elem_id_set_interface(elem_id, SND_CTL_ELEM_IFACE_MIXER);

    // 獲取控制元素的數值
    snd_ctl_elem_value_alloca(&elem_value);
    snd_ctl_elem_value_set_id(elem_value, elem_id);
    snd_ctl_elem_value_set_boolean(elem_value, 0, option);  // 設置boolean值,由API參數option帶入

     

    // This is for fixing the core_dump issue
    // 先取得之前狀態,如果跟這次要設定的狀態相同,就不需要再做,直接 return.
    err = snd_ctl_elem_read(handle, elem_value);

    if (err < 0) {

            printf("Cannot read value: %s\n", snd_strerror(err));

            snd_ctl_close(handle);

            return err;

    }


    ori_value = snd_ctl_elem_value_get_boolean(elem_value, 0);

    if( option == ori_value )

    {

        printf("No need to Set, option equal to ori_value\n");

        snd_ctl_close(handle);

        return 0;

    }

    else

        snd_ctl_elem_value_set_boolean(elem_value, 0, option); //設定boolean值,由API參數option帶入

    /////////////////////////////////////////////


    // 設置控制元素的數值
    err = snd_ctl_elem_write(handle, elem_value);
    if (err < 0) {
        printf("Cannot set value: %s\n", snd_strerror(err));  //無法設置控制元素的數值
        snd_ctl_close(handle);
        return err;

    }

    // Poll the control value until it reaches the desired state

    // For fix the non-blocking issue

    while (!i2s_is_set) {

        // Sleep for a short period to avoid busy-waiting

        usleep(5000); // Sleep for 5 milliseconds


        // Read the control value

        err = snd_ctl_elem_read(handle, elem_value);

        if (err < 0) {

            printf("Cannot read value 2th: %s\n", snd_strerror(err));

            snd_ctl_close(handle);

            return err;

        }


        // Check if the control value is equal to the desired state

        int cur_value = snd_ctl_elem_value_get_boolean(elem_value, 0);

        if (cur_value == option) {

            i2s_is_set = 1;

        }

    }

    // 關閉音訊設備的控制界面
    snd_ctl_close(handle);
    printf("Setting %s %d success\n", control_name, option);  //已成功設置 i2s_clock 為 on
    return 0;

}


在Linux當中,應用程式,計算執行時間的範例程式

這個範例,計算單位為 microSecond(10-6)

#include <time.h>

 


clock_t start, end;

double cpu_time_used;

 

 

printf("** Start to measure time **\n");

start = clock();

...

...

...

end = clock();


cpu_time_used = ((double) (end - start))*1000000 / (CLOCKS_PER_SEC);

printf("** execution time:%f microseconds\n", cpu_time_used);

printf("** End of measure time **\n");


Linux kernel 4.19版 中,計算執行時間的方法,範例程式

首先需要 include 這個 header file 

#include <linux/time.h>


然後使用下面的方式,搭配 printk 在kernel 端印出計算時間,
這邊我們取 microseconds (10-6)

struct timeval start_time, end_time;

unsigned long elapsed_time;


 printk(KERN_ERR "#### measure time start %s ####\n", __func__);

do_gettimeofday(&start_time);   // Get the starting time

...

...

...

do_gettimeofday(&end_time);     // Get the ending time

 

// Calculate the executing time

elapsed_time = (end_time.tv_sec - start_time.tv_sec) * 1000000 +

                              (end_time.tv_usec - start_time.tv_usec);


printk(KERN_ERR "#### Elapsed time: %lu microseconds\n", elapsed_time);

printk(KERN_ERR "#### measure time end %s ####\n", __func__);



另外在 kernel 較新的版本當中,如果 do_gettimeofday() 無法使用,可以試試看下列方法

#include <linux/ktime.h>
#include <linux/types.h>

ktime_t start, end;
s64 elapsed_ns, 
elapsed_us;

start = ktime_get();

...
...
...

end = ktime_get();

elapsed_ns = ktime_to_ns(ktime_sub(end, start));
elapsed_us = ktime_to_us(elapsed_ns );

printk(KERN_ERR "#### Elapsed time: %lld microseconds\n", elapsed_us);


2023年6月6日星期二

Android 4.2.2 無法使用 YouTube的解決方法,使用 NewPipe Legacy

 在網路上查詢了很久,總算找到了一個解法
 並且讓我的舊平板電腦,也可以上 YouTube看影片

NewPipe 是一個 Open source,如果你的Android 是 4.2.2 (低於 Android 4.4)
可以到以下的網站,下載 NewPipe Legacy (0.20.8版)

https://f-droid.org/packages/org.schabi.newpipelegacy/#latest












If your device is Android 4.2.2 and cannot successfully use the YouTube, you can install the "NewPipe Legacy" APK.

The NewPipe Legacy is an open source. After I install into my Table computer, the YouTube can work now. You can use your Table computer and click the following link. Then download the version 0.20.8, this should be work. 

Best Regards!


[Linux Audio] 使用ALSA API 實作amixer command: amixer -c0 set i2s_clock on

當在我們的device端,可以使用命令 "amixer -c0 set i2s_clock on" 來開啟 i2s_clock
                                   也可以使用命令 "amixer -c0 set i2s_clock off" 來關閉 i2s_clock

這表示我們的device 底層,已經有建立 "i2s_clock" 這個kcontrol,因此我們使用amixer 命令,才可以順利的再取呼叫到kcontrol所定義好的 function,進而做到function裡面所實作好的行為

簡單的kcontrol,大概如下圖所示: (此範例為MTK mt6880 audio card)





*註 SOC_SINGLE_EXT 是Linux底下的巨集,想知道定義可以去kernel底下 include/sound/soc.h 查看

以上簡單描述一下kcontrol,接下來進入本文章的主題,如何使用ALSA API來實作一個API,讓別人呼叫此API,就達到跟 amixer command 一樣的行為,底下是一個簡單的實作範例


#include <stdio.h>

#include <alsa/asoundlib.h>


int set_mixer_onoff(const char *control_name,
                            int option)
{
    const char *device = "hw:0";  // 音訊設備的名稱或識別符號
    //const char *control_name = "i2s_clock";  // 控制元素的名稱, 由API參數帶入

    snd_ctl_t *handle;
    snd_ctl_elem_id_t *elem_id;
    snd_ctl_elem_value_t *elem_value;
    int err;

    // 打開音訊設備的控制界面
    err = snd_ctl_open(&handle, device, 0);
    if (err < 0) {
        printf(":Cannot open device interface: %s\n", snd_strerror(err));  //無法打開音訊設備的控制界面
        return err;
    }


    // 分配並初始化 snd_ctl_elem_id_t 結構
    snd_ctl_elem_id_alloca(&elem_id);
    snd_ctl_elem_id_set_name(elem_id, control_name);


    // 獲取控制元素的索引
    snd_ctl_elem_id_set_interface(elem_id, SND_CTL_ELEM_IFACE_MIXER);

    // 獲取控制元素的數值
    snd_ctl_elem_value_alloca(&elem_value);
    snd_ctl_elem_value_set_id(elem_value, elem_id);
    snd_ctl_elem_value_set_boolean(elem_value, 0, option);  // 設置boolean值為1,由API參數帶入


    // 設置控制元素的數值
    err = snd_ctl_elem_write(handle, elem_value);
    if (err < 0) {
        printf("Cannot set value: %s\n", snd_strerror(err));  //無法設置控制元素的數值
        snd_ctl_close(handle);
        return err;

    }


    // 關閉音訊設備的控制界面
    snd_ctl_close(handle);
    printf("Setting %s %d success\n", control_name, option);  //已成功設置 i2s_clock 為 on
    return 0;

}


最後,編譯成為Library之後,提供對方 library 以及 xxx.h 裡面有包含此API宣告
int set_mixer_onoff(const char *control_name, int option);

對方就可以使用了!



2023年5月9日星期二

Linux底下,一個控制CPU Loading的 Open Source tool,cpulimit (Tool使用方式)

 此篇直接介紹 cpulimit 該如何使用,讓我們做stress-test 可以直接指定想要的CPU Loading

先假設我們的設備為 雙核心(dual-core)的device

我們先撰寫一個loop的shell script,這個script可以把一個CPU使用率,占用到100%
====== loop_1.sh ======
#!/bin/sh

while [ 1 ]
do
    echo 5566 > /dev/null
done
====================

上面這個簡單的小程式,就可以占用100%的一個CPU使用率
所以如果是雙核心的device,很簡單,我們就再搞一個loop script

====== loop_2.sh ======
#!/bin/sh

while [ 1 ]
do
    echo 5566 > /dev/null
done
====================


接著我們再去撰寫一個主要的shell script,可以帶起 loop_1.sh 與 loop_2.sh
並且會去使用 cpulimit 去限制這兩個 loop程式的 cpu 使用率
進而達到我們想要維持的 CPU 使用率

====== cpuload.sh =======
#!/bin/sh

if [ "$#" -lt "1" ]; then
    echo "ex: ./cpuload.sh 40 (limit at 40%)"
    exit
fi

VAL=$1

killall loop_1.sh loop_2.sh

./loop_1.sh &
L1=`ps | grep loop_1.sh | awk -F ' ' '{print $1}'`     #get pid
./loop_2.sh &
L2=`ps | grep loop_2.sh | awk -F ' ' '{print $1}'`     #get pid

./cpulimit --limit=$VAL --pid=$L1 &
./cpulimit --limit=$VAL --pid=$L2 &

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

Linux底下,一個控制CPU Loading的 Open Source tool,cpulimit (Cross-compile)

 今天要跟大家介紹一個好用的工具,可以限制某一個Process只允許他使用多少的CPU Loading
 另外,如果要做壓力測試(stress test),只要稍微再搭配一些自己撰寫的shell script
 可以達到自行指定壓力測試所要的cpu loading

 先介紹這個open source,名為 "cpulimit",source code link如下:
 https://github.com/opsengine/cpulimit

 如果要在你的平台上,作壓力測試,請先自行做 Cross Compile,這邊先簡單教你如何編譯出你平台可以使用的tool

 我們可以看到此opensouce的目錄結構如下圖:

 










Step1:

在你下載好的source code,如上圖的路徑底下,先指定好你的CC環境變數
ex: 我要編譯電腦x86 用的tool,我的Toolchain就會是 /usr/bin/gcc,於是我用以下方式指定CC
=>   export CC=/usr/bin/gcc

Step2:

執行make,就可以成功編譯出我們要的工具,"cpulimit"
(如果要重新編譯,記得先make clean)







Step3:

編譯出來的執行程式,會在cpulimit-master/src/ 路徑底下,如下圖:




Step4:

執行cpulimit,可以看到使用方式,如下圖:
我們主要會用到 limit 與 pid 這兩個參數







下一篇文章,再來繼續介紹,怎麼加一些shell script,來做到壓力測試!

2023年5月5日星期五

[shell script] script如何做小數點運算,實際範例

 今天要記錄一個小數點運算的 shell script 範例

我們要把12去除以10,然後要得到值1.2,實際範例如下:


########## Floating point operation #############

#!/bin/sh

VAL=12
VAL=`echo | awk "{print $VAL/10}"`

echo "VAL=$VAL"


結果:




2023年3月5日星期日

永豐大戶綁定行動裝置

 永豐大戶的銀行APP, 目前需要重新綁定裝置

 目前有兩種方式可以來綁定

1. 直接APP內操作綁定: 
如果你的手機SIM卡,電話號碼與你當初申請的號碼是同一個,可以直接使用APP,按照APP建議的步驟來做APP與手機綁定

2. 透過永豐的網頁版,網路銀行來做裝置綁定:
如果你有兩個門號,A與B門號,當初申請永豐是用A門號,而你目前常用的手機是B門號,就需要用這個方式來綁定你B門號的手機
做這個動作,你必須要有電腦,讀卡機,以及永豐金融卡(白色那張),來做認證
步驟如下:
a. 到MMA金融交易網,登入網路銀行,網址如下:
https://mma.sinopac.com/MemberPortal/Member/NextWebLogin.aspx
b. 登入之後,選擇"申請/設定",管理我的行動裝置














c. 選擇新增裝置










d. 選擇晶片晶融卡驗證

















金融卡密碼驗證通過之後,會有個QR Code頁面,接著就使用手機掃描QR Code
手機部分會跳過去永豐APP
接著,就使用APP,選擇 更多->設定-> 裝置綁定,此時就會提醒你,有作過晶片金融卡認證,就可以綁定成功了

2023年1月29日星期日

[C Language] linux signal 範例程式

 下面介紹一個範例程式名為 "signal",編譯此程式之後,把此程式run在背景,可以使用下面幾個指令,來觸發此程式當中的 printf來印出相對應的訊息,當然你也可以把 printf 改成你想做的事情

 kill -SIGHUP `pidof signal`
 kill -SIGINT `pidof signal`
 kill -SIGQUIT `pidof signal`


======================= signal.c =================

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

void sigroutine(int sig_num) {
    switch(sig_num) {
        case 1:
                printf("Get a signal - SIGHUP \n");
        case 3:
                
printf("Get a signal - SIGQUIT \n");
        case 10:
                printf("Get a signal - SIGUSR1 \n");
    }
    return;
}

int main() {
    printf("process id is %d\n", getpid());
    signal(SIGHUP, 
sigroutine);
    signal(SIGQUIT, sigroutine);
    signal(SIGUSR1, sigroutine);
    for (;;) ;
}

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


另外列出,所有可以帶入 kill 後面的sigmal列表(Reference from google)
2 - 就是我們常見的鍵盤中斷 CTRL+c
9 - 就是我們常用來kill process的 signal



信號取值默認動作含義(發出信號的原因)
SIGHUP1Term終端的掛斷或進程死亡
SIGINT2Term來自鍵盤的中斷信號
SIGQUIT3Core來自鍵盤的離開信號
SIGILL4Core非法指令
SIGABRT6Core來自abort的異常信號
SIGFPE8Core浮點例外
SIGKILL9Term殺死
SIGSEGV11Core段非法錯誤(內存引用無效)
SIGPIPE13Term管道損壞:向一個沒有讀進程的管道寫數據
SIGALRM14Term來自alarm的計時器到時信號
SIGTERM15Term終止
SIGUSR110Term用戶自定義信號1
SIGUSR212Term用戶自定義信號2
SIGCHLD20,17,18Ign子進程停止或終止
SIGCONT19,18,25Cont如果停止,繼續執行
SIGSTOP17,19,23Stop非來自終端的停止信號
SIGTSTP18,20,24Stop來自終端的停止信號
SIGTTIN21,21,26Stop後台進程讀終端
SIGTTOU22,22,27Stop後台進程寫終端
SIGBUS10,7,10Core總線錯誤(內存訪問錯誤)
SIGPOLLTermPollable事件發生(Sys V),與SIGIO同義
SIGPROF27,27,29Term統計分佈圖用計時器到時
SIGSYS12,-,12Core非法系統調用(SVr4)
SIGTRAP5Core跟踪/斷點自陷
SIGURG16,23,21Ignsocket緊急信號(4.2BSD)
SIGVTALRM26,26,28Term虛擬計時器到時(4.2BSD)
SIGXCPU24,24,30Core超過CPU時限(4.2BSD)
SIGXFSZ25,25,31Core超過文件長度限制(4.2BSD)
SIGIOT6CoreIOT自陷,與SIGABRT同義
SIGEMT7,-,7Term
SIGSTKFLT-,16,-Term協處理器堆棧錯誤(不使用)
SIGIO23,29,22Term描述符上可以進行I/O操作
SIGCLD-,-,18Ign與SIGCHLD同義
SIGPWR29,30,19Term電力故障(System V)
SIGINFO29,-,-與SIGPWR同義
SIGLOST-,-,-Term文件鎖丟失
SIGWINCH28,28,20Ign窗口大小改變(4.3BSD, Sun)
SIGUNUSED-,31,-Term未使用信號(will be SIGSYS)


另外在Linux底下,輸入 kill -l 也可以看到這些SIGXXX 所定義的編號,如下:

$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX



使用 lsblk 印出 emmc 每個 partition的"名字"與"size"

使用以下的command可以印出 eMMC的 partition資訊 lsblk --bytes --output name,partlabel,size   參數說明 --bytes: partition的大小,以byte的方式輸出 --output: 後面可以指定要輸出的內容...