tinygo-org / tinygo

Go compiler for small places. Microcontrollers, WebAssembly (WASM/WASI), and command-line tools. Based on LLVM.
https://tinygo.org
Other
15.42k stars 910 forks source link

samd21: machine.Flash.WriteAt() crashes for unaligned offset values #4355

Open mateusznowakdev opened 3 months ago

mateusznowakdev commented 3 months ago

Hi,

my program is locking up if the offset for machine.Flash.WriteAt() is not a multiple of writeBlockSize (4). This is the code:

package main

import (
    "machine"
    "time"
)

const Offset = 3

func main() {
    time.Sleep(3 * time.Second) // let minicom reconnect
    print(machine.FlashDataStart(), "\r\n")

    print("erase\r\n")
    machine.Flash.EraseBlocks(0, 1)

    print("write\r\n")
    l, _ := machine.Flash.WriteAt([]byte{12, 34}, Offset)
    print("written ", l, " bytes\r\n")

    print("read\r\n")
    buf := make([]byte, 16)
    l, _ = machine.Flash.ReadAt(buf, 0)
    print("read ", l, " bytes\r\n")
}

and the broken output. No error message is displayed even if I try to handle the returned error value.

0x00003f00                                                                                                               
erase                                                                                                                    
w

It works perfectly if Output is set to 0, 4, 8, 12, and so on.

This can be fixed by adding up to writeBlockSize-1 bytes with the value of 0xFF in front of the input slice, and updating the initial memory address for write. However, this will create a new temporary slice, being not efficient for large inputs.

Before even trying to submit the PR, I'd like to know if it's expected that user can provide such invalid offset values. Maybe panic()king or returning an error would be enough.

I've encountered the issue on both Seeed XIAOs I have. I don't know if the issue is present on other platforms such as RP2040 or STM32. But I see that the very similar pad() method is used there as well.

deadprogram commented 3 months ago

This is a characteristic of writing to flash storage in general: you can only write block by block.

it is a lot easier to used with a file system. For example I often use littlefs in the "unused" portion of the flash. See https://github.com/tinygo-org/tinyfs