-
Notifications
You must be signed in to change notification settings - Fork 989
usb/msc: erase blocks before writing to them #5017
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
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,6 +91,16 @@ func (m *msc) writeBlock(b []byte, lba, offset uint32) (n int, err error) { | |
return 0, invalidWriteError | ||
} | ||
|
||
// Erase the block first if needed. | ||
// Data packets arrive in order, so if we want to write to the start of a | ||
// block, that means it's the first write to this erase block and it needs | ||
// to be erased first. | ||
if uint32(blockStart)%m.blockSizeUSB == 0 { | ||
firstBlock := uint32(blockStart) / uint32(m.dev.EraseBlockSize()) | ||
numBlocks := (m.blockSizeUSB + uint32(m.dev.EraseBlockSize()) - 1) / uint32(m.dev.EraseBlockSize()) | ||
m.dev.EraseBlocks(int64(firstBlock), int64(numBlocks)) | ||
} | ||
Comment on lines
+98
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes the assumption that data is always written in full blocks, and that packets arrive sequentially. @mikesmitty can you confirm that this is true? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's how the protocol operates, yeah. A read or write command is sent from the host in a CDB packet along with the transfer length and then nothing but un-encapsulated raw data is sent/received until the transfer length is met There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this again, it might make sense to refactor the block erase logic like in #5027, then you could simplify this like so:
writeBlock() gets called when a full flash device write block is buffered and |
||
|
||
// Write the full block to the underlying device | ||
n, err = m.dev.WriteAt(b, blockStart) | ||
n -= int(blockOffset) | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably be better to leave the default blockSizeUSB here to 512 and move the new block size checking logic to
RegisterBlockDevice()
in disk.go (called a few lines below here). I put the logic around setting up the block device in there with the idea that it could be swapped out during runtime if someone wanted to.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean, you'd like to still emulate a block size of 512 even if the underlying flash has an erase block size of 4096?
I think that's a bad idea:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was more thinking in the context that it'd be unusual for TinyGo to see a device with 4k erase blocks so 512 would be a safe default, but after the unexpected edge case that just bit me with the nrf52840 buffer thing, might as well plan to handle it better
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4k is pretty common, it's what the nrf52* devices uses and IIRC also what rp2040 uses. And the code in this PR uses 512 bytes when possible anyway, so devices with a smaller erase block size can use that.