RPI pico 以编程方式写入闪存

问题描述 投票:0回答:1

我正在尝试为 Rust 中的 pico 编写一个程序,该程序需要在可能的关闭之间保存数据。它将与程序一起装入闪存中,并且闪存是“根据互联网”可写的。

我复制了一些大使馆 pico 模板存储库并更改了

memory.x
以包含大小为 1M 的部分
.log

MEMORY {
    BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
    FLASH : ORIGIN = 0x10000100, LENGTH = 1M - 0x100
    LOG   : ORIGIN = 0x10100000, LENGTH = 1M
    RAM   : ORIGIN = 0x20000000, LENGTH = 256K
}

EXTERN(BOOT2_FIRMWARE)

SECTIONS {
    /* ### Boot loader */
    .boot2 ORIGIN(BOOT2) : {
        KEEP(*(.boot2));
    } > BOOT2
    /* Data log */
    .log : {
        *(.log);
       . = ALIGN(4);
    } > LOG
} INSERT BEFORE .text;

然后在我的代码中

#[link_section = ".log"]
static mut LOG: MaybeUninit<[u8; 1 << 20]> = MaybeUninit::uninit();

fn foo() {
    let log = unsafe { LOG.assume_init_mut() };
}

但是从行为和调试中我可以看出,分配给数组没有任何作用。该部分最初被清零,即使在分配后也保持这种状态。

我已经通过一个简单的测试函数验证了这一点,该函数检查内存是否可写。

fn test_writable(log: &mut [u8]) -> bool {
    let prev = log[0];
    let masked = prev ^ 0xb5;
    log[0] = masked;
    if log[0] == masked {
        log[0] = prev;
        true
    } else {
        if log[0] == prev {
            error!("Log is not writable");
        } else {
            error!("Log writing is incorrect. Prev: {}, expected: {}, current: {}", prev, masked, log[0]);
        }
        false
    }
}

我使用

MaybeUninit
是否错误,是内存映射错误还是其他原因?

rust embedded raspberry-pi-pico memory-mapping
1个回答
0
投票

RPIPico 会将其闪存内存映射到“正常”地址以供读取。对于写入,该闪存不能直接寻址。

您需要使用API函数

flash_range_erase (offset, size)
flash_range_write (offset, buffer, size)

先擦除Flash中的某个块,然后再写入。

让事情变得有点复杂的是,显然这两个函数只有在禁用中断的情况下才能正常工作。另外,您需要确保不会擦除/写入保存程序的闪存区域。

RPi 2040 上的闪存必须以 4k 块进行处理 - 这意味着,您必须确保将下一个块写入闪存中程序“后面”的下一个地址,该地址可以被 4096 整除。程序地址由库在

flash_binary_end
变量中方便地提供(这是一个绝对地址,而上述两个函数需要相对于闪存的 start 的偏移量,可以通过常量
XIP_BASE
找到) .

© www.soinside.com 2019 - 2024. All rights reserved.