feat: docs & ARCH 2.2, 2.3, 2.4

This commit is contained in:
Faynot
2026-07-07 16:40:41 +03:00
parent c092a81331
commit 1bfde637d0
50 changed files with 5113 additions and 1823 deletions

View File

@@ -0,0 +1,88 @@
# Подсистема отладки: концептуальная модель
## Два канала вывода
Ядро имеет два параллельных канала для отладки:
1. **Экранный (framebuffer console)** — через `tty::Console`.
- Использует PSF2-шрифты.
- Цветной вывод (зелёный/жёлтый/красный для Info/Warn/Error).
- Медленнее, но визуально нагляднее.
2. **Serial port (COM1)** — через `debug::serial`.
- Текстовый вывод с ANSI escape codes.
- Работает через QEMU/KVM serial console.
- Быстрее, может быть перенаправлен в файл.
## LogLevel — уровни логирования
```rust
pub enum LogLevel {
Info, // Зелёный на экране, зелёный в serial
Warn, // Жёлтый
Error, // Красный
}
```
Каждый уровень имеет:
- `serial_color_code()` — ANSI escape code для serial.
- `console_color()` — RGB значение для framebuffer.
## Макросы
```rust
// Основной макрос
log!(console, level, module, format_args...)
// Специализированные
info!(console, module, format_args...)
warn!(console, module, format_args...)
error!(console, module, format_args...)
```
**Формат вывода на экран:**
```
[ LOG ] <module> | <message>
```
**Формат в serial:**
```
GREEN[ LOG] RESET <module> | <message>
```
## Цветовое кодирование
| Уровень | Экран (RGB) | Serial (ANSI) |
|---------|-------------|---------------|
| Info | 0x00FF00 | `\x1b[32m` (green) |
| Warn | 0xFFFF00 | `\x1b[33m` (yellow) |
| Error | 0xFF0000 | `\x1b[31m` (red) |
| Текст | 0xFFFFFF (white) | `\x1b[0m` (reset) |
## Использование в kmain()
```rust
// После инициализации serial
debug::serial::init_global();
// После инициализации console
info!(console, "BOOT", "LIS4 Kernel Starting...");
info!(console, "MEM", "BitmapPMM initialized.");
info!(console, "LAPIC", "Local APIC initialized.");
```
## Архитектура
```
┌──────────────┐ ┌───────────────────┐
│ kmain() │────►│ log!() macro │
└──────────────┘ └────────┬──────────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Экран │ │ Serial │ │ Паника │
│ Console │ │ COM1 │ │ Handler │
│ (tty.rs) │ │(serial.rs)│ │(main.rs) │
└──────────┘ └──────────┘ └──────────┘
```

110
kernel/docs/debug/serial.md Normal file
View File

@@ -0,0 +1,110 @@
# Serial Port драйвер: `serial.rs`
## Назначение
Драйвер последовательного порта (UART 16550, COM1) для отладочного
вывода. Позволяет видеть сообщения ядра через QEMU serial console,
minicom, screen и т.д.
## Аппаратная модель
COM1 расположен по портам ввода-вывода `0x3F8`-`0x3FF`:
| Порт | Регистр | Назначение |
|------|---------|------------|
| 0x3F8 | DATA | Чтение/запись данных |
| 0x3F9 | IER | Interrupt Enable |
| 0x3FA | IIR/FCR | Interrupt ID / FIFO Control |
| 0x3FB | LCR | Line Control |
| 0x3FC | MCR | Modem Control |
| 0x3FD | LSR | Line Status |
| 0x3FE | MSR | Modem Status |
## Инициализация
```rust
pub unsafe fn init() -> Self {
let port = Self::COM1; // 0x3F8
outb(port + 1, 0x00); // IER = 0 (disable interrupts)
outb(port + 3, 0x80); // LCR DLAB=1 (enable baud rate programming)
outb(port + 0, 0x03); // Divisor LSB = 3 (38400 baud)
outb(port + 1, 0x00); // Divisor MSB = 0
outb(port + 3, 0x03); // LCR = 8N1 (8 bits, No parity, 1 stop)
outb(port + 2, 0xC7); // FCR = enable FIFO, clear, 14-byte threshold
outb(port + 4, 0x0B); // MCR = DTR+RTS+OUT2 (enable IRQ + handshake)
SerialPort(port)
}
```
### Детали конфигурации
1. **IER = 0**: отключаем прерывания UART (TODO: включить для RX).
2. **DLAB = 1**: разрешаем программирование делителя бода.
3. **Divisor = 3**: при тактовой 1.8432 MHz → 115200 / 3 = 38400 бод.
4. **LCR = 0x03**: 8N1 — 8 бит данных, нет чётности, 1 стоп-бит.
5. **FCR = 0xC7**: enable FIFO, clear both FIFOs, trigger at 14 bytes.
6. **MCR = 0x0B**: DTR=1, RTS=1, OUT2=1 (необходимо для IRQ на ISA шине).
## Отправка байта
```rust
fn is_transmit_empty(&self) -> bool {
unsafe { (inb(self.0 + 5) & 0x20) != 0 } // LSR bit 5 = Transmitter Holding Register Empty
}
pub fn send(&self, data: u8) {
while !self.is_transmit_empty() {} // Ждём, пока UART готов
unsafe { outb(self.0, data); }
}
```
## fmt::Write реализация
```rust
impl core::fmt::Write for SerialPort {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for byte in s.bytes() { self.send(byte); }
Ok(())
}
}
```
## Глобальный экземпляр
```rust
static SERIAL_PORT: Locked<Option<SerialPort>> = Locked::new(None);
pub fn init_global() {
let mut guard = SERIAL_PORT.lock();
*guard = Some(unsafe { SerialPort::init() });
}
pub fn write_global(args: core::fmt::Arguments) {
let mut guard = SERIAL_PORT.lock();
if let Some(ref mut sp) = *guard {
let _ = sp.write_fmt(args);
}
}
```
`init_global()` вызывается из `kmain()` после инициализации TTY.
`write_global()` используется:
- В `log!()` макросе (через debug.rs).
- В `rust_panic()` обработчике.
- В обработчиках исключений (GPF, Double Fault, Early Exception).
## Низкоуровневый I/O
```rust
unsafe fn outb(port: u16, val: u8) {
asm!("out dx, al", in("dx") port, in("al") val,
options(nomem, nostack, preserves_flags));
}
unsafe fn inb(port: u16) -> u8 {
let res: u8;
asm!("in al, dx", out("al") res, in("dx") port,
options(nomem, nostack, preserves_flags));
res
}
```