-
Notifications
You must be signed in to change notification settings - Fork 5
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
Add object type "memory" #47
Comments
Hi, thanks for opening the issue! First off, this proposal would work for the usecase you're working on. See, a memory interface is quite high level. And for chips like most EEPROMs, it doesn't directly map to the interface the chips provide. So if you create a driver for an EEPROM, what does it look like? Also, you mention erase. For NOR-flash that would be required too. So that's also difficult to solve. Ideally we'd not force an erase implementation for chips that don't need it. Add to that, that I'm not entirely happy with the current traits: rust-embedded-community/embedded-storage#58 So, what can we do? I think it'd be better to extend the possibilities for commands so they can carry data buffer slices. Then you could have a write command with an address and have the user give the bytes that need to be written. Maybe something like this: "Write": {
"type": "command",
"address": 5,
"input_buffer": true, <== New
"size_bits_in": 32,
"fields_in": {
"address": {
"base": "uint",
"start": 0,
"end": 32
}
},
} device.write().dispatch(|data| data.set_address(1234), &[0, 1, 2, 3, 4, 5]).unwrap(); Thoughts? |
In my opinion the commands are not the best way to access memory if the memory feature is not added. Its still a workaround. Instead I would prefer access to the interface with a mutable reference. This is already possible with the method "interface" on the device driver struct. For my case i can add a method "write_eeprom" and "read_eeprom". |
I'm not sure why you think having commands with buffer data is a workaround. For example, in this datasheet of your device: https://www.st.com/resource/en/datasheet/st25dv04k.pdf They look like commands, and in the datasheet they're called commands too. If we had commands with buffer data you could implement the interface like: i2c.transaction(DEV_ID, &mut [
Operation::Write(&[request_flags, command_address]),
Operation::Write(command_data), // The fieldset containing the first block number and the number of blocks
Operation::Write(command_buffer), // The slice of bytes the user provides
Operation::Write(&calculated_crc.to_le_bytes()),
]).unwrap(); This is modeled exactly how the datasheet specifies. I don't know what part of this would be a workaround. To me this seems like the proper solution. The problem I have with the memory interface isn't that it wouldn't your problem. It would! My problem is that it's not actually modeling what the device is doing. Maybe I'm wrong, but it seems like your desire is for a high level interface while this toolkit only really generates a low level interface. For the memory interface, you'd have to implement some commands from scratch which is exactly the thing this toolkit is trying to avoid. Instead, the intended use is create an easy to use high level layer on top of the generate low level driver.
That's completely fine and good. In my S2-LP driver I have separated the low level parts from the high level parts. The high level struct contains the low level generated struct: This allows better modelling of the functionality for this chip. You might want to do the same maybe. |
The section you referred to is for the RF access. I'm only modelling the I2C access part. The ST25DV is a dynamic NFC tag where you can access the EEPROM via I2C while at the same time a NFC reader can access the EEPROM via RF. The RF side works with commands where a command to access the EEPROM would make sense. For the I2C access the EEPROM memory is the same as a big register with 64K of consecutive bytes. So reading the first byte of the EEPROM at address 0x0000 or reading the first byte of a register (for example EH_CTRL_Dyn) at 0x2002 would look exactly the same apart from the address. So:
Since the I2C interface to the IC only knows memory addresses it would make sense for me to have a low-level interface to the EEPROM memory as I described initially. The high level layer on top would then consider additional things like the I2C password or the user memory areas. I hope I described my thoughts well enough. I still need to get better at explaining my thoughts. |
Ah ok, now I see. It's probably not just you. I've been sick for a couple of days, so my thinking isn't entirely straight haha. I'll take some time to think about how best to model this and look around how other people tend to solve this. |
While working on the driver I found 1 difference between the registers and the eeprom memory. After writing a byte to a eeprom address you have to wait 5ms for the data to be written. This is not the case for registers. So they are not identical from the driver perspective. |
Ah yes. Usually for eeproms or flash there's a status register somewhere with a 'busy' bit that you're supposed to poll. Btw, I'm coming around on the idea of adding this. Though probably the name would become 'region' or 'memregion' or something like that. The biggest concern I have now is whether there's enough justification for adding it. I mean, what would the toolkit do for you that would not be straightforward when doing it by hand? |
As far as I understand the documentation there is no busy bit somewhere but the IC just doesn't acknowledge on the i2c bus if you try to write data while it is still writing to the EEPROM. There is also a section about polling on ack. Initially I thought that I could only access the EEPROM if it was declared in the device driver. But while implementing the driver I found out that I can access it via the mutable reference to the interface. So for my implementation there is no hard need for this. Though I would say it is nicer to have everything declared in the device driver. When someone looks at the code they can find everything in one place. |
Motivation
The device ST25DV has a user memory area that is up to 64kBytes big. That means setting it as a big register is not feasible since this would require 64kByte on the stack to read or write it. A buffer also doesn't make sense in this case.
Design
In my opinion a new field type "memory" would make sense. As discussed here I want to describe how I think this field type could look:
How does the user specify it
It would share many similarities to a register. So the following attributes would be identical:
The following should be different/new:
What should the generated code be like to use
I'm orienting myself on embedded-storage here.
Writing should look like this:
Reading should look like this:
This is basically 1:1 embedded-hal NorFlash (docs) without the erase stuff. Maybe the erase stuff also makes sense. I don't know if there are any devices which would require this.
Interface trait
The interface trait would also look very similar to NorFlash from embedded-hal:
The text was updated successfully, but these errors were encountered: