Description
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);