Yu-Hsien Hsu
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # **Job notebook** [toc] # 環境建置 網址: [Install Sublime Text on Ubuntu 20.04](https://linuxize.com/post/how-to-install-sublime-text-3-on-ubuntu-20-04/) [Trace code](http://kunhsien.blogspot.com/2015/02/linuxsublime-text3ctagssource-insight.html) [git 教學](https://zlargon.gitbooks.io/git-tutorial/content/) # share memory ## shmget() **用來得到一個shared memory id或建立一個shared memory object。 格式如下** ```c #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); ``` :::info **ex: shm_id=shmget(SHMKEY, MAXBUF+1, IPC_CREAT | 0666)** key: > IPC_PRIVATE:產生一個新的共享記憶體分段。 0表示建立新的shared memory object,>0表示根據shmflag的值操作。 size: > 需要共享記憶體的大小 , 因為分配大小皆以page為單位 , 所以如果size = 1~4096 , 則實際上會分配到4k。 0表示只取得share memory,>0則表示要指定的shared memory大小。 shmflag: > IPC_CREAT :確保開啟的記憶體是新的,而不是現存的記憶體。 | 0666 : 作為校驗 , ubuntu要加。 使用IPC_CREAT時,若沒有shared memory object則建立一個,若有則回傳shared memory id。 ::: **Hint:** :::spoiler rwx rwx rwx = 111 111 111 rw- rw- rw- = 110 110 110 rwx --- --- = 111 000 000 and so on... rwx = 111 in binary = 7 rw- = 110 in binary = 6 r-x = 101 in binary = 5 r-- = 100 in binary = 4 Where of course, ==r== stands for *read* and ==w== for *write* then ==x== means *execute*. | model | code |description | |--------|--------|--------| |S_IRWXU | 00700 | user (file owner) has read, write and execute permission | |S_IRUSR | 00400 |user has read permission| |S_IWUSR | 00200 |user has write permission| |S_IXUSR | 00100 |user has execute permission| |S_IRWXG | 00070 |group has read, write and execute permission| |S_IRGRP | 00040 |group has read permission| |S_IWGRP | 00020 |group has write permission| |S_IXGRP | 00010 |group has execute permission| |S_IRWXO | 00007 |others have read, write and execute permission| |S_IROTH | 00004 |others have read permission| |S_IWOTH | 00002 |others have write permission| |S_IXOTH | 00001 |others have execute permission| ::: ## shmat() **透過shmget()產生的shared memory id將shared memory object映射到memory,之後會回傳可直接存取的shared memory address。** ```c #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg); ``` :::info **ex: shm = shmat(shm_id, NULL, 0)** shmid: >共享記憶體的id shmaddr: > 指定shared memory要出現的位置,直接指定null可讓作業系統自己決定。 shmflg: > SHM_RDONLY:唯讀模式 0:可讀可寫 ::: ## shmdt() **將shared memory的address關閉,成功會傳回0** ```c #include <sys/shm.h> int shmdt(const void *shmaddr); ``` :::info **ex: shmdt(shm);** shmaddr: >shared memory的address ::: ## shmctl() **管理shared memory** ```c #include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf); ``` :::info **ex: shmctl(shmid, IPC_RMID, NULL);** shmid: > share memory id cmd: >IPC_STAT: 從共享記憶體裡,拿 shmid_ds 結構資料給 buf. IPC_SET: 從buf 複製到共享記憶體 IPC_RMID: 砍了共享記憶體 buf: > 暫存區. ::: ## For example ### <shm_server.c> ```c= #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <sys/stat.h> #define shm_size 32 #define PARM IPC_CREAT | 0666 int main(void) { char c; int shm_id; char *shm_addr, *s; key_t key; key = 5679; if ((shm_id = shmget(key, shm_size, PARM)) < 0) { perror("shmget"); return 0; } if ((shm_addr = shmat(shm_id, NULL, 0)) == (char *) -1) { perror("shmat"); return 1; } s = shm_addr; for (c = 'a'; c <= 'z'; c++) *s++ = c; *s = NULL; while (*shm_addr != '*'){ sleep(1); } shmdt(shm_addr); shmctl(shm_id , IPC_RMID , NULL); return 0; } ``` ### <shm_client.c> ```c= #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <sys/stat.h> #define shm_size 32 int main(void) { int shmid; key_t key; char *shm, *s; key = 5679; if ((shmid = shmget(key, shm_size , S_IRUSR | 0666)) < 0) { perror("shmget"); return 1; } if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) { perror("shmat"); return 1; } for (s = shm; *s != NULL; s++) putchar(*s); putchar('\n'); *shm = '*'; return 0; } ``` ```cpp= #include <iostream> #include <string> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> using namespace std; int main() { struct Data { int a; int arr[3]; }; int shm_id; key_t key = 1234; struct Data *p; shm_id = shmget(key, sizeof(struct Data), IPC_CREAT | 0666); p = (struct Data *) shmat(shm_id, NULL, 0); p->a = 27; p->arr[0] = 1; p->arr[1] = 2; p->arr[2] = 3; cout << p->a << endl; cout << p->arr[0] << endl; cout << p->arr[1] << endl; cout << p->arr[2] << endl; int pid = fork(); if(pid > 0) { sleep(1); } if(pid == 0) {//Notice that we didn't explicitly attach the shared memory to the child p->a = 32; p->arr[0] = 4; p->arr[1] = 5; p->arr[2] = 6; exit(0); } cout << p->a << endl; cout << p->arr[0] << endl; cout << p->arr[1] << endl; cout << p->arr[2] << endl; return 0; } ``` ## openlog() :::info |logopt Parameter| Description| |----------|----------| |LOG_PID|加上程序識別符號(系統分配給每個程序的一個獨一無二的數字標識)| |LOG_CONS|如果訊息無法記錄到日誌檔案裡則傳送訊息到控制檯| |LOG_NDELAY | 在第一次呼叫 syslog 函式時開啟日誌功能| ::: ## syslog() :::info LOG_EMERG——緊急情況 LOG_ALERT——應該被立即改正的問題,如系統數據庫破壞 LOG_CRIT——重要情況,如硬盤錯誤 LOG_ERR——錯誤 LOG_WARNING——警告信息 LOG_NOTICE——不是錯誤情況,但是可能需要處理 LOG_INFO——情報信息 LOG_DEBUG——包含情報的信息,通常旨在調試一個程序時使用 ::: ### For example ```c #include<stdio.h> #include<stdlib.h> #include <syslog.h> void main(void) { for(int i=0;i<3;i++){ syslog(LOG_USER|LOG_EMERG,"syslog programming test %d times/n", i); } } ``` ## write log example ```c #include #include int main(int argc,char* argv[]) { openlog(argv[0],LOG_CONS | LOG_PID, LOG_USER); int count=0; while(count<5){ syslog(LOG_INFO,"%d, log info test...",count); count++; } closelog(); return 0; } ``` ## memset() **作用是在一段記憶體塊中填充某個給定的值,它是對較大的結構體或數組進行清零操作的一種最快方法 。** :::info **void *memset(void *s, int ch, size_t n) 將s中當前位置後面的n個位元組 (typedef unsigned int size_t )用 ch 替換並返回 s 。** s: >這是來填充的內存塊的指針。 ch: > 這是要設置的值。作為一個int值傳遞,但使用這個值的無符號字符型轉換函數填充的內存塊。 n: >這是要設置的值的字節數。 ::: ### for example ```c #include <stdio.h> #include <string.h> int main () { char str[50]; strcpy(str,"This is string.h library function"); puts(str); memset(str,'$',7); puts(str); return(0); } /** result: This is string.h library function $$$$$$$ string.h library function **/ ``` ### 參考資料: [結構與指標](https://kopu.chat/2017/05/30/c-%E8%AA%9E%E8%A8%80%EF%BC%9A%E7%B5%90%E6%A7%8B%E8%AE%8A%E6%95%B8%E8%88%87%E6%8C%87%E6%A8%99/) [字串長度、複製、串接](https://openhome.cc/Gossip/CGossip/StringLengthCopyCat.html) # 指標 ::: info Function Pointer:指向函數的指標。 int (*pfunc)(int); Function return a pointer: 回傳指標的函數。 int* func(int); Function pointer return a pointer。 int (pfunc)(int); 括弧(*functionName)是很重要的部份,如果沒有括弧,編譯器會自動視為此函式回傳的只是一個指標而不是指標函式 ::: ```c // 函式宣告如下 void func1(int int1, char char1); /* 指向func1的指標如下: * 這樣的寫法應理解成:funcPtr1是一個函數指標,它指向的函數接受int與char兩個參數並回傳void。(signature) */ void (*funcPtr1)(int, char); /* 如果今天有另一個函式有相同的參考簽名 * 則funcPtr1也能指向func2。 */ void func2(int int2, char char2); // 函式指標指向函式1 funcPtr1 = &func1; // 函式指標指向函式2 funcPtr1 = &func2; // 在宣告時就直接給予初值,則如下: void (*funcPtr1)(int, char) = &func1; //&亦可省略 // example #include <stdio.h> int foo(int, int); int main (){ int (*add)(int, int) = foo; printf("add: %d",add(1, 2)); // 顯示 1 + 2 = 3 } int foo(int a, int b) { return a + b; } ``` ```c /****************** 結構中呼叫函式執行strcpy ***************************/ #include <stdio.h> #include <stdint.h> #include <string.h> typedef struct sConfig2ShdMem_s { void (* Set_Val)(uint8_t *value, uint32_t *u8InputShm); uint8_t *u8InputShm; } tConfig2ShdMem_t; void vfn_Config2Shm_String(uint8_t *value, uint32_t *u8InputShm) { strcpy(u8InputShm, value); } int main() { unsigned char src[] = "fewfefwefwefwef"; unsigned char abc[32]; tConfig2ShdMem_t tConfig2ShdMem[]= { {vfn_Config2Shm_String,abc}, }; tConfig2ShdMem[0].Set_Val(src, tConfig2ShdMem[0].u8InputShm); printf("abc:%s",abc); return 0; } ``` ```c #include<stdio.h> #define n 3 struct body { double p[3];//position double v[3];//velocity double a[3];//acceleration double radius; double mass; }; struct body bodies[n]; int main() { int a, b; for(a = 0; a < n; a++) { for(b = 0; b < 3; b++) { bodies[a].p[b] = 0; bodies[a].v[b] = 0; bodies[a].a[b] = 0; } bodies[a].mass = 0; bodies[a].radius = 1.0; printf("bodies[%d]:%f\n",a,bodies[a].radius); } return 0; } ``` > 函式的返回值是指標型別 int* fun(int a,int b); ```c #include <stdio.h> int* str(){ //申請堆空間 int *p=malloc(20*sizeof(int)); //列印地址 printf("addr p:%d\r\n",p); //資料儲存 for(int i=0;i<20;i++){ p[i]=i; } return p; } void main(){ //呼叫 int *p=str(); //地址 printf("addr p:%d\r\n",p); //資料輸出 for(int i=0;i<20;i++) { printf("%d",p[i]); } //釋放堆空間 free(p); } ``` >函式名表示的就是這個地址,既然是地址我們就可以定義一個指標變數來存放 int (*funp)(int,int) ```c #include <stdio.h> //找最大值 int max(int a,int b){ if(a>b) return a; return b; } //找最小值 int min(int a,int b){ if(a<b) return a; return b; } void main(){ //定義函式指標變數 pfun int (*pfun)(int,int); //賦值函式指標,找最大值 pfun=max;//或者為&max int c=pfun(10,20); printf("%d\r\n",c); //賦值函式指標,找最小值 pfun=min; //或者為&min c=pfun(10,20); printf("%d\r\n",c); } ``` ```c #include <stdio.h> //找最大值 int max(int a,int b){ if(a>b) return a; return b; } //找最小值 int min(int a,int b){ if(a<b) return a; return b; } //函式入口 int all(int a,int b,int (*pfun)(int,int)){ return pfun(a,b); } void main(){ int c=0; //找最大值呼叫 c=all(10,20,max); printf("%d\r\n",c); //找最小值呼叫 c=all(10,20,min); printf("%d\r\n",c); } ``` # OpenWrt OpenWrt項目是基於Linux作業系統的嵌入式設備作業系統。並不是試圖建立一個單一的,靜態的固件,而是提供了一個完全可寫的檔案系統與OpenWrt套裝軟體管理。這可以讓您從供應商提供的應用程式選擇和配寘中解脫出來,並允許您通過使用開發包來定制設備,以適應任何應用程式。對於開發人員來說,OpenWrt是一個用於構建應用程式的框架,並不需要在它周圍建立了一個完整的固件;這意味著用戶擁有完整的定制權限,用意想不到的方式來使用設備。 ## The UCI System * “uci”是Unified Configuration Interface“的縮寫, 此模組的目的是集中管理OpenWrt中, 各個模組的設定值(configuration).記錄系統的設定值, 應該是非常直覺且容易達到的工作. * 對於OpenWrt而言, 我們可以將UCI視為系統中主要使用者操作介面, 用來操作系統中最重要的設定項目. * 最常見的例子有: 主要網路設定(main network interface configuration), 無線網路設定(wireless settings), 系統日誌功能(logging) 和 遠端存取功能的設定(remote access configuration). **OpenWRT UCI API的使用** * OpenWrt中主要的設定值, 被切割成好幾個獨立的檔案(UCI設定檔), 存放在系統的 /etc/config/ 目錄之中. 大致上, 每一個設定檔會和它所屬的系統功能有關. 使用者可以透過文字編輯器(vim, notepad之類的)直接修改UCI設定檔的內容, 來達到修改設定值的目的, 或者透過 uci 這個指令來修改設定值. UCI設定檔也可以透過各種的API(例如shell, Lua 和 C)來修改, 例如Web GUI就可以透過 LuCI 來修改UCI設定檔. * 當UCI設定檔被修改, 不論使用者用什麼方式(透過文字編輯器修改或是透過uci指令)修改的, 其相關的service或是執行檔必須(重新)啟動, 方可讓修改過的設定值可以產生作用, (重新)啟動的方式是透過init.d call. ==root@OpenWrt:/# /etc/init.d/example restart== [https://openwrt.org/zh-tw/docs/guide-user/base-system/uci] **基本概念** * UCI上下文: struct uci_context * * 包(Package): 一個包對應一個UCI格式的文件.類型是 struct uci_package * * 節(Section): 一個配置文件的節點. 類型是 struct uci_list * * 值(Value):一個節下面可能包含多個值 一個值具有一個名字. :::info ``` package 'example' config 'example' 'test' # type:example section:test option 'string' 'some value' # name:string value:'some value' option 'boolean' '1' # name:boolean value:'1' list 'collection' 'first item' # name:collection collection[0]='first item' list 'collection' 'second item' # name:collection collection[1]='second item' ``` ![](https://yume190.github.io/image/openwrt/uci/1.png) ![](https://yume190.github.io/image/openwrt/uci/2.png) ::: ```c #include <unistd.h> #include <stdio.h> #include <string.h> #include <uci.h> static struct uci_context * ctx = NULL; //定義一個UCI上下文的靜態變量. /********************************************* * 載入配置文件,並遍曆Section. */ bool load_config() { struct uci_package * pkg = NULL; struct uci_element *e; ctx = uci_alloc_context(); // 申請一個UCI上下文. if (UCI_OK != uci_load(ctx, UCI_CONFIG_FILE, &pkg)) goto cleanup; //如果打開UCI文件失敗,則跳到末尾 清理 UCI 上下文. /*遍曆UCI的每一個節*/ uci_foreach_element(&pkg->sections, e) { struct uci_section *s = uci_to_section(e); // 將一個 element 轉換爲 section類型, 如果節點有名字,則 s->anonymous 爲 false. // 此時通過 s->e->name 來獲取. // 此時 您可以通過 uci_lookup_option()來獲取 當前節下的一個值. if (NULL != (value = uci_lookup_option_string(ctx, s, "ipaddr"))) { ip = strdup(value) //如果您想持有該變量值,一定要拷貝一份。當 pkg銷毀後value的內存會被釋放。 } // 如果您不確定是 string類型 可以先使用 uci_lookup_option() 函數得到Option 然後再判斷. // Option 的類型有 UCI_TYPE_STRING 和 UCI_TYPE_LIST 兩種. } uci_unload(ctx, pkg); // 釋放 pkg cleanup: uci_free_context(ctx); ctx = NULL; } ``` ## for example ```c /* 現在有一個如下的配置文件: config "server" "webserver" list "index" "index.html" list "index" "index.php" list "index" "default.html" */ /********************代碼片段***********************/ // s 爲 section. struct uci_option * o = uci_lookup_option(ctx, s, "index"); if ((NULL != o) && (UCI_TYPE_LIST == o->type)) //o存在 且 類型是 UCI_TYPE_LIST則可以繼續. { struct uci_element *e; uci_foreach_element(&o->v.list, e) { //這裏會循環遍曆 list // e->name 的值依次是 index.html, index.php, default.html } } /**********************寫配置**********************/ /* * UCI提供了一個簡潔的辦法來操作配置信息,例如有一個配置文件 * 文件名: testconfig * config 'servver' * option 'value' '123' # 我們想修改 'value' 的值爲 '456' */ struct uci_context * ctx = uci_alloc_context(); //申請上下文 struct uci_ptr ptr ={ .package = "config", .section = "servver", .option = "value", .value = "256", }; uci_set(_ctx,&ptr); //寫入配置 uci_commit(_ctx, &ptr.p, false); //提交保存更改 uci_unload(_ctx,ptr.p); //卸載包 uci_free_context(ctx); //釋放上下文 /* * uci_ptr 用來指定資訊.而是用uci_set則是寫入資訊.同類的函式有如下幾個: 針對list的操作: * uci_add_list() // 新增一個list 值 * uci_del_list() // 刪除一個list 值 * uci_delete() // 刪除一個option值 */ ``` ### 參考資料: [OpenWRT 筆記](https://yume190.github.io/2016/11/15/OpenWRT-2016-11-15-OpenWRT-Begin/) [OpenWRT uci](https://yume190.github.io/2016/11/24/OpenWRT-2016-11-24-OpenWRT-uci/) [OpenWRT 介紹以及應用情境](https://note-on-clouds.blogspot.com/search?q=OpenWRT) [OpenWRT: WiFi 網路的開放平台](https://openwrt-nctu.gitbook.io/project/) [Openwrt development am335x beginner](https://www.programmersought.com/article/77343556635/) [OpenWrt系統及新增自開發軟體](https://www.itread01.com/content/1545217025.html) # Overview to AM335x Boot Sequence :::info ROM Code主要有幾項任務: - Stack Setup - Watchdog timer 1 configuration (set to three minutes) - System clock configuration - Search bootable devices (must be the FAT 12/16/32 partition) for a valid booting image (the image name must be MLO) - Load the content of the file “MLO” from a bootable device to internal RAM (the 128KB on-chip memory) - Execute the file “MLO” stored in internal RAM ::: ![](https://lh3.googleusercontent.com/-6t7H14Lj3Bc/VT3n0BPjOaI/AAAAAAAAH9M/woI49MW-TC4/w1099-h752-no/am335x-boot-sequence.png) ### 參考資料: [Embedded Linux Boot Sequence](https://kernelmasters.org/blog/2020/06/30/embedded-linux-boot-sequence/) [AM335x ARM Cortex-A8 Boot Sequence](http://wiki.csie.ncku.edu.tw/embedded/rt-thread) [AM335x booting ](http://lirobo.blogspot.com/2014/06/am335x-booting.html) [AM335x U-Boot User's Guide](https://blog.csdn.net/yaked/article/details/41515793) [uboot 命令列操作簡介](http://pominglee.blogspot.com/2013/12/uboot.html) ## Setting the board ```htmlembedded Hardware setup: PC <-> USB_to_RS485(D+/D-) <-> board(D+/D-) board connect power supply(DC 12v) Software setup: environmant: ubuntu terminal: putty or minicom (baudrate:115200) first. open the terminal and listen comport before power-on second. terminal will show U-boot info like... --------------------------------------------------- U-boot SPL 2019.01 (Jan 30 2019 - 12:21:02 +0000) >>>am33xx_spl_board_init Enabling Spread Spectrum for DISP Trying to boot from NAND ... ... ... Hit any key to stop autoboot: 3 --------------------------------------------------- third. press 'Enter' when info show 'Hit any key to stop autoboot:' forth. step by step enter cmd => fatload mmc 0 0x80000000 MLO && nand erase 0x00000000 0x00080000 && nand write 0x80000000 0x00000000 0x00080000 ' response: 109596 bytes read in 9 ms (11.6 MiB/s) NAND erase: device 0 offset 0x0, size 0x80000 Erasing at 0x40000 -- 100% complete. OK NAND write: device 0 offset 0x0, size 0x80000 524288 bytes written: OK ' => fatload mmc 0 0x80000000 u-boot.img && nand erase 0x00280000 0x00100000 && nand write 0x80000000 0x00280000 0x00100000 ' response: 996940 bytes read in 66 ms (14.4 MiB/s) NAND erase: device 0 offset 0x280000, size 0x100000 Erasing at 0x340000 -- 100% complete. OK NAND write: device 0 offset 0x280000, size 0x100000 1048576 bytes written: OK ' => fatload mmc 0 0x80000000 image-am335x-evm.dtb && nand erase 0x00200000 0x00080000 && nand write 0x80000000 0x00200000 0x00080000 ' response: 39893 bytes read in 4 ms (9.5 MiB/s) NAND erase: device 0 offset 0x200000, size 0x80000 Erasing at 0x240000 -- 100% complete. OK NAND write: device 0 offset 0x200000, size 0x80000 524288 bytes written: OK ' => fatload mmc 0 0x80000000 openwrt-omap-am335x-evm-initramfs-kernel.bin && nand erase 0x00500000 0x01000000 && nand write 0x80000000 0x00500000 0x01000000 ' response: 14463136 bytes read in 936 ms (14.7 MiB/s) NAND erase: device 0 offset 0x500000, size 0x1000000 Erasing at 0x14c0000 -- 100% complete. OK NAND write: device 0 offset 0x500000, size 0x1000000 16777216 bytes written: OK ' fifth. turn the power 'off' and 'on' again Hint: Clear flash cmd : 'nand erase.chip' minicom: cannot open /dev/modem: No such file or directory : 'sudo ln -s /dev/ttyS0 /dev/modem' Error opening /dev/sdb: No medium found: 'sudo eject -t /dev/sdb' The board does not boot up(maybe error reason->Disk identifier: 0x00000000): first. Format sd card: *look for all available devices cmd : 'lsblk' *format device (Securely Wipe Up the Data): 'sudo dd if=/dev/zero of=/dev/sdb bs=4096 status=progress' *Format with FAT32: 'sudo parted /dev/sdb --script -- mklabel msdos' *Create a FAT32 partition that takes the whole space: 'sudo parted /dev/sdb --script -- mkpart primary fat32 1MiB 100%' *Format the boot partition to FAT32: 'sudo mkfs.vfat -F32 /dev/sdb1' second. Check the SD bootable partition: *Into SD : 'sudo fdisk /dev/sdb' *print disk partition: 'p' *partition type: 't' change to 'W95 FAT32 (LBA)' *set bootable flag: 'a' *write table to disk and exit: 'w' third. copy files to SD card ``` ### 參考資料: [如何在 Linux 上格式化 USB 驅動器和 SD 卡](https://linuxize.com/post/how-to-format-usb-sd-card-linux/) [C/C++ 中的 static, extern 的變數](https://medium.com/@alan81920/c-c-%E4%B8%AD%E7%9A%84-static-extern-%E7%9A%84%E8%AE%8A%E6%95%B8-9b42d000688f) # 更改ubuntu terminal be colorful `vim ~/.bashrc` 若找不到~/.bashrc `cp /etc/bash.bashrc ~/.bashrc` 於最後貼上 ``` if [ "$color_prompt" = yes ]; then PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' else PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' fi unset color_prompt force_color_prompt # Set color_prompt PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u\[\033[00m\]@\[\033[01;36m\]\h\[\033[00m\]:[\[\033[01;34m\]\w\[\033[00m\]]\$ ' # If this is an xterm set the title to user@host:dir case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" ;; *) ;; esac export LS_OPTIONS='--color=auto' eval "$(dircolors -b)" alias ls='ls $LS_OPTIONS' ``` 存檔後, `source ~/.bashrc` ## 只要打指令的前幾的字,或是 branch 名稱的前幾個字,就可以用 TAB 自動完成剩下的部分 只要打指令的前幾的字,或是 branch 名稱的前幾個字,就可以用 TAB 自動完成剩下的部分 > 若你所安裝的 git 預設已經有這個功能,則不需要安裝 如何安裝設定: 下載 git-completion.bash,存到 ~/.git-completion.sh 在 ~/.bash_profile 加上 [ -f ~/.git-completion.sh ] && . ~/.git-completion.sh 重開終端機 ```shell curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash > ~/.git-completion.sh $ echo "" >> ~/.bash_profile $ echo "# git completion" >> ~/.bash_profile $ echo "[ -f ~/.git-completion.sh ] && . ~/.git-completion.sh" >> ~/.bash_profile $ source ~/.bash_profile ``` # Server build codimd 安裝環境: Docker for windows git 下載指令 ```shell $ git clone https://github.com/codimd/container.git codimd-container $ cd codimd-container $ docker-compose up ``` 進入docker container ```dockerfile docker-compose exec codimd bash ``` 進入docker SQL(postgres) ```dockerfile 範例:docker exec -it my-postgres psql -U postgres docker exec -it 6c48b480500d psql -U codimd ``` SQL cmd:(for example) ```sql SELECT "email","password" FROM "Users" ; SELECT * FROM "Notes" ; SELECT "alias","id","shortid","title","ownerId" FROM "Notes"; SELECT "email","id" FROM "Users"; ``` :::info hint \l: List of databases \c: Connect to databases ex: \c codimd \dt: list tables docker內安裝vim: docker exec -u root -it e444ac9c514f bash -c "apt-get update&&apt-get install -y vim" ::: # TCP Server 概念補充:https://beej-zhtw-gitbook.netdpi.net/whatissocket/liang_zhong_internet_sockets struct addrinfo由getaddrinfo()返回,並在成功時包含針對指定主機名和/或服務的此類struct的鏈接列表(linklist)。 ai_addr成員實際上不是struct sockaddr,因為該struct只是一個通用類,其中包含所有其他成員的通用成員,並用於確定您實際擁有的結構類型。根據傳遞給getaddrinfo()的內容以及發現的功能的不同,ai_addr實際上可能是struct sockaddr_in或struct sockaddr_in6或其他的指針,具體取決於該特定地址條目的內容。 ```c struct addrinfo { int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc. int ai_family; // AF_INET, AF_INET6, AF_UNSPEC int ai_socktype; // SOCK_STREAM, SOCK_DGRAM int ai_protocol; // use 0 for "any" size_t ai_addrlen; // size of ai_addr in bytes struct sockaddr *ai_addr; // struct sockaddr_in or _in6 char *ai_canonname; // full canonical hostname struct addrinfo *ai_next; // linked list, next node }; struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address }; ``` ## Linked list of addrinfo’s struct addrinfo 一個有趣的方面是它也是linklist中的一個節點。 ai_next 字段存儲指向下一個 addrinfo 的指針,該地址存儲其他解析為域的 IP 地址。 最終,ai_next 引用了 NULL,它表示列表的結尾。 我們現在可以像這樣遍歷 addrinfo 的linklist: ```c struct addrinfo * cur_result, *results, hints; //... //Convert the hostname to an address if ((s = getaddrinfo(argv[1], NULL, &hints, &result)) != 0) { fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(s)); exit(1); } for (cur_result = result; cur_result != NULL; cur_result = cur_result->ai_next) { // do something with the current result } ``` ## IPv4 vs IPv6 要考慮的 addrinfo 結構的最後一個方面是 ai_family,它描述了已解析的地址類型。 這可以是 IPv4 (AF_INET) 或 IPv6 (AF_INET6)。 我們主要關注 IPv4,因此您可以將 ai_family 與 AF_INET 進行比較,以確保您只訪問正確 IP 地址的解析: ```c if (cur_result->ai_family == AF_INET) { /* ... */ } ``` ### 參考資料 [openssl](https://breezetemple.github.io/2019/04/09/ssl-programming/) [TCP Server](https://www.geeksforgeeks.org/tcp-server-client-implementation-in-c/) [C語言-struct、union、enum](http://gundambox.github.io/2015/10/30/C%E8%AA%9E%E8%A8%80-struct%E3%80%81union%E3%80%81enum/) https://www.cnblogs.com/yjf512/category/385367.html?page=2 https://www.cnblogs.com/skyfsm/p/7079458.html [Socket筆記](https://www.kshuang.xyz/doku.php/programming:c:socket) ### json_object_array_put_idx.c ```C #include <json/json.h> #include <stdio.h> /* http://linuxprograms.wordpress.com/2010/08/19/json_object_array_put_idx/ Input: NONE Output: { "Categories":[ null, null, "c", "c++", "php" ] } */ int main() { /*Creating a json object*/ json_object * jobj = json_object_new_object(); /*Creating a json array*/ json_object *jarray = json_object_new_array(); /*Creating json strings*/ json_object *jstring[3]; jstring[0] = json_object_new_string("c"); jstring[1] = json_object_new_string("c++"); jstring[2] = json_object_new_string("php"); /*Adding the above created json strings to the array*/ int i; for (i=0;i<3; i++) { json_object_array_put_idx(jarray,i+2, jstring[i]); } /*Form the json object*/ json_object_object_add(jobj,"Categories", jarray); /*Now printing the json object*/ printf ("%s\n", json_object_to_json_string(jobj)); } ``` ## enum to string (lookup table) ```c #include <stdio.h> typedef enum { north, south, east, west } E_directions; struct direction_datum { E_directions direction; char direction_name[6]; }; struct direction_datum direction_data[] = { {north, "north"}, {south, "south"}, {east, "east"}, {west, "west"}, }; #define ARRAY_LENGTH(A) sizeof(A) / sizeof(*A) char *Get_text_from_enum(int enum_value, void *array, unsigned int array_length, unsigned int size_of_array_entry) { unsigned int i; unsigned int offset; for (i = 0; i < array_length; i++) { offset = i * size_of_array_entry; if ((int) * ((int *) (array+ offset)) == enum_value) return (char *) (array + offset + sizeof(int)); } return NULL; } int main() { printf("Expect south, got %s\n", Get_text_from_enum(south, direction_data, ARRAY_LENGTH(direction_data), sizeof(direction_data[0]))); return 0; } ``` ```c #include <stdio.h> typedef enum { north, south, east, west } E_directions; typedef struct EnumName { int value; const char *name; } EnumName; const EnumName direction_data[] = { {north, "north"}, {south, "south"}, {east, "east" }, {west, "west" }, {0, NULL }, }; const char *Get_text_from_enum(int enum_value, const EnumName *names) //const char *Get_text_from_enum(E_directions enum_value, const EnumName *names) { while (names->value != enum_value && names->name != NULL) names++; return names->name; } int main(void) { printf("Expect south, got %s\n", Get_text_from_enum(south, direction_data)); } ```

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully