bit operation 實戰
最近看到一段話
"If you want to go fast, go alone. If you want to go far, go together."
想起周五和同事討論到, 但沒能好好解釋清楚,
決定今天好好地來說明紀錄一下.
首先先複習一下大學的幾個知識.
在這個筆記有詳細的說明: https://hackmd.io/@sysprog/ByzoiggIb?type=view
1. LSB / MSB
LSB : least significant bit : 最低有效位元
MSB : most significant bit : 最高有效位元
以 通訊常用的 IQ data 為例 : (Ref: Understanding Waveform Data)
或例如這段描述:
大概了解 LSB / MSB 定義就可以了解.
另外需要注意, 一般這邊 B 指的是 bit, 像 USB spec 也會用到 byte,
這時候 就會有兩種 LSB / LSb , 以大小寫做區分, 所以需要留意一開始 spec 的名詞定義.
2. little endian / big endian
( Ref: Jserv CS-APP 第二章 )
顧名思義, little endian 是把低的位元組放前面, 而 big endian 是把高的位元組放前面
可以發現下圖用的 LSB / MSB 指的是 byte 而非 bit.
所以原先範例:
所以硬體規格: LSB/MSB 要留意最低位元/最高位元和相對意義的對照.
1 byte (8 bit) register 讀出來的值, 就會是我們認為的值, 接下來須注意 endian 轉換.
另外也有用到 bit reverse 的時候:
reverse bit algorithm
uint16_t reverse_uint16(uint16_t n){
n = ((0xff00 & n) >> 8) | ((0x00ff & n) << 8);
n = ((0xf0f0 & n) >> 4) | ((0x0f0f & n) << 4);
n = ((0xcccc & n) >> 2) | ((0x3333 & n) << 2);
n = ((0xaaaa & n) >> 1) | ((0x5555 & n) << 1);
return n;
}
Linux kernel 定義是在 include/linux/bitrev.h
而有些平台, 像 ARM 也有指令集支援 : REV
而像一些 CRC 轉換, 就有可能會有用到這個 bit reversing
e.g. Linux kernel bluetooth hci 計算
而 Linux kernel endian 轉換, 就會用到像 be16_to_cpu() / cpu_to_be16()
這類 functions, 定義在 include/linux/byteorder/generic.h,
會看平台是 big endian 還是 little endian, 需要時會用 /include/uapi/linux/swab.h
做 swap 轉換.
==
所以在現實環境下, 這個就變得複雜,
例如在一個 wifi soc 的架構下, 我們如果讀到的值是錯的時該怎麼辦.
WIFI HW - MCU <- interface --> Host CPU
首先要先看 HW 硬體定義 和 MCU 平台的 endian 定義,
看 FW 將register 讀出來時是否正確,
接著看 FW 寫到 interface, 和 Host driver 從 interface 讀出來是否正確.
而通常 FW 和 host driver 間的資料傳輸內容, 也會有他相關的資料排列順序定義.
這地方也需要比對.
所以雖然在 IC 產業多年, 還是蠻佩服相關同事,
從軟體到硬體, 都需要有相當的細心和耐心, 相互配合, 才能做好.
所以雖然在 IC 產業多年, 還是蠻佩服相關同事,
從軟體到硬體, 都需要有相當的細心和耐心, 相互配合, 才能做好.
留言
張貼留言