8000 `machine.BlockDevice` refactor · Issue #4857 · tinygo-org/tinygo · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

machine.BlockDevice refactor #4857

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
soypat opened this issue Apr 12, 2025 · 1 comment
Open

machine.BlockDevice refactor #4857

soypat opened this issue Apr 12, 2025 · 1 comment
Labels
enhancement New feature or request

Comments

@soypat
Copy link
Contributor
soypat commented Apr 12, 2025

This is a discussion issue meant to center around ways to make the current BlockDevice HAL in machine better.

Today
// BlockDevice is the raw device that is meant to store flash data.
type BlockDevice interface {
	// ReadAt reads the given number of bytes from the block device.
	io.ReaderAt

	// WriteAt writes the given number of bytes to the block device.
	io.WriterAt

	// Size returns the number of bytes in this block device.
	Size() int64

	// WriteBlockSize returns the block size in which data can be written to
	// memory. It can be used by a client to optimize writes, non-aligned writes
	// should always work correctly.
	WriteBlockSize() int64

	// EraseBlockSize returns the smallest erasable area on this particular chip
	// in bytes. This is used for the block size in EraseBlocks.
	// It must be a power of two, and may be as small as 1. A typical size is 4096.
	EraseBlockSize() int64

	// EraseBlocks erases the given number of blocks. An implementation may
	// transparently coalesce ranges of blocks into larger bundles if the chip
	// supports this. The start and len parameters are in block numbers, use
	// EraseBlockSize to map addresses to blocks.
	EraseBlocks(start, len int64) error
}

Issues

  • ReaderAt/WriteAt methods is not the correct HAL, as is indicated by sister methods which operate on a block indexing scheme.
    • This means that all BlockDevice implementations must reimplement block to address indexing conversion and checks leading to lots of duplicated code between reimplementations
    • No access to actual block reading HAL for when block read/write is what the user wants
    • Obfuscates the cost of a read operation for users who actually are unaware what a block device actually is
  • Same goes for Size, a more correct approach would be NumBlocks/BlockCount instead.
  • Block sizes can be represented as int type since they must fit into main memory or else the API is completely unusable since a single block read results in OOM

Proposal

The actual meat of the proposal is replacing with the following abstraction. dst and data buffers should be a multiple of the block size for efficient use of the block device. WE can have a BlockDeviceOperator type that wraps a BlockDevice that implements reading less than multiple of a block which I believe would be a good design practice- it simplifies all BlockDevice implementations and puts all that complexity in one single place making maintenance much easier on developers.

type BlockReader interface {
	ReadBlocks(dst []byte, startBlock int64) (int, error)
}

type BlockWriter interface {
	WriteBlocks(data []byte, startBlock int64) (int, error)
}

// BlockDevice is the basic interface that must be implemented for a device to function properly.
type BlockDevice interface {
	BlockReader
	BlockWriter
	EraseBlocks(startBlock, numBlocks int64) error
	BlockSize() int
        EraseBlockSize() int
	BlockCount() int64
}

Sub Proposals

These are just observations on things that could be better

  • Move BlockDevice into an internal package, exported one should live in tinygo drivers repo
@aykevl
Copy link
Member
aykevl commented Apr 16, 2025

The flash devices I've seen allow reading and writing at arbitrary offsets. This allows for example to erase a whole block and only incrementally write parts of it (this is done in https://github.com/micropython/micropython/blob/master/ports/nrf/modules/os/microbitfs.c for example, which I wrote/ported a looong time ago before I started TinyGo).

Do you have examples of flash block devices that do not allow reads and writes to individual bytes?
Also, I don't think mapping these sizes is very complicated. Do you have code samples that show it leads to complicated code?

@deadprogram deadprogram added the enhancement New feature or request label Apr 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants
0