最初からオペレヌティングシステム。 レベル1叀い半分

次のパヌトの時が来たした。 これは、翻蚳ラボ番号1の埌半です。 この問題では、呚蟺機噚ドラむバヌタむマヌ、GPIO、UARTを蚘述し、XMODEMプロトコルず1぀のナヌティリティを実装したす。 これらすべおを䜿甚しお、カヌネルのコマンドシェルず、microSDカヌドを前埌に動かさないようにするブヌトロヌダヌを䜜成したす。


䞋半分 。
読曞はれロラボで始たりたす 。


フェヌズ3貝殻ではない



今回は、統合された呚蟺機噚甚のドラむバヌをいく぀か䜜成したす。 組み蟌みタむマヌ、GPIO、およびUARTに興味がありたす。 それらは組み蟌みのコマンドラむンを曞くのに十分であり、少し埌にブヌトロヌダヌを䜜成するのに䟿利になりたすこれにより、さらに䜜業がいくらか簡単になりたす。


ドラむバヌずは䜕ですか

ドラむバヌたたはデバむスドラむバヌずいう甚語は、特定のハヌドりェアデバむスず盎接察話し、それを管理する゜フトりェアなどです。 ドラむバヌは、制埡するデバむスに高レベルのむンタヌフェむスを提䟛したす。 オペレヌティングシステムは、デバむスドラむバヌず察話しお、それらの䞊にさらに高床な抜象化を構築したすもちろん、䟿宜䞊。 たずえば、Linuxカヌネルは、ドラむバヌず察話するオヌディオ甚のAPIであるALSAAdvanced Linux Sound Architectureを提䟛し、ドラむバヌはサりンドカヌドず盎接通信したす。

サブフェヌズAはじめに


割り圓おの残りの郚分では、 osカブの内郚で䜜業したす。これは、この郚分だけでなく、コヌスの残りの郚分でも䜿甚されたす。 最終的にオペレヌティングシステムになるのは、このリポゞトリです。


このコヌスを参照しお、ラボなどすべおに次のディレクトリ構造をお勧めしたす。


 cs140e ├── 0-blinky │ ├── Makefile │ ├── phase3 │ └── phase4 ├── 1-shell │ ├── ferris-wheel │ ├── getting-started │ ├── stack-vec │ ├── ttywrite │ ├── volatile │ └── xmodem └── os ├── Makefile ├── bootloader ├── kernel ├── pi ├── std └── volatile 

快適で端正な。 0-blinkyおよび1-shellは、以前のラボず珟圚のラボを指し、 osは次のように取埗できたす。


 git clone https://web.stanford.edu/class/cs140e/os.git os git checkout master 

すべおが正しく配眮されおいるこずを確認し、 os/kernel内でmakeを実行しos/kernel 。 すべおが正垞であれば、コマンドは正垞に実行されたす。


プロゞェクト構造


osディレクトリには、次の䞀連のサブディレクトリが含たれたす。



すべおのドラむバヌコヌドはpiラむブラリにありたす。 piはvolatileラむブラリずオプションで stdたす。 kernelずbootloaderはpiを䜿甚しおデバむスず通信したす。 そしお、これに加えお、それらはstdに䟝存しおいstd 。 volatileは䜕にも䟝存したせん。 グラフィカルに、この関係は次のようになりたす。



ファヌムりェア


続行する前に、ラズベリヌファヌムりェアを曎新する必芁がありたす。 これらはすべお、 osディレクトリからmake fetchコマンドでダりンロヌドできたす。 必芁な玠材をfiles/ロヌドしfiles/ 。 firmware/bootcode.bin 、 firmware/config.txtおよびfirmware/start.elfをmicroSDカヌドのルヌトにコピヌしfirmware/bootcode.bin 。 前の郚分からact-led-blink.binコピヌし、名前をkernel8.imgに倉曎kernel8.imgたす。 したがっお、すべおが機胜するこずを確認できたす。 そこで、ラズベリヌ自䜓の緑色のLEDが点滅したす。


曎新されたvolatile


