Skip to content

Question about aarch64 memory access #10

Closed
@binaryfields

Description

@binaryfields

I am running into an interesting issue where a slightly modified version of 05_uart0 example keeps hanging on my rpi3 hardware.

I modified the example and for clarify moved code to get the board serial number into its own function. The function takes a slice (&mut [u32]) to fill in the part of mbox buffer that represents request data and uses it to collect response output.

The issue I'm running into is around how my slice gets copied into the mbox buffer.

If I simply do a loop and iterate over slice values, it works fine.

    for i in 0..data.len() {
       mbox.buffer[5 + i] = data[i];
    }

However, if I use rust's copy_from_slice function, the program hangs

mbox.buffer[5..7].copy_from_slice(&data[0..2]);

This feels to me like some unaligned access issue but I'm not sure how to further debug it. Is there anything I'm doing wrong when trying to use copy_from_slice?

Thanks
-Seb

Here is the complete modified source code for main.rs.

#![no_std]
#![no_main]
#![feature(asm)]

const MMIO_BASE: u32 = 0x3F00_0000;

mod gpio;
mod mbox;
mod uart;

use core::sync::atomic::{compiler_fence, Ordering};

fn kernel_entry() -> ! {
    let mut mbox = mbox::Mbox::new();
    let uart = uart::Uart::new();

    // set up serial console
    match uart.init(&mut mbox) {
        Ok(_) => uart.puts("\n[0] UART is live!\n"),
        Err(_) => loop {
            unsafe { asm!("wfe" :::: "volatile") }; // If UART fails, abort early
        },
    }

    uart.puts("[1] Press a key to continue booting... ");
    uart.getc();
    uart.puts("Greetings fellow Rustacean!\n");

    let mut data = [0, 0];
    let serial_avail = get_serial(&mut mbox, &mut data[0..2]);
    if serial_avail {
        uart.puts("[i] My serial number is: 0x");
        uart.hex(data[1]);
        uart.hex(data[0]);
        uart.puts("\n");
    } else {
        uart.puts("[i] Unable to query serial!\n");
    }

    // echo everything back
    loop {
        uart.send(uart.getc());
    }
}

#[inline(never)]
fn get_serial(mbox: &mut mbox::Mbox, data: &mut [u32]) -> bool {
    // get the board's unique serial number with a mailbox call
    mbox.buffer[0] = 8 * 4; // length of the message
    mbox.buffer[1] = mbox::REQUEST; // this is a request message
    mbox.buffer[2] = mbox::tag::GETSERIAL; // get serial number command
    mbox.buffer[3] = 8; // buffer size
    mbox.buffer[4] = 8;
    mbox.buffer[5..7].copy_from_slice(&data[0..2]);
    //for i in 0..data.len() {
      //  mbox.buffer[5 + i] = data[i];
    //}
    //mbox.buffer[5] = data[0]; // clear output buffer
    //mbox.buffer[6] = data[1];
    mbox.buffer[7] = mbox::tag::LAST;

    // Insert a compiler fence that ensures that all stores to the
    // mbox buffer are finished before the GPU is signaled (which is
    // done by a store operation as well).
    compiler_fence(Ordering::Release);

    // send the message to the GPU and receive answer
    match mbox.call(mbox::channel::PROP) {
        Err(_) => false,
        Ok(()) => {
            //data[0..2].copy_from_slice(&mbox.buffer[5..7]);
            for i in 0..data.len() {
                data[i] = mbox.buffer[5 + i];
            }
            //data[0] = mbox.buffer[5];
            //data[1] = mbox.buffer[6];
            true
        },
    }
}
raspi3_boot::entry!(kernel_entry);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions