Голый металлический рамный буфер Raspberry Pi не работает

#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 Спасибо за совет. В чем заключается нарушение курса? Кроме того, есть ли более простая цель, которую я мог бы понаблюдать, прежде чем пробовать видео?