Hubris是一個微控制器操作環境,專為具有可靠性要求的深層系統設計。它的設計最初是在RFD41中提出的,但從那時起就已經大量發展。
開發人員文檔位於doc/
目錄中的Asciidoc。它通過github頁面渲染,可在https://oxidecomputer.github.io/hubris上找到。
存儲庫的佈局如下。
app/
是用於應用程序的頂級二進制板條箱現場的位置,例如, app/gimlet
包含用於gimlet的固件板條箱。一般來說,如果您想為某事構建圖像,請在這裡查看。
build/
包含構建系統和支撐板條。
chip/
包含外圍定義和調試單個微控制器的支持文件。
doc/
包含開發人員文檔。
drv/
包含驅動程序,簡單的驅動器Lib板條板和成熟的服務器箱板條箱的混合物。當前的慣例是, drv/SYSTEM-DEVICE
是SYSTEM
上DEVICE
的驅動程序(通常SYSTEM
SOC名稱),而drv/SYSTEM-DEVICE-server
是服務器bin板條箱。
idl/
包含偶像中編寫的接口定義
lib/
包含我們編寫的各種公用事業庫。如果您需要製作不適合其他目錄之一的可重複使用的板條箱,則可能屬於此處。
stage0/
是Bootloader/ FelsOvisor,主要用於LPC55。
support/
包含一些接口和編程支持文件,例如假證書和程序員固件圖像。
sys/
包含Hubris的“系統”位,即內核( sys/kern
),定義ABI( sys/abi
)的共享板條以及任務( sys/userlib
)使用的用戶庫。
task/
包含可重複使用的任務,這些任務不是驅動程序。在任務與drv/something-server
中生活在task
中的事物之間的區別是模糊的。使用您的判斷。
test/
包含測試框架和用於為各種板構建其的二元板條箱。
website/
包含Hubris網站的源代碼
目前,我們支持Linux和Windows作為第一層平台。 MACOS也每天都由氧化物員工使用,但未在CI中進行測試。該構建可能也適用於Illumos。如果有人想加緊維持支持和對Illumos或Macos的持續建立,我們會很喜歡幫助。
要提交更改以進行審查,請將它們推到叉子中的分支機構,並提交拉動請求將該分支合併master
。有關詳細信息,請參見CONTRIBUTING.md
。
您將需要:
基於rustup
的工具鏈安裝。當您第一次嘗試構建時, rustup
將自動安裝我們的固定工具鏈版本以及交叉補償目標。
openocd
(理想情況下是0.11)或(如果使用LPC55) pyocd
(0.27或更高版本)。請注意,OpenOCD的0.10釋放早於STLINK V3。人們正在使用系統軟件包經理提供的各種後0.10,Pre-0.11的構建,但如果您的系統尚未包裝0.11,請纏繞它們。如果您要在MacOS上使用Homebrew安裝OpenOCD,則需要使用brew install --head openocd
來構建主分支的尖端,而不是使用最新的二進製版本。如果需要從源構建,則可以在此處找到OpenOCD V0.11.0。運行./configure
時,請確保您看到啟用了ST-Link Programmer
(應該是默認值)。
libusb,通常從系統的軟件包管理器中找到, libusb-1.0.0
或類似。
libfdti1,被發現為libftdi1-dev
或類似。
如果您要運行GDB,則應安裝arm-none-eabi-gdb
。這通常來自系統的軟件包管理器,其包裝名稱如arm-none-eabi-gdb
或gdb-multiarch
。 MACOS用戶可以運行brew install --cask gcc-arm-embedded
安裝官方的ARM二進製文件。
傲慢的調試器,謙卑。請注意, cargo install
與此存儲庫根中存在的rust-toolchain.toml
文件奇怪地相互作用;如果您運行以下命令逐字安裝謙卑,請從其他目錄中進行操作:
cargo install --git https://github.com/oxidecomputer/humility.git --locked humility
cargo-readme
作為一種依賴性: cargo install cargo-readme
安裝OpenOCD有三種替代方法:
請參閱此處獲取openocd
的來源或獲得非正式的二進製文件。
另外,您可以使用巧克力安裝:
> choco install openocd
最後,您可以使用SCOOP安裝openocd
:
> scoop bucket add extras
> scoop install openocd
注意:通過scoop
安裝的openocd
已證明對某些用戶有問題。如果您遇到問題,請嘗試通過choco
或來自來源安裝(請參見上文)。
要使用ST-Link程序員,您可能需要安裝此驅動程序。
沒有必要建立和運行傲慢,但是如果您想通過串行鏈接進行通信(並且終端不支持),則需要使用Putty;本指南很好地解釋瞭如何。
我們不使用cargo build
或直接cargo run
,因為它們對於我們的目的太僵化了。我們有一個複雜的多構造構建,這遠遠超出了它們。
取而代之的是,存儲庫包括一個名為xtask
的貨物擴展名,該貨物命名我們的自定義構建命令。
cargo xtask dist TOMLFILE
構建了TOML文件描述的應用程序的分發圖像。
cargo xtask dist app/demo-stm32f4-discovery/app.toml
-stm32f4-discoverycargo xtask dist app/demo-stm32f4-discovery/app-f3.toml
-stm32f3-discoverycargo xtask dist app/lpc55xpresso/app.toml
-LPCXPRESSO55S69cargo xtask dist app/demo-stm32g0-nucleo/app-g031.toml
-STM32G031-NUCLEOcargo xtask dist app/demo-stm32g0-nucleo/app-g070.toml
-STM32G070-NUCLEOcargo xtask dist app/demo-stm32h7-nucleo/app-h743.toml
-NUCLEO-IH743ZI2cargo xtask dist app/demo-stm32h7-nucleo/app-h753.toml
-NUCLEO-IH753ZIcargo xtask dist app/gemini-bu/app.toml
-Gemini trup板因為完整的圖像構建可能需要10秒或更長時間,具體取決於您更改的內容,當您在任務或內核上迭代時,您可能需要單獨構建它。這就是cargo xtask build
的目的。
例如,要構建task-ping
,因為它將在其中一個圖像中構建,但沒有構建演示的其餘部分,請運行:
$ cargo xtask build app/gimletlet/app.toml ping
clippy
在特定圖像的上下文中,可以使用cargo xtask clippy
子命令來針對一個或多個任務運行clippy
:
$ cargo xtask clippy app/gimletlet/app.toml ping pong
rust-analyzer
集成傲慢的構建系統將無法與rust-analyzer
配合使用。
但是, cargo xtask lsp
在這裡可以提供幫助:它以其參數為生鏽文件,並返回JSON編碼的配置,以設置rust-analyzer
。
要使用此數據,需要一些編輯器配置!
(我們尚未製作插件,但這肯定是可能的)
使用Neovim和rust-tools
,這是一個示例配置:
-- monkeypatch rust-tools to correctly detect our custom rust-analyzer
require ' rust-tools.utils.utils ' . is_ra_server = function ( client )
local name = client . name
local target = " rust_analyzer "
return string.sub ( client . name , 1 , string.len ( target )) == target
or client . name == " rust_analyzer-standalone "
end
-- Configure LSP through rust-tools.nvim plugin, with lots of bonus
-- content for Hubris compatibility
local cache = {}
local clients = {}
require ' rust-tools ' . setup {
tools = { -- rust-tools options
autoSetHints = true ,
inlay_hints = {
show_parameter_hints = false ,
parameter_hints_prefix = " " ,
other_hints_prefix = " " ,
-- do other configuration here as desired
},
},
server = {
on_new_config = function ( new_config , new_root_dir )
local bufnr = vim . api . nvim_get_current_buf ()
local bufname = vim . api . nvim_buf_get_name ( bufnr )
local dir = new_config . root_dir ()
if string.find ( dir , " hubris " ) then
-- Run `xtask lsp` for the target file, which gives us a JSON
-- dictionary with bonus configuration.
local prev_cwd = vim . fn . getcwd ()
vim . cmd ( " cd " .. dir )
local cmd = dir .. " /target/debug/xtask lsp "
-- Notify `xtask lsp` of existing clients in the CLI invocation,
-- so it can check against them first (which would mean a faster
-- attach)
for _ , v in pairs ( clients ) do
local c = vim . fn . escape ( vim . json . encode ( v ), ' " ' )
cmd = cmd .. ' -c" ' .. c .. ' " '
end
local handle = io.popen ( cmd .. bufname )
handle : flush ()
local result = handle : read ( " *a " )
handle : close ()
vim . cmd ( " cd " .. prev_cwd )
-- If `xtask` doesn't know about `lsp`, then it will print an error to
-- stderr and return nothing on stdout.
if result == " " then
vim . notify ( " recompile `xtask` for `lsp` support " , vim . log . levels . WARN )
end
-- If the given file should be handled with special care, then
-- we give the rust-analyzer client a custom name (to prevent
-- multiple buffers from attaching to it), then cache the JSON in
-- a local variable for use in `on_attach`
local json = vim . json . decode ( result )
if json [ " Ok " ] ~= nil then
new_config . name = " rust_analyzer_ " .. json . Ok . hash
cache [ bufnr ] = json
table.insert ( clients , { toml = json . Ok . app , task = json . Ok . task })
else
-- TODO:
-- vim.notify(vim.inspect(json.Err), vim.log.levels.ERROR)
end
end
end ,
on_attach = function ( client , bufnr )
local json = cache [ bufnr ]
if json ~= nil then
local config = vim . deepcopy ( client . config )
local ra = config . settings [ " rust-analyzer " ]
-- Do rust-analyzer builds in a separate folder to avoid blocking
-- the main build with a file lock.
table.insert ( json . Ok . buildOverrideCommand , " --target-dir " )
table.insert ( json . Ok . buildOverrideCommand , " target/rust-analyzer " )
ra . cargo = {
extraEnv = json . Ok . extraEnv ,
features = json . Ok . features ,
noDefaultFeatures = true ,
target = json . Ok . target ,
buildScripts = {
overrideCommand = json . Ok . buildOverrideCommand ,
},
}
ra . check = {
overrideCommand = json . Ok . buildOverrideCommand ,
}
config . lspinfo = function ()
return { " Hubris app: " .. json . Ok . app ,
" Hubris task: " .. json . Ok . task }
end
client . config = config
end
end ,
settings = {
[ " rust-analyzer " ] = {
-- enable clippy on save
checkOnSave = {
command = " clippy " ,
extraArgs = { ' --target-dir ' , ' target/rust-analyzer ' },
},
diagnostics = {
disabled = { " inactive-code " },
},
}
}
},
}
end
創建新的LSP配置( on_new_config
)時,我們在目標文件上運行cargo xtask lsp
。 JSON配置包括配置的哈希;我們使用該哈希修改客戶端的名稱,從rust_analyzer
到rust_analyzer_$HASH
。這樣可以防止Neovim嘗試重複使用現有客戶端,該客戶端通常由客戶端名稱和工作區根目錄重複編輯;在傲慢中,我們希望多個客戶端與相同的工作區根共存,因此他們需要不同的名稱。然後,我們將其餘配置的其餘部分存放在本地變量( cache
)中,並將該客戶端的存在記錄在clients
中。
連接到LSP時,我們嘗試將配置從cache
中拉出。如果存在一個,那麼我們知道我們正在處理傲慢的緩衝區。複製配置的相關部分。
請注意,這不會為您編譯xtask
;它假設它已經存在於target/debug/xtask
中。如果您定期使用傲慢,這應該是正確的,並且打開新文件時會節省大量時間。
為了創建自己的任務,最簡單的方法是:
task/template
複製到新名稱。Cargo.toml
。Cargo.toml
中的工作空間成員列表中。app.toml
文件將其添加到系統映像中。cargo xtask build
以對其進行編譯。一個典型的app.toml
條目,用於使用不使用內存映射外圍設備的小任務
[ tasks . name_for_task_in_this_image ]
name = " my-task-target-name "
priority = 1
requires = { flash = 1024 , ram = 1024 }
start = true
可以生成圖表,以顯示各種任務及其優先級的關係。結果文件以GraphViz的dot
格式為單位。 Dot
源可以包含在Asciidoctor源中,也可以呈現為各種格式。
要在Ubuntu上創建並查看gimletlet
的SVG圖,請確保安裝graphviz
軟件包。然後生成圖:
$ cargo xtask graph -o gimletlet.dot app/gimletlet/app.toml
$ dot -Tsvg gimletlet.dot > gimletlet.svg
$ xdg-open gimletlet.svg
bash命令生成所有圖形:
APPS=( $(find app -name '*.toml' ! -name Cargo.toml) )
for app in "${APPS[@]}"
do
out=$(basename ${app////_} .toml).dot
svg=$(basename $out .dot).svg
cargo xtask graph -o $out $app
dot -Tsvg $out > $svg
done
first="${APPS[0]}"
out="$(basename ${first////_} .toml).dot"
svg="$(basename $out .dot).svg"
xdg-open "${svg}"
如果eog
是默認查看器,則在目錄中打開第一個SVG,將允許使用同一窗口循環瀏覽所有可用圖形。
傲慢與其調試器謙卑緊密結合,該謙卑用於下面的命令(在cargo xtask flash
中)或明確(以cargo xtask humility
)。
如果您的$PATH
上沒有humility
二進制,則可以使用HUBRIS_HUMILITY_PATH
環境變量來提供二進制的路徑。
可以通過運行cargo xtask flash
並指定適當的TOML文件,將傲慢存檔中的圖像直接閃爍到目標板上。這將運行cargo xtask dist
,然後將所得的構建存檔傳遞給humility flash
。 humility
會調用openocd或pyoCD閃爍圖像。確切的調用取決於板,並在構建檔案中編碼。
cargo xtask flash app/lpc55xpresso/app.toml
cargo xtask flash app/demo-stm32f4-discovery/app.toml
cargo xtask flash app/demo-stm32h7-nucleo/app-h743.toml
cargo xtask flash app/demo-stm32h7-nucleo/app-h753.toml
cargo xtask flash app/gemini-bu/app.toml
謙卑是通過在直接連接的板上指定檔案的原位運行的,或者通過指定轉儲來實現屍體。為了方便開發,謙卑也可以通過指定適當的TOML來原位運行,例如,在具有STM32F4發現板的機器上直接附加了謙卑:
$ cargo xtask humility app/demo-stm32f4-discovery/app.toml -- tasks
Finished dev [optimized + debuginfo] target(s) in 0.17s
Running `target/debug/xtask humility demo/app.toml -- tasks`
humility: attached via ST-Link
ID ADDR TASK GEN STATE
0 20000108 jefe 0 Healthy(InRecv(None))
1 20000178 rcc_driver 0 Healthy(InRecv(None))
2 200001e8 usart_driver 0 Healthy(InRecv(None))
3 20000258 user_leds 0 Healthy(Runnable) <-
4 200002c8 ping 48 Healthy(Runnable)
5 20000338 pong 0 Healthy(InRecv(None))
6 200003a8 idle 0 Healthy(Runnable)
humility
包括一個gdb
命令,該子命令使用arm-none-eabi-gdb
連接到運行系統,可選地基於構建存檔中的配置數據運行自己的openocd
實例。
為了方便起見,還有一個cargo xtask gdb
立面,該立humility
稱其為適當的構建檔案:
$ cargo xtask gdb app/demo-stm32f4-discovery/app.toml -- --run-openocd
# ... lots of output elided ...
task_idle::main () at task/idle/src/main.rs:14
14 loop {
Breakpoint 1 at 0x800434c: file /crates.io/cortex-m-rt-0.6.15/src/lib.rs, line 560.
Note: automatically using hardware breakpoints for read-only addresses.
semihosting is enabled
semihosting is enabled
(gdb)
請注意, cargo xtask gdb
(默認情況下)也將運行dist
和flash
,以確保芯片上的圖像是最新的。 -n
/ --noflash
選項跳過了這些步驟。
對傲慢內核進行了專用測試圖像測試,其中包括測試跑步者,助手和測試套件。測試圖像通過ITM排放結果。雖然可以手動解釋這些結果,但humility test
可以自動化這一點。 humility test
本身最容易通過cargo xtask test
運行,該測試與cargo xtask dist
, cargo xtask flash
和cargo xtask humility test
測試相同。確切的調用取決於董事會:
cargo xtask test test/tests-lpc55xpresso/app.toml
cargo xtask test test/tests-stm32fx/app-f3.toml
cargo xtask test test/tests-stm32fx/app.toml
cargo xtask test test/tests-stm32h7/app-h743.toml
cargo xtask test test/tests-stm32h7/app-h753.toml
注意: cargo xtask humility test
運行OpenOCD以連接到設備。您必須在運行測試之前退出您已連接到設備的任何其他實例。
有關測試結果的詳細信息,請參見文檔以獲取humility test
。
測試的輸出通過humility test
捕獲;可以添加sys_log!()
調用測試,然後在humility test
轉儲中捕獲。要從否則通過的測試中捕獲轉儲,請直接使用cargo xtask humility
並傳遞-d
標誌,例如:
$ cargo xtask humility test/tests-stm32fx/app.toml -- test -d
...
humility: attached via ST-Link
humility: TPIU sync packet found at offset 1
humility: ITM synchronization packet found at offset 12
humility: expecting 22 cases
humility: running test_send ... ok
...
humility: running test_timer_notify ... ok
humility: running test_timer_notify_past ... ok
humility: tests completed: pass
humility: test output dumped to hubris.testout.2
如果需要同時運行GDB和測試套件,請在測試圖像的TOML和適當的GDB文件中使用cargo xtask gdb
,然後將斷點放置在感興趣的測試中。
請參閱Gemini Buthup入門文檔(內部氧化物回購)
對於STM32F3發現板,必須將SB10焊接到ITM上工作!這款焊橋默認為開放,這使SWO斷開了連接。有關示意圖和詳細信息,請參見STM32F3 Discovery用戶手冊(UM1570)。
要使用lpcxpresso55s69,您將需要PYOCD,版本0.27.0或更高版本。
LPCXPRESSO55S69有點混亂,因為內置的芯片調試器LPC-Link2無法正確支持SWO/SWV
如果您擁有庫存LPC-Link2,它將通過pyocd list
以這種方式報告:
$ pyocd list
# Probe Unique ID
-----------------------------------------------------------------
0 NXP Semiconductors LPC-LINK2 CMSIS-DAP V5.361 JSAQCQIQ
您也有可能擁有Segger J-Link固件 - 固件將通過促使您在運行pyocd list
時接受許可條款而聞名!
$ pyocd list
# Probe Unique ID
-----------------------------------------------------------------------------
0 Segger J-Link LPCXpresso V2 compiled Apr 4 2019 16:54:03 726424936
在任何一種情況下,您都必須(作為一次性步驟)在LPC-Link2上安裝新固件。新的固件是(開源)Daplink的構建,我們以此為由地稱呼Ricklink,後者是設法建立的工程師,這並不是一件小事!
您需要兩個文件,這兩者都包含在傲慢存儲庫中:
您還需要NXP的LPCSCRYPT程序。
這是安裝ricklink的步驟:
安裝DFU跳線。可以在板左側的SWD標頭旁邊找到。它標記為“ DFU”。
從已安裝的LPCSCRYPT軟件運行scripts/boot_lpcscrypt
:
$ /usr/local/lpcscrypt/scripts/boot_lpcscrypt
Looking for DFU devices with VID 1fc9 PID 000c ...
dfu-util -d 1fc9:000c -c 1 -i 0 -t 2048 -R -D /usr/local/lpcscrypt/scripts/../bin/LPCScrypt_228.bin.hdr
Booted LPCScrypt target (1fc9:000c) with /usr/local/lpcscrypt/scripts/../bin/LPCScrypt_228.bin.hdr
$
lpcscrypt clockslow
: $ /usr/local/lpcscrypt/bin/lpcscrypt clockslow
$
lpcscrypt program +w1 0x0 BankA
覆蓋現有的固件$ /usr/local/lpcscrypt/bin/lpcscrypt program +w1 0x0 BankA
................
Programmed 524288 bytes to 0x1a000000 in 2.610s (196.165KB/sec)
$
lpcscrypt program +c <path-to-lpc4322_bl_crc.bin> BankA
: $ /usr/local/lpcscrypt/bin/lpcscrypt program +c ~ /hubris/support/lpc4322_bl_crc.bin BankA
..
Programmed 57344 bytes to 0x1a000000 in 0.827s (67.717KB/sec)
$
假設成功,請刪除DFU跳線並斷開/重新連接USB
現在應該有一個名為MAINTENANCE
的USB質量存儲設備
# fdisk -l
Disk /dev/nvme0n1: 477 GiB, 512110190592 bytes, 1000215216 sectors
Disk model: Micron 2200S NVMe 512GB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: A8653F99-39AB-4F67-A9C9-524A2864856E
Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 1050623 1048576 512M EFI System
/dev/nvme0n1p2 1050624 967393279 966342656 460.8G Linux filesystem
/dev/nvme0n1p3 967393280 1000214527 32821248 15.7G Linux swap
Disk /dev/sda: 64.1 MiB, 67174400 bytes, 131200 sectors
Disk model: VFS
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000
# mount /dev/sda /mnt
# ls /mnt
DETAILS.TXT PRODINFO.HTM
# cat /mnt/DETAILS.TXT
# DAPLink Firmware - see https://mbed.com/daplink
Unique ID: 02360b000d96e4fc00000000000000000000000097969905
HIC ID: 97969905
Auto Reset: 1
Automation allowed: 1
Overflow detection: 1
Daplink Mode: Interface
Interface Version: 0254
Bootloader Version: 0254
Git SHA: f499eb6ec4a847a2b78831fe1acc856fd8eb2f28
Local Mods: 1
USB Interfaces: MSD, CDC, HID, WebUSB
Bootloader CRC: 0x09974fb3
Interface CRC: 0x7174ab4c
Remount count: 0
URL: https://os.mbed.com/platforms/LPCXpresso55S69/
lpc4322_lpc55s69xpresso_if_rla_swo_hacks.bin
到USB驅動器$ sudo cp ~ /hubris/support/lpc4322_lpc55s69xpresso_if_rla_swo_hacks.bin /mnt
$
# umount /mnt
#
通過運行pyocd list
來驗證您在新固件上:
$ pyocd list
# Probe Unique ID
-------------------------------------------------------------------------------------
0 LPCXpresso55S69 [lpc55s69] 02360b000d96e4fc00000000000000000000000097969905
請注意,在LPCXPResso55S69上運行的Ricklink也可以用作Gemini載體板上LPC55S28的調試器。為此,首先,請按照上面的所有說明將Ricklink進入您的LPCXPRESSO55S69。然後:
使用焊接的鐵,在J5上焊接了兩針頭。可以在P1的左側和“調試器”跳線(J3)的左側找到J5。
在新標頭上放一個跳線
將“調試器”跳線(J3)移至“ ext”。
使用SWD電纜(10針2x5 1.27mm螺距電纜)將LPCXPRESSO55S69上的SWD連接到Gemini載體板下方的SWD(J202)
(要允許您的Ricklink再次調試其本地LPC55S69,請刪除J5上的跳線,然後將J3移至“ LOC”。)
如果附有多個探測器,工具可能會在正確的時間找到合適的探針。特別是,OpenOCD會選擇它找到的第一個;為了強制openOCD選擇特定的探針,您可以確定探針的序列號(例如,從humility probe
openocd.cfg
,然後通過添加,例如:
interface hla
hla_serial 271828182845904523536028
(其中271828182845904523536028
是探針的序列號。)
通常,調試加密狗和帶有嵌入式調試硬件(例如Nucleo系列)的開發板是用較舊的固件交付的。
您將無法使用過時的ST-Link固件使用Humilty。謙卑會告訴您情況,例如,在嘗試使用humility test
時:
...
Warn : Adding extra erase range, 0x08020060 .. 0x0803ffff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
humility: test failed: The firmware on the probe is outdated
Error: test failed
請按照此“ ST-Link固件升級”鏈接找到安裝當前固件所需的軟件和說明。