2018年1月28日 星期日

dtc - Device Tree Compiler


從dtc manpage可以簡略瞭解一下DTC(Device Tree Compiler)功能, 就是將device-tree的format轉成另一種format, 其input格式有三種,
  1. dts - device tree source text
  2. dtb - device tree blob
  3. fs - /proc/device-tree style directory

而output格式也有三種,
  1. dts - device tree source text
  2. dtb - device tree blob
  3. asm - assembler source

而dtc支援的phandle可支援三種
  1. legacy - "linux,phandle" properties only
  2. epapr - "phandle" properties only
  3. both - Both "linux,phandle" and "phandle" properties

根據Device Tree Mysteries,
what is the reason for having a phandle? 
It is really just a hack to get around the fact that device tree does 
not have a pointer data type. 
It is a way to reference 
"that node over there that is related to this node for some reason". 
簡單來說, phandler就是pointer data type, 用個例子說明
pic@10000000 {
    phandle = < 1 >;
};

A phandle value of 1 is defined. 
Another device node could reference the pic node with a
phandle value of 1:

uart@20000000 {
    interrupt-parent = > 1 >;
};
"phandle = < 1 >"的"1"是一個隨意的unit32數值, 只要不衝突即可, 但是這並不是很好記, 所以DTC貼心的可以用lable來建立phandle,如下範例
PIC_3: pic@10000000 {
    interrupt-controller;
};

uart@20000000 {
    interrupt-parent = < &PIC_3 >;
};
這裡的"&"是告訴DTC後面接一個字串, 是個phandle參考到某個lable, 然後DTC就會幫user建立unit32的數值, 建立出phandle. 除此之外也可以使用full path來取代lable, 如下範例
/{
    soc {
        PIC_3: pic@10000000 {
            interrupt-controller;
        };
    };

    uart@20000000 {
        interrupt-parent = < &PIC_3 >;
    };

    uart@30000000 {
        interrupt-parent = < &{/soc/pic@10000000} >;
    };
};

下面再用一個例子同時說明DTC與phandle
brook@vista:~/dts$ cat test_phandle.dts
/dts-v1/;
/{
    soc {
        PIC_3: pic@10000000 {
           interrupt-controller;
        };
    };

    uart@20000000 {
        interrupt-parent = < &PIC_3 >;
    };

    uart@30000000 {
        interrupt-parent = < &{/soc/pic@10000000} >;
    };
};
brook@vista:~/dts$ dtc -O dtb -I dts test_phandle.dts > test_phandle.dtb
brook@vista:~/dts$ dtc -O dts -I dtb test_phandle.dtb
/dts-v1/;

/ {

        soc {

                pic@10000000 {
                        interrupt-controller;
                        linux,phandle = <0x1>;
                        phandle = <0x1>;
                };
        };

        uart@20000000 {
                interrupt-parent = <0x1>;
        };

        uart@30000000 {
                interrupt-parent = <0x1>;
        };
};

這篇文章主要簡單講解利用dtc來轉換dtb與dts, 順帶說明一下phandle是一種pointer data type, 與其基本原理



2018年1月7日 星期日

note for "The Art of Readable Code" - CH6


CH6, Making Comments Precise and Compact

Comments should have a high information-to-space ratio.當你準備寫註解時, 請盡可能的精簡, 因為註解會佔版面, 而且需要時間了解
// CategoryType -> (score, weight)
typedef hash_map<int, pair<float, float> > ScoreMap;
會比下面例子精簡
// The int is the CategoryType.
// The first float in the inner pair is the 'score',
// the second is the 'weight'.
typedef hash_map<int, pair<float, float> > ScoreMap;


// Return the number of lines in this file.
int CountLines(string filename) { ... }
這段註解不精確, 因為一行有很多種定義, 下面例子會相對精準
// Count how many newline bytes ('\n') are in the file.
int CountLines(string filename) { ... }


Use Input/Output Examples That Illustrate Corner Cases有時候用範例當註解可以更容易讓人理解,比如
// Rearrange 'v' so that elements < pivot come before those >= pivot;
// Then return the largest 'i' for which v[i] < pivot (or -1 if none are < pivot)
// Example: Partition([8 5 9 8 2], 8) might result in [5 2 | 8 9 8] and return 1
int Partition(vector<int>* v, int pivot);


"Named Function Parameter” Comments即在function參數上加上註解
Connect(/* timeout_ms = */ 10, /* use_encryption = */ false);



    參考資料:
  1. The Art of Readable Code





2018年1月1日 星期一

note for "The Art of Readable Code" - CH5


CH5, Knowing What to Comment

The purpose of commenting is to help the reader know as much as the writer did.千萬別為了註解而註解, 因為凌亂的畫面, 不會讓人對程式碼更清晰

無意義的註解範例
// The class definition for Account
    class Account {
      public:
        // Constructor
Account();
        // Set the profit member to a new value
        void SetProfit(double profit);
        // Return the profit from this Account
        double GetProfit();
    };


不要註解不好的名稱, 直接修正名稱
// Enforce limits on the Reply as stated in the Request,
// such as the number of items returned, or total byte size, etc. 
void CleanReply(Request request, Reply reply);
直接修改上述function name從CleanReply()改為EnforceLimitsFromRequest()會比註解一堆來得有意義,
// Make sure 'reply' meets the count/byte/etc. limits from the 'request' 
void EnforceLimitsFromRequest(Request request, Reply reply);

Recording Your Thoughts / directory commentary,註解重要的紀錄,比如以下幾個註解
// This heuristic might miss a few words. That's OK; solving this 100% is hard.
...
// This class is getting messy. Maybe we should create a 'ResourceNode' subclass to
// help organize things.
...


Comment the Flaws in Your Code,程式會不斷的被修改, 不要害怕記錄這些需要改進的地方, 以下是常用的標記
TODO:Stuff I haven’t gotten around to yet
FIXME:Known-broken code here
HACK:Admittedly inelegant solution to a problem
XXX:Danger! major problem here

// TODO: move this into sched_fork()
...
// FIXME: do we need to worry about rq being invalidated by the
...


Summary Comments,對一些code給予一些comment, 比如
# Find all the items that customers purchased for themselves.
    for customer_id in all_customers:
        for sale in all_sales[customer_id].sales:
            if sale.recipient == customer_id:
                ...

def GenerateUserReport():
    # Acquire a lock for this user
    ...

    # Read user's info from the database
    ...

    # Write info to a file
    ...

    # Release the lock for this user
    ...


    參考資料:
  1. The Art of Readable Code