Rusty Nixie! 完全使用Rust製作輝光鍾(1)

Rusty Nixie! 完全使用Rust製作輝光鍾(1)

來自專欄 Hacky Teddy

前言

終終終終於要填坑啦!自上個暑假以來,Ted開了n多個坑,然而卻一直由於種種原因無法填上。包括這個項目在內的還有「從零開始全棧黑白膠片攝影」和「Rust紅白機模擬器」。希望能盡快都形成文字和大家見面。

Rust語言與嵌入式編程

去年此時,Ted久聞Rust大名,決定一探究竟。學習一個語言最好的方式就是不斷使用以熟悉,因此他打算用Rust來做些有趣的事情。作為一個CS菜鳥,Ted對EE的事情毫無頭緒。由於大學時期鬼使神差地錯過了模擬電路和數字電路兩座大山,他既不知道什麼三極體集電極,也不了解什麼TTL寄存器。

身為食物鏈頂端的碼農,他很迫切想搞清楚很多困擾已久的概念。尤其是身為一個研究計算機系統的PhD,怎麼能對硬體系統一無所知呢?有強迫症的他,藉著這次學習的機會,用Rust來寫一些bare-metal的代碼,最好能直接刷寫在chip上運行。於是他想到了MCU。不要問我他怎麼知道MCU的。

MCU,即Marvel Cinematic Universe 漫威電影宇宙,哦不,MicroController Unit 單片機。形象點說就是集成了處理器、內存、IO功能的晶元。這次Ted選擇了比較常見便宜的STM32系列晶元:STM32F103C8。它內置了最大主頻為72MHz的ARM Cortex-M3 CPU,64K Flash和20K SRAM。也就是說最多20K的運行時內存和64K的固件。STM32系列的chip可以直接通過ST-link在串口寫入或者調試代碼,十分方便。

Rust,是一款生存向PvP遊戲,哦不,是一款近年來逐漸受到關注的靜態類型,保證內存安全和線程安全的類C程序語言。用它寫的程序跑得快,還不受segfaults或者data-race的困擾,十分適合系統編程。與golang不同的是,它的內存安全不是通過GC,而是通過programming model來實現的。它支持type polymorphism和hygienic macros,且官方提供了較為完善的工程構建和包管理系統。

Nixie Tube

既然要用Rust做嵌入式開發,且最後程序無需OS直接在bare-metal chip上運行,考慮到參考資料並不太多且沒有過嵌入式經驗,Ted打算從最簡單的系統入手:時鐘。當然,為了讓project更加有趣酷炫,必須在時鐘顯示上面下點功夫,比如使用Nixie tube(輝光管)。在上世紀50年代,VFD、LCD或是LED被廣泛使用前,電子儀器的數字指示主要是通過Nixie Tube來實現的。它的原理是利用陰極電子在高壓下向陽極發射,擊中附近的惰性氣體,從而發出輝光。一個顯示0-9數字的輝光管內一般有10個金屬片,每個金屬片被做成相應數字的形狀,且與一個對應的陰極接腳相連。這些金屬片像千手觀音那樣被疊放起來,以至於當其中任意一個發出輝光時,都會讓人忽略掉其他未發光的金屬片的存在,從而實現可變的數字顯示。最後,陽極的金屬網罩將所有金屬片圍起來,提供電子發射的電勢。

不知是不是因為符合工程暴力美學,現在市面上保有的絕大部分輝光管都是產自蘇聯。這種燈管因為壽命遠低於後來的替代技術,且需要較高的工作電壓,功耗高,很快便成為了歷史。然而因為它顯示數字獨特的輝光,以及和後來分段顯示不同的顯示方式,在如今搖身一變為收藏品。因為已經停產,那些相對保有量較少的管子更是價格令人咋舌。此外,由於有些蒸汽朋克的外觀,它也出現在影視作品和遊戲之中,例如《命運石之門》中的世界線變動檢測儀,或是《輻射4》中的機甲HUD。

思路和關鍵技術

在完全沒有硬體方面經驗的情況下,Ted以他作為system researcher 敏(yu)銳(dun)的直覺列舉了以下的關鍵點:

  1. 如何只使用Rust完成一個bare-metal的"Hello, World"程序(閃爍外部的LED)?
  2. 印象中好像控制一個外部設備不需要那麼多接線,但是如果製作一個同時控制6位數的電路,再怎麼也得每個bit需要一個IO吧?除非,除非用多個時鐘週期來完成一次顯示的更新……
  3. 如何在不使用數量巨大IO的情況下讓二進制的介面控制實際上是十進制的燈管(因為有10個陰極)?除非有個神奇的現成的晶元可以把4位二進制的編碼轉成10個腳的通斷……
  4. 如何在5v的工作電壓的邏輯門下驅動170v懸空電壓的輝光管?

最後,Ted發現這些問題都得到了令人滿意的答案:

  1. 處理器有著固定的Reset中斷地址,相當於整個代碼執行的起始點。交叉編譯器能處理好這個問題,與語言無關。但是工具鏈需要把代碼和內存地址正確地與物理地址對應起來(在沒有OS的情況下),且Rust代碼需要在編譯時去掉標準庫。
  2. 完全正確,這種思路就是串列,可以通過移位寄存器(Shift register)來實現。
  3. 其實就是4個bit的多路選通器(Multiplexer),也叫做譯碼器(Decoder),這種邏輯太常見了,有集成電路賣。
  4. 使用open-drain的設計方式,可以用高壓三級管來控制接地的通斷,或者直接省事購買能耐高壓的decoder。

接下來的幾個連載會介紹整個過程,在這之前先放實物圖。

初號機顯示時間晚上10點57分38秒:

二號機調試過程中:

推薦閱讀:

TAG:Rust編程語言 | 嵌入式開發 | 單片機 |