osフォルダヌにあるこのラむブラリヌは、フェヌズ2で怜蚎したコヌドずは少し異なりたす。倉曎により、デバむスドラむバヌの䜜成のコンテキストでこれを少し簡単に䜿甚できるようになりたす。 䞻な違いは次のずおりです。


  1. UniqueVolatileがUnique<Volatile>眮き換えられたした
  2. Reservedタむプを远加したした。これは絶察に䜕もできず、スタブずしお䜿甚されたす

もう1぀、より重芁な違いがありたす。 ラむブラリのすべおの型は、 *mut T TではなくTラップしたす*mut T これにより、ラッピングせずにあらゆる皮類の生のアドレスを䜿甚し、次のようにキャストできたす0x1000 as *mut Volatile<T> 。 これに加えお、 Volatileラップされたフィヌルドを含む構造を指定できたす。 このようなもの


 #[repr(C)] struct Registers { REG_A: Volatile<u32>, REG_B: Volatile<u8> } //    .  `Registers`   `0x4000`  . //     `u32`     `u8`      // (. ). let x: *mut Registers = 0x4000 as *mut Registers; //       `unsafe`. //   Rust        unsafe { //   Rust      (*x).REG_A.write(434); let val: u8 = (*x).REG_B.read(); } 

#[repr(C)]ずは䜕ですか

远蚘#[repr(C)]は、RustがSmallず同じ方法でメモリ内に構造を圢成するように匷制したす。 これがなければ、Rustにはフィヌルドの順序ずフィヌルド間のむンデントを最適化する暩利がありたす。 生のポむンタを䜿甚する堎合、ほずんどの堎合、メモリ内の特定の構造を意味したす。 したがっお、 #[repr(C)]䜿甚するず、Rustが想定どおりに構造をメモリに配眮するこずをアサヌトできたす。

コア


os/kernelディレクトリには、OSのカヌネルコヌドの準備が含たれおいたす。 このディレクトリ内のmake呌び出しは、カヌネルを収集したす。 アセンブリの結果はbuild/サブディレクトリにありたす。 このビゞネスを開始するには、 build/kernel.binをkernel8.imgずいう名前でmicroSDカヌドのルヌトにコピヌbuild/kernel.bin必芁がありたす。 珟圚、カヌネルは䜕もしおいたせん。 このフェヌズの終わりたでに、カヌネルにはチャット可胜なテキストベヌスの察話型シェルが含たれたす。


kernelラックはpiラックに䟝存したす。 extern crate pi;を芋るこずができたすextern crate pi; kernel/src/kmain.rsに蚘述しCargo.toml 。 ぀たり pi宣蚀されたすべおの型ず構造を非遞択的に䜿甚できたす。


ドキュメント


ドラむバヌを䜜成するずき、 BCM2837ペリフェラルマニュアルは非垞に圹立ちたす。


サブフェヌズBシステムタむマヌ



このサブフェヌズでは、組み蟌みタむマヌのドラむバヌを䜜成したす。 䞻な䜜業は、ファむルos/pi/src/timer.rsおよびos/kernel/src/kmain.rsたす。 タむマヌは、 BCM2837呚蟺機噚マニュアルの 172ペヌゞセクション12に蚘茉されおいたす。


最初に、すでにos/pi/src/timer.rsあるコヌドを芋おos/pi/src/timer.rs 。 少なくずもこれらの郚分


 const TIMER_REG_BASE: usize = IO_BASE + 0x3000; #[repr(C)] struct Registers { CS: Volatile<u32>, CLO: ReadVolatile<u32>, CHI: ReadVolatile<u32>, COMPARE: [Volatile<u32>; 4] } pub struct Timer { registers: &'static mut Registers } impl Timer { pub fn new() -> Timer { Timer { registers: unsafe { &mut *(TIMER_REG_BASE as *mut Registers) }, } } } 

最初に泚意する必芁があるunsafeでunsafeコヌドの1行がありたす。 *mut RegistersのアドレスTIMER_REG_BASEはこの行にキャストされ、その埌すぐに&'static mut Registersに倉わりたす。 実際、 TIMER_REG_BASEの構造ぞの静的リンクが必芁であるこずをTIMER_REG_BASEおいたす。


TIMER_REG_BASEには正確に䜕がありたすか マニュアルの 172ペヌゞで、 0x3000がタむマヌの呚蟺の先頭からのオフセットであるこずがわかりたす。 ぀たり TIMER_REG_BASEは、このタむマヌのレゞスタが始たるアドレスです。 unsafeでunsafe 1行の埌に、 registersフィヌルドを䜿甚しお、これらすべおに完党に安党にアクセスできたす。 たずえば、 self.registers.CLO.read()をself.registers.CLO.read()おCLOレゞスタをself.registers.CLO.read()か、たたは
self.registers.CS.write()を䜿甚するCS 。


なぜCLOおよびCHIレゞスタに曞き蟌めないのですか [制限付き読み取り]

BCM2837のドキュメントには、 CLOおよびCHIレゞスタが読み取り専甚であるず蚘茉されおいたす。 コヌドはこのプロパティを提䟛したす。 どうやっお 䜕がCLOずCHI曞くこずを劚げたすか



安党ではないものは䜕ですか

芁するに、 unsafeはRustコンパむラヌのマヌカヌであり、ナヌザヌはメモリヌのセキュリティを制埡しおいるず蚀いたす。 コンパむラヌは、これらのコヌドのメモリヌ問題からナヌザヌを保護したせん。 コヌドのunsafe郚分では、Rustを䜿甚しお、Neat Cで実行できるすべおの操䜜を実行できたす。 できる コラバンを奪う あるタむプを別のタむプにキャストし、生のポむンタヌで遊んで、寿呜を䜜成するだけで十分です。

ただし、 unsafeブロック内のコヌドは非垞に危険です。 安党でないセクションで行うこずは、実際に安党であるこずを確認する必芁がありたす。 これは䞀芋思われるよりも耇雑です。 特に、Rustのセキュリティ抂念は他の蚀語よりも厳栌であるためです。 unsafeでないものを䜿甚しunsafeしおください。 もちろん、可胜な範囲で。 オペレヌティングシステムなどの堎合、機噚ず盎接通信する堎合は、 unsafeを䜿甚する必芁がありたす。 ただし、この䜿甚はできる限り制限したす。

unsafeモアレを読みたい堎合は、Nomiconの第1章をご芧ください 。 さらに、この小さな本を通しお、Rustのさたざたな匷力な魔術垫に圹立぀倚くのこずを孊ぶこずができたす。

ドラむバヌの実装


os/pi/src/timer.rs Timer::read() os/pi/src/timer.rsからTimer::read()実装しos/pi/src/timer.rs 。 次に、メ゜ッドcurrent_time() 、 spin_sleep_us() 、 spin_sleep_ms()が近くにありたす。 これらの関数のコメントず名前は、期埅される機胜を瀺しおいたす。 Timer::read()を実装するには、適切なセクションのBCM2837ドキュメントを読む必芁がありTimer::read() 。 少なくずも、64ビットタむマヌ倀党䜓を取埗するために読み取る必芁があるレゞスタを理解する必芁がありたす。 cargo buildしお、パむクレヌトを組み立おるこずができたす。 ただし、 cargo checkを䜿甚しお蚘述された内容の正確性を単玔にチェックする方が高速です。


ドラむバヌテスト


spin_sleep_ms()関数が正しく実装されおいるこずを確認するこずはspin_sleep_ms()です。 これを行うには、 kernel/src/kmain.rs適切なコヌドを蚘述しkernel/src/kmain.rs 。


れロラボのフェヌズ4からLEDの点滅コヌドをコピヌしたす。 ルヌプ内でスピンするだけのスリヌプ関数の代わりに、 spin_sleep_ms()関数を䜿甚しお、点滅間の䌑止を䜜成する必芁がありたす。 カヌネルを再コンパむルし、 kernel8.imgずいうメモリカヌドにロヌドしたす。 すべおを実行しお、蚈画した頻床でLEDが点滅するこずを確認したす。 別の遅延サむズを蚭定しお、すべおが機胜するこずを確認しおください。 はい、microsdカヌドを垞に前埌に突くのは非垞に面倒です。 このパヌトの終わりたでに、この問題を解決するブヌトロヌダヌができたす。


タむマヌのドラむバヌ実装が機胜する堎合、次のサブフェヌズに進むこずができたす。


サブフェヌズCGPIO


このサブフェヌズでは、特定のピン番号に関係なく、汎甚GPIOドラむバヌを䜜成したす。 䞻な䜜業は、ファむルos/pi/src/gpio.rsおよびos/kernel/src/kmain.rsたす。 GPIOのドキュメントは、 BCM2837呚蟺機噚マニュアルの 89ペヌゞセクション6にありたす 。


ステヌトマシン



すべおのハヌドりェアデバむスは、本質的にステヌトマシン  eng ず芋なすこずができたす。 それらはある状態で初期化され、他の状態に明瀺的たたはそうではありたせん。 同時に、デバむスは珟圚の状態に応じおさたざたな機胜を提䟛したす。 ぀たり、特定の特定の状態では、他の状態ぞの特定の遷移セットのみが動䜜可胜です。


ほずんどのプログラミング蚀語では、有限状態マシンのセマンティクスを正確に远跡するこずは䞍可胜です。 しかし、もちろんこれはRustには圓おはたりたせん。 Rustを䜿甚するず、このセマンティクスを非垞に明確に远跡できたす。 これを䜿甚しお、より安党なGPIOドラむバヌを実装したす。 ドラむバヌは、すべおのGPIOピンが垞に正しく䜿甚されるようにしたす。 コンパむル段階。


* ある皮の研究のように芋える...

あなたは私を捕たえた。 これは本質的に、珟時点での私の研究分野です。 - セルゞオ

以䞋に、GPIOステヌトマシンプロパティのサブセット1ピンの状態図を瀺したす。



私たちの目暙は、これらすべおをRustで実装するこずです。 そもそも、sobsnaは次の図を教えおくれたす。



ラボ0ではどのようなトランゞションを䜿甚したしたか [たばたき状態]

Lab 0からフェヌズ4のコヌドを蚘述したずき、本質的にステヌトマシンのサブセットを暗黙的に実装したした。 この堎合、状態間のどのような遷移が実珟したしたか

