嵌入式系統除錯Uboot串列埠互動除錯
1 硬體連線
我們需要一個USB轉串列埠線來除錯,有兩種規格如下:
規格1
規格2
其他轉換晶片如CH340,PL2303,FTP232也都是可以的,FTP232能夠支援的最大波特率會更高。
在板上可以看到如下一個介面:
我們使用串列埠2也就是UART2來做除錯口,將USB轉串列埠線的RX,TX,GND連線到板子上UART2的TX,RX,GND。
2 波特率配置
如果CONFIG_BAUDRATE不是115200,修改為115200,因為不是所有晶片都可以支援高波特率的(15000000):
修改後編譯U-Boot並燒錄。
3 除錯
首先我們建立一個串列埠連線:
協議選擇SERIAL:
注意:埠號對應我們USB轉串列埠的那個埠,波特率要115200;
點選“連線”:
最後給板子上電,可以看到串列埠的UBoot日誌輸出:
4 Driver Model(DM)模型
uboot引入了驅動模型(driver model),這種驅動模型為驅動的定義和訪問介面提供了統一的方法;提高了驅動之間的相容性以及訪問的標準型。
uboot的DM主要有四個組成部分:
udevice - 簡單就是指裝置物件,可以理解為kernel中的device。
driver - udevice的驅動,可以理解為kernel中的device_driver。和底層硬體裝置通訊,並且為裝置提供面向上層的介面。
uclass - 使用相同方式的操作集的device的組。相當於是一種抽象。uclass為那些使用相同介面的裝置提供了統一的介面。
uclass_driver - 對應uclass的驅動程式。主要提供uclass操作時,如繫結udevice時的一些操作。
呼叫關係如下:
DM的模型支援原始碼在:include/dm
幾個關鍵資料結構的說明:
- uclass id
在uclass-id.h中定義了相關的id,部分列舉如下:
比如我們串列埠用到uclass的ID就是UCLASS_SERIAL。
2. uclass
同一類裝置屬於同一個uclass,擁有相同的uclass ID。比如說RTC晶片,
市面上RTC晶片很多,由不同的廠家生產,其記憶體暫存器定義甚至訪問介面都不一樣,所以RTC的driver肯定是不一樣的,但是從功能的角度來說,他們都是用來記錄時間的,所他們都屬於rtc-class。 uclass從層級結構來講,起到非常好的承上啟下的作用,它既能遮蔽具體裝置個體間的差異性,向使用者提供統一的介面,又能為同一類的裝置定義統一的處理函式,具體的裝置驅動只需要實現這些處理函式即可,從而簡化的裝置驅動的開發。
我們可以在uclass.h中找到uclass的定義如下:
從裝置的角度來看,同一類的裝置(比如RTC)擁有相同的uclass ID,並全部掛在該uclass下;從驅動的角度來看,uclass driver實現通用的處理邏輯。
3. uclass_driver
同樣我們可以在uclass.h中找到struct uclass_driver的定義,這個結構體定義了一組我們訪問uclass的介面:
post_bind // 在udevice被繫結到該uclass之後呼叫
pre_unbind // 在udevice被解綁出該uclass之前呼叫
pre_probe // 在該uclass的一個udevice進行probe之前呼叫
post_probe // 在該uclass的一個udevice進行probe之後呼叫
pre_remove // 在該uclass的一個udevice進行remove之前呼叫
child_post_bind // 在該uclass一個udevice的一個子裝置被繫結到該udevice之後呼叫
child_pre_probe // 在該uclass的一個udevice的一個子裝置進行probe之前呼叫
init // 安裝該uclass的時候呼叫
destroy // 銷燬該uclass的時候呼叫
4. udevice
我們可以在device.h中找到定義:
const struct driver *driver; // 該udevice對應的driver
const char *name; // 裝置名
void *platdata; // 該udevice的平臺資料
void *parent_platdata; // 提供給父裝置使用的平臺資料
void *uclass_platdata; // 提供給所屬uclass使用的平臺資料
int of_offset; // 該udevice的dtb節點偏移,代表了dtb裡面的這個節點node
ulong driver_data; // 驅動資料
struct udevice *parent; // 父裝置
void *priv; // 私有資料的指標
struct uclass *uclass; // 所屬uclass
void *uclass_priv; // 提供給所屬uclass使用的私有資料指標
void *parent_priv; // 提供給其父裝置使用的私有資料指標
struct list_head uclass_node; // 用於連線到其所屬uclass的連結串列上
struct list_head child_head; // 連結串列頭,連線其子裝置
struct list_head sibling_node; // 用於連線到其父裝置的連結串列上
uint32_t flags; // 標識
5. driver
同樣我們可以在device.h中找到定義:
char *name; // 驅動名
enum uclass_id id; // 對應的uclass id
const struct udevice_id *of_match; //用於和device tree裡面的裝置節點匹配
(*bind) // 用於繫結目標裝置到該driver中
(*probe) // 用於probe目標裝置,啟用
(*remove) // 用於remove目標裝置。禁用
(*unbind) // 用於解綁目標裝置到該driver中
(*ofdata_to_platdata) // probe之前,解udevice的dts節點,轉化成udevice的資料
(*child_post_bind) // 如果目標裝置的一個子裝置被繫結之後,呼叫
(*child_pre_probe) // 在目標裝置的一個子裝置被probe之前,呼叫
(*child_post_remove) // 在目標裝置的一個子裝置被remove之後,呼叫
int priv_auto_alloc_size; //需要分配多少空間作為其udevice的私有資料
int platdata_auto_alloc_size; //需要分配多少空間作為其udevice的平臺資料
int per_child_auto_alloc_size; //每個子裝置需要多少私有資料
int per_child_platdata_auto_alloc_size; //每個子裝置需要多少平臺資料
const void *ops; // 操作集,提供給uclass用,格式具體由uclass決定
uint32_t flags; // 一些標誌位
5 串列埠驅動程式及DTS
5.1 驅動程式
U-Boot中的驅動程式目錄如下(drivers):
其中serial中存放的是串列埠相關的驅動原始碼。
其中ns16550.c為串列埠驅動程式,採用的是DM的框架,我們可以在原始碼中檢視到相關的定義:
這裡的U_BOOT_DRIVER其實是一個巨集定義,這段程式碼其實就是定義一個DM driver,見上節課DM中driver的結構。udevice最終會由一組API來訪問這個driver。
5.2 裝置樹
目錄在:arch/arm/dts中:
在rk3308-u-boot.dtsi中,可以看到一個stdout指向uart2,其實就是把串列埠2作為標準輸出:
需要注意的是,serial驅動在載入的時候需要依賴clk驅動,如果在這個時候clk驅動還沒有正常載入,需要在對應uart的dts節點中加入clock-frequency屬性,同樣在該dts檔案中可以找到uart2描述:
status可以是okay也可以是disable,表示使能和關閉。
最後我們在u-boot/configs/evb-rk3308_defconfig檔案中配置好相關串列埠做控制檯以及對應的波特率就可以了。
==================================================================================================================================
Uboot串列埠除錯就是這樣Easy!!
如果覺得對您有幫助並想進一步深入學習交流可以掃描以下微信二維碼或加入QQ群:928840648
歡迎共同學習成長,有一群愛學習的小夥伴一起勉勵!!一起加油!!也可點選
筆者基於嵌入式系統框架內容如下整理編輯:
相關文章
- win10 如何除錯串列埠_win10串列埠除錯怎麼除錯Win10除錯串列埠
- serial for mac 串列埠除錯工具Mac串列埠除錯
- linux串列埠命令列除錯Linux串列埠命令列除錯
- gdbserver連線Ubuntu除錯程式(使用串列埠)ServerUbuntu除錯串列埠
- 超好用的繪圖串列埠除錯助手繪圖串列埠除錯
- 【linux學習--工具篇】串列埠除錯工具Linux串列埠除錯
- BPI-M4 Berry在windows系統下連線串列埠除錯Windows串列埠除錯
- 沒有真實串列埠裝置時使用"虛擬串列埠驅動"除錯你的串列埠程式碼串列埠除錯
- 虛擬串列埠工具和串列埠除錯工具詳解 - 附下載地址串列埠除錯
- Xamarin.Forms-手機串列埠除錯程式開發文件ORM串列埠除錯
- serial for mac(串列埠除錯工具) v2.0.16啟用版Mac串列埠除錯
- 一款小而美的線上串列埠除錯工具串列埠除錯
- J-LINK RTT列印除錯,釋放串列埠資源除錯串列埠
- 除錯篇——除錯物件與除錯事件除錯物件事件
- 嵌入式Linux的除錯方案Linux除錯
- OpenHarmony系統使用gdb除錯init除錯
- Windows windbg kernel debug 雙機核心除錯 - USB3.0 除錯 USB除錯 除錯線Windows除錯
- 蘋果Mac電腦串列埠除錯工具:serial for mac 支援M1蘋果Mac串列埠除錯
- 虛擬串列埠工具MCGS開發除錯的靈活應用教程串列埠除錯
- TCP伺服器虛擬串列埠工具的MCGS開發除錯教程TCP伺服器串列埠除錯
- 嵌入式程式除錯與opencv影像庫除錯OpenCV
- CM3除錯系統簡析除錯
- vscode配置遠端linux系統除錯VSCodeLinux除錯
- windows系統vscode遠端除錯MySQLWindowsVSCode除錯MySql
- IsDebuggerPresent的反除錯與反反除錯除錯
- Python 程式碼除錯—使用 pdb 除錯Python除錯
- Xcode動態除錯原理XCode除錯
- nginx 錯誤除錯Nginx除錯
- 除錯toybox除錯
- Linux除錯Linux除錯
- postman除錯Postman除錯
- gdb除錯除錯
- 前端除錯前端除錯
- python 除錯Python除錯
- LLDB除錯LLDB除錯
- Apk_動態除錯方案APK除錯
- phpstorm進行動態除錯PHPORM除錯
- 移動端網頁除錯網頁除錯