#rust #raspberry-pi #raspberry-pi3 #framebuffer #bare-metal
Вопрос:
Я работал над написанием голой металлической программы для raspberry pi 3B 1.2
Я написал функцию запуска на ассемблере, которая способна вызывать функцию rust. В настоящее время я пытаюсь инициализировать и нарисовать один цвет в буфере кадров. Когда я пытаюсь это сделать и запускаю свой pi, градиент по умолчанию перестает отображаться, и экран становится черным. Однако больше ничего не видно. Есть ли причина, по которой это так?
Вот моя функция запуска:
pub extern "C" fn start() {
let fb = gpu::init();
if let Ok(fbi) = fb {
fbi.draw();
}
}
Вот мое gpu.rs
досье:
//! This module provides an interface to the raspberry pi's built in gpu
use super::mmio;
const MBOX_BASE_OFFSET: usize = 0x0000b880;
pub fn init() -> Result<FBInfo, ()>{
let fb_info = FBInfo {
width: 1920,
height: 1080,
v_width: 1920,
v_height: 1080,
pitch: 0,
bit_depth: 16,
x_offset: 0,
y_offset: 0,
ptr: 0,
size: 0,
};
let gpu_channel = Channel::new(0).unwrap();
unsafe {
let fbi_ptr = amp;fb_info as *const FBInfo;
gpu_channel.write(fbi_ptr as u32 0x40000000)
}
if gpu_channel.read() == 0 {Ok(fb_info)} else {Err(())}
}
fn wait_util_ready() {
loop {
//wait until mailbox is ready
let status = MailboxRegister::Status.read();
if status amp; 0x80000000 == 0 {
break;
}
}
}
pub struct Channel{
number: u32,
}
impl Channel {
const CHANNELS: u32 = 7;
pub fn new(number: u32) -> Result<Self, ()> {
if number < Channel::CHANNELS {Ok(Channel { number: number} )} else { Err(()) }
}
pub fn read(amp;self) -> u32 {
loop {
wait_util_ready();
let value = mmio::read_at_offset(MBOX_BASE_OFFSET MailboxRegister::Read as usize);
if value amp; 0b1111 == self.number {
return value;
}
}
}
pub fn write(amp;self, value: u32) {
wait_util_ready();
mmio::write_at_offset(value self.number, MBOX_BASE_OFFSET MailboxRegister::Write as usize)
}
}
pub enum MailboxRegister {
Read = 0,
Poll= 16,
Sender = 20,
Status = 24,
Configuration = 28,
Write = 32
}
impl MailboxRegister {
pub fn read(self) -> u32 {
mmio::read_at_offset(MBOX_BASE_OFFSET self as usize)
}
}
#[repr(align(4))]
pub struct FBInfo {
width: u32,
height: u32,
v_width: u32,
v_height: u32,
pitch: u32,
bit_depth: u32,
x_offset: u32,
y_offset: u32,
ptr: u32,
size: u32,
}
impl FBInfo {
pub fn draw(amp;self) {
let color: u16 = 0xff;
loop {
let mut current_pxl = self.ptr;
for y in 0..self.v_height {
for x in 0..self.v_width {
unsafe {
core::ptr::write_volatile((current_pxl as *mut u16), color);
}
current_pxl = 2
}
}
}
}
}
а вот мое mmio.rs
досье:
pub const MMIO_START: usize = 0x3F000000;
pub fn write_at_offset(data: u32, offset: usize) {
unsafe {
core::ptr::write_volatile((MMIO_START offset) as *mut u32, data);
}
}
pub fn read_at_offset(offset: usize) -> u32 {
unsafe {
core::ptr::read_volatile((MMIO_START offset) as *const u32)
}
}
Любая помощь будет принята с благодарностью.
Изменить: Вот разборка скомпилированной программы:
Disassembly of section .rodata.cst16:
0000000000000000 <.rodata.cst16>:
0: 00000780 udf #1920
4: 00000438 udf #1080
8: 00000780 udf #1920
c: 00000438 udf #1080
Disassembly of section .rodata.cst8:
0000000000000010 <.rodata.cst8>:
10: 00000000 udf #0
14: 00000010 udf #16
Disassembly of section .text.boot:
0000000000000018 <_start>:
18: d53800a0 mrs x0, mpidr_el1
1c: 92401c00 and x0, x0, #0xff
20: b4000040 cbz x0, 28 <master>
24: 1400000b b 50 <hang>
0000000000000028 <master>:
28: 58000180 ldr x0, 58 <hang 0x8>
2c: 580001a1 ldr x1, 60 <hang 0x10>
30: 14000001 b 34 <bss_init>
0000000000000034 <bss_init>:
34: eb01001f cmp x0, x1
38: 54000060 b.eq 44 <enter_rust> // b.none
3c: f900001f str xzr, [x0]
40: 91002000 add x0, x0, #0x8
0000000000000044 <enter_rust>:
44: 5800013e ldr x30, 68 <hang 0x18>
48: 910003df mov sp, x30
4c: 94001020 bl 40cc <start>
0000000000000050 <hang>:
50: 14000000 b 50 <hang>
54: d503201f nop
58: 00000070 udf #112
5c: 00000000 udf #0
60: 00000070 udf #112
64: 00000000 udf #0
68: 00004070 udf #16496
6c: 00000000 udf #0
Disassembly of section .text._ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E:
0000000000004070 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E>:
4070: b9400c09 ldr w9, [x0, #12]
4074: 34000069 cbz w9, 4080 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x10>
4078: 52801fe8 mov w8, #0xff // #255
407c: 14000003 b 4088 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x18>
4080: 14000000 b 4080 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x10>
4084: b9400c09 ldr w9, [x0, #12]
4088: b940080b ldr w11, [x0, #8]
408c: 34ffffe9 cbz w9, 4088 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x18>
4090: 34ffffeb cbz w11, 408c <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x1c>
4094: b940200a ldr w10, [x0, #32]
4098: 2a1f03ec mov w12, wzr
409c: 340000cb cbz w11, 40b4 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x44>
40a0: 2a0a03ed mov w13, w10
40a4: 7100056b subs w11, w11, #0x1
40a8: 1100094a add w10, w10, #0x2
40ac: 790001a8 strh w8, [x13]
40b0: 54ffff81 b.ne 40a0 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x30> // b.any
40b4: 1100058c add w12, w12, #0x1
40b8: 6b09019f cmp w12, w9
40bc: 54fffe40 b.eq 4084 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x14> // b.none
40c0: b940080b ldr w11, [x0, #8]
40c4: 35fffeeb cbnz w11, 40a0 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x30>
40c8: 17fffffb b 40b4 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E 0x44>
Disassembly of section .text.start:
00000000000040cc <start>:
40cc: d10183ff sub sp, sp, #0x60
40d0: 90ffffe8 adrp x8, 0 <_start-0x18>
40d4: 90ffffe9 adrp x9, 0 <_start-0x18>
40d8: 3dc00100 ldr q0, [x8]
40dc: fd400921 ldr d1, [x9, #16]
40e0: 52971308 mov w8, #0xb898 // #47256
40e4: 72a7e008 movk w8, #0x3f00, lsl #16
40e8: 3d800fe0 str q0, [sp, #48]
40ec: fd0023e1 str d1, [sp, #64]
40f0: a904ffff stp xzr, xzr, [sp, #72]
40f4: b9400109 ldr w9, [x8]
40f8: 37ffffe9 tbnz w9, #31, 40f4 <start 0x28>
40fc: 9100c3e9 add x9, sp, #0x30
4100: 52a8000a mov w10, #0x40000000 // #1073741824
4104: 0b0a0129 add w9, w9, w10
4108: b9000909 str w9, [x8, #8]
410c: b9400109 ldr w9, [x8]
4110: 37ffffe9 tbnz w9, #31, 410c <start 0x40>
4114: b85e8109 ldur w9, [x8, #-24]
4118: 72000d3f tst w9, #0xf
411c: 54ffff81 b.ne 410c <start 0x40> // b.any
4120: 34000069 cbz w9, 412c <start 0x60>
4124: 910183ff add sp, sp, #0x60
4128: d65f03c0 ret
412c: ad4187e0 ldp q0, q1, [sp, #48]
4130: f9402be8 ldr x8, [sp, #80]
4134: 9100c3e0 add x0, sp, #0x30
4138: ad0007e0 stp q0, q1, [sp]
413c: f90013e8 str x8, [sp, #32]
4140: ad0187e0 stp q0, q1, [sp, #48]
4144: f9002be8 str x8, [sp, #80]
4148: 97ffffca bl 4070 <_ZN8graph_os8platform6raspi33gpu6FBInfo4draw17h1a3de04fef86caf4E>
414c: d4200020 brk #0x1
Комментарии:
1. вы сделали то же самое в C и это сработало? вы проверили разборку, чтобы убедиться, что она делает то, что вы думаете
2. @old_timer Я не пробовал это в C, но я использовал курс выпечки pi в качестве руководства. Я добавил разборку в пост.
3. курс выпечки pi нарушен. вам нужно проводить по одному эксперименту за раз. ржавчина-это эксперимент. были ли вы успешны в изучении языка ассемблера на курсе pi?
4. и, может быть, попробовать что-нибудь попроще, чем видео. Добились ли вы успеха в других вещах, используя rust baremetal для этой платформы, прежде чем попробовать почтовые ящики?
5. @old_timer Спасибо за совет. В чем заключается нарушение курса? Кроме того, есть ли более простая цель, которую я мог бы понаблюдать, прежде чем пробовать видео?