Rustタむプシステムを䜿甚しお、ピンがOUTPUT状態にある堎合にのみSETおよびCLEAR 、 INPUT状態にある堎合にLEVELのみが可胜であるこずを保蚌したす。 pi/src/gpio.rsのGPIO構造宣蚀を芋おください


 pub struct Gpio<State> { pin: u8, registers: &'static mut Registers, _state: PhantomData<State> } 

構造䜓には、 Stateずいう䞀般的な匕数が1぀ありたす。 PhantomDataのみが䜿甚し、他のPhantomDataは䜿甚したせん。 実際、そのようなPhantomDataのために、構造が䜕らかの圢で䞀般化された匕数を䜿甚しおいるこずをRustに玍埗させるために存圚したす。 Gpio状態のマヌカヌずしおStateを䜿甚Gpioたす。 同時に、このパラメヌタヌの特定の倀を䜜成できないようにする必芁がありたす。


マクロstate! そこにあるず思われる型を生成したすが、䜜成するこずはできたせん。 この堎合、 Gpioの状態のリストが生成さGpioたす。


 states! { Uninitialized, Input, Output, Alt } //        -  : enum Input { } 

倉に芋えたす 。 可胜な倀なしで列挙を䜜成する必芁があるのはなぜですか 圌らは1぀の快適なプロパティがありたす。 䜜成できたせん。 ただし、マヌカヌずしお䜿甚できたす。 Input型の倀は䜜成できないため、だれも枡すこずができたせん。 それらはタむプのレベルでのみ存圚し、他のどこにも存圚したせん。


次に、適切な遷移セットを䜿甚しお各状態のメ゜ッドを実装できたす。


 impl Gpio<Output> { ///   pub fn set(&mut self) { ... } ///   pub fn clear(&mut self) { ... } } impl Gpio<Input> { ///      pub fn level(&mut self) -> bool { ... } } 

これは、 Gpioが状態に応じお厳密に定矩された方法でのみGpioできるずいう保蚌のように芋えたす。 悪くないでしょ しかし、これらの状態をどのように達成するのでしょうか これを行うには、 Gpio::transition()メ゜ッドがありたす。


 impl<T> Gpio<T> { fn transition<S>(self) -> Gpio<S> { Gpio { pin: self.pin, registers: self.registers, _state: PhantomData } } } 

この方法を䜿甚するず、 Gpioをある状態から別の状態に簡単か぀自由に転送できたす。 状態T Gpioを取埗し、状態S GpioをGpio S すべおのSおよびTで機胜するこずに泚意しおくださいT このメ゜ッドは非垞に慎重に䜿甚する必芁がありたす。 このすべおに間違いを犯した堎合、ドラむバヌは誀っお蚘述されおいるず芋なされたす。


transition()を䜿甚するには、 Gpio<S>タむプSを指定する必芁がありたす。 Rustに十分な情報を提䟛しお、Rustがすべお自分で取埗できるようにしたす。 たずえば、 into_outputメ゜ッドの実装


 pub fn into_output(self) -> Gpio<Output> { self.into_alt(Function::Output).transition() } 

このメ゜ッドでは、戻り倀の型がGpio<Output>こずが必芁です。 Rust型システムはtransition()呌び出しを調べるず、 Gpio::transition()メ゜ッドをGpio<Output>たす。このメ゜ッドはGpio<Output>を返したす。 圌は、任意のS存圚するGpio<S>を返すメ゜ッドを芋぀けたすS したがっお、 S代わりにS Outputを安党に眮き換えるこずができたす。 その結果、 Gpio<Alt>  into_alt関数からをGpio<Output>に倉換したす。


クラむアントが任意の状態を枡すこずができる堎合はどうなりたすか [停の状態]

ナヌザヌコヌドがGpio構造の初期状態を自由に遞択できるようにするずどうなるかを考えおください。 䜕がおかしいのでしょうか



なぜこれがすべおRustでしかできないのですか

into_遷移は移動のセマンティクスを䜿甚するずいう小さな事実に泚意しおください。 これは、 Gpioが別の状態になるずすぐに、以前の状態ではアクセスできなくなるこずを意味したす。 型がClone 、 Copyおよびその他の耇補メ゜ッドを実装するたで、逆遷移は䜿甚できたせん。 他の蚀語ではそれができたせん。 C++でも。 すべおの保蚌付きのコンパむル䞭のそのような魔術垫はここだけです。 プラスや他の䜕かの達人は、この声明に挑戊しようずするこずができたす

ドラむバヌの実装


unimplemented!()代わりに必芁なコヌドをすべお曞いおunimplemented!()ファむルpi/src/gpio.rs これらすべおの方法のコメントず眲名から、理解できたす 控陀を䜿甚しお 期埅される機胜。 ドキュメント89ペヌゞ、 BCM2837マニュアルのセクション6を参照するこずは䞍芁です。 cargo checkの有甚性を忘れないでcargo check 。


ヒント䞭括匧{ ... }を䜿甚しお任意の字句スコヌプを䜜成できるこずを忘れないでください。

ドラむバヌテスト


明らかに、ドラむバヌをテストするには、 kernel/src/kmain.rsいく぀かのコヌドを曞く必芁がありkernel/src/kmain.rs 。


今回は、レゞスタ自䜓を盎接読み曞きする代わりに、LEDを点滅させるためにドラむバヌを䜿甚したす。 GPIOピン番号16をオン/オフするこずにより、同時に、コヌド党䜓がよりクリヌンで゚レガントになりたす。 カヌネルをコンパむルし、 kernel8.imgずいうカヌドにロヌドしお、 kernel8.imgラズベリヌを実行したす。 LEDは以前ずたったく同じように点滅するはずです。


これで、より倚くのLEDを接続できたす。 5、6、13、19、26の番号が付けられたGPIOピンを䜿甚したす。れロラボのピンの番号付きの図を参照しお、物理的な䜍眮を確認したす。 あなたが望むように倚くのLEDでコアを点滅させおください


どの点滅パタヌンを遞択したしたか [LEDパタヌン]

LEDをオン/オフするこずにしたスキヌムは䜕ですか 奜みに合わせお倚くのオプションから遞択できたす。 ただし、遞択が厳しい堎合は、サヌクルでオンずオフを切り替えるこずができたす。 画像

GPIOドラむバヌが完党に動䜜可胜になったら、次のサブフェヌズに進むこずができたす。


サブフェヌズDUART


このサブフェヌズでは、ミニUARTデバむスドラむバヌを䜜成したす。これは、ラズベリヌの割合に組み蟌たれおいたす。 ほずんどの䜜業は、ファむルos/pi/src/uart.rsおよびos/kernel/src/kmain.rsたす。 Mini UARTは、 BCM2837マニュアルの 8ペヌゞず10ペヌゞセクション2.1ず2.2に蚘茉されおいたす 。


UARTナニバヌサル非同期RX / TX


UART  ru たたはUniversal Synchronous Reception Transmitterは、腺を2本のワむダで通信するためのデバむスおよびシリアルプロトコルです。 これらは、CP2102 USBモゞュヌルのUARTデバむスをラズベリヌのUARTデバむスに接続するために、れロラボのフェヌズ1で䜿甚されたものず同じ2぀の配線rx / txです。 UARTを介しお任意のデヌタを送信できたす。テキスト、バむナリファむル、シヌル付きの写真など、ファンタゞヌに十分なものです。 䟋ずしお、次のサブフェヌズで、ラズベリヌのUARTから読み取り、CP2102のUARTに曞き蟌む察話型シェルを䜜成したす。 フェヌズ4では、ほが同じ方法でバむナリ情報を送信したす。


UARTプロトコルにはいく぀かの構成パラメヌタヌがありたす。 すべおが機胜するためには、受信機ず送信機の䞡方を同䞀に構成する必芁がありたす。 これらは次のパラメヌタヌです。



Mini UARTはパリティビットをサポヌトせず、1぀のストップビットのみをサポヌトしたす。 したがっお、ボヌレヌトずフレヌム長を蚭定するだけです。 UART通信の基本 翻蚳が必芁ですかずいうドキュメントで、UART自䜓に぀いおもう少し読むこずができたす。


ドラむバヌの実装


この段階では、各ステップをペむントするこずなくデバむスドラむバヌを䜜成するために必芁なすべおのツヌルが甚意されおいたす。 おめでずうございたす


タスクは、必芁なすべおをファむルpi/src/uart.rsに実装するこずです。 Registers構造のコンテンツを远加する必芁がありたす。 この堎合、各レゞスタに最䜎限必芁な機胜のセットを備えた[ Volatileタむプ]オプションを䜿甚したす。 これらの読み取り専甚レゞスタはReadVolatileを䜿甚する必芁がありたす。 WriteVolatileのみWriteVolatile蚱可されおいる堎合、 WriteVolatile 。 予玄スペヌスにはReservedたす。 new() 115200 ( 270) 8 . unimplemented!() , . fmt::Write , io::Read io::Write MiniUart .


: LCR , BAUD CNTL new /

: GPIO .


, ( kernel/src/kmain.rs ), . :


 loop { write_byte(read_byte()) } 

screen /dev/<_> 115200 UART. screen TTY . , . ぀たり . :


 loop { write_byte(read_byte()) write_str("<-") } 

, — .


E: The Shell


UART . os/kernel/src/console.rs , os/kernel/src/shell.rs os/kernel/src/kmain.rs .


Console



, , - / . Unix stdin stdout . Console . Console kprint! kprintln! 。 , print! println! 。 . Console , .


os/kernel/src/console.rs . Console . - MiniUart . . . MiniUart MiniUart Console .



— , . Rust. Rust . , ? , unsafe . : Rust'y, , .. , "" . , . Rust . :


 //      ! fn make_mut<T>(value: &T) -> &mut T { unsafe { /*      */ } } 

. . , , unsafe Rust. , . " ". ぀たり . .


, . , . , ( & ). , ( &T -> &mut ).


. , , :


 fn lock<T>(value: &T) -> Locked<&mut T> { unsafe { lock(value); cast value to Locked<&mut T> } } impl Drop for Locked<&mut T> { fn drop(&mut self) { unlock(self.value) } } 

Mutex . — , :


 fn get_mut<T>(value: &T) -> Mut<&mut T> { unsafe { if ref_count(value) != 0 { panic!() } ref_count(value) += 1; cast value to Mut<&mut T> } } impl Drop for Mut<&mut T> { fn drop(&mut self) { ref_count(value) -= 1; } } 

, RefCell::borrow_mut() . — , :


 fn get_mut<T>(value: &T) -> Option<Mut<&mut T>> { unsafe { if ref_count(value) != 0 { None } else { ref_count(value) += 1; Some(cast value to Mut<&mut T>) } } } impl Drop for Mut<&mut T> { fn drop(&mut self) { ref_count(value) -= 1; } } 

RefCell::try_borrow_mut() . " ": . Console Mutex . std::Mutex — . . kernel/src/mutex.rs . , , , Rust. Mutex , , .


だから。 CONSOLE kernel/src/console.rs . kprint! kprintln! , . , Console — Console . CONSOLE Console .


Rust Sync .

T static , T Sync . , Rust . , Rust , . Send Sync , Rust .



** &mut T ? [drop-container]

, , Drop . , &mut T ?



write_fmt ? [write-fmt]

_print write_fmt MutexGuard ( Mutex<Console>::lock() . write_fmt ?

Console


, unimplemented!() kernel/src/console.rs . kprint! kprintln! , kernel/src/kmain.rs , , . , print! println! 。 screen /dev/<-> 115200 .


...

println! — Rust. printf . Rust , , . . , ? .



: Console : .


完成品


. kernel/src/shell.rs . Command . Command::parse() Command . parse args StackVec , buf . Command::path() .


( Command , StackVec , Console CONSOLE , kprint! , kprintln! , ) shell . prefix , . "> " . , . ad-infinitum . . echo .


, :



shell . kernel/src/kmain.rs . SOS, , . , . — . .


:

b'a' u8 'a'

\u{b} ASCII b

\r \n

, backspace, , backspace

StackVec

std::str::from_utf8



std !

, std . . , , xargo doc --open os/std .



? [shell-lookback]

. , .

4:


, , Raspberry Pi. os/bootloader/src/kmain.rs


, MicroSD- . , , . , .


— "", , XMODEM UART. , . ttywrite . :




Raspberyy Pi 3 kernel8.img 0x80000 . , , kernel8.img 0x80000 ARM' (program counter) 0x80000 . , . , 0x80000 .


(linker, ). . : , . , . os/kernel/ext/layout.ld ( ). , 0x80000 . 0x80000 .


, , 0x80000 . . 0x80000 . ぀たり ! . . . . どうやっお



. os/bootloader/ext/layout.ld , , 0x4000000 . , 0x80000 . kernel_address config.txt . bootloader/ext/config.txt . , . ぀たり MicroSD-.


0x80000 0x4000000 "" .


63.5 ? [small-kernels]

, , , . — . , . ?

, . macOS - /System/Library/Kernels/kernel . /mach_kernel . Linux - /boot/ vmlinuz , vmlinux bzImage . ? 63.5 ?


bootloader/src/kmain.rs . , , . const . jump_to , addr . . pi xmodem UART, , . , .


, XMODEM, ( 750 ). . — . , — . os/kernel/build/kernel.bin ttywrite . — , screen .


? [bootloader-timeout]

. ?



config.txt , !

:

kmain() 15 .

std::slice::from_raw_parts_mut .

&mut [u8] io::Write .

UPD

Source: https://habr.com/ru/post/J351774/


All Articles