-
Notifications
You must be signed in to change notification settings - Fork 146
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
I2C HAL ideas #401
Comments
An alternative design adds a parameter to the Master_* routines to send or not to send the Stop condition at the end (defaulting to true). |
If we want to reuse basic routines for sending and receiving for master and for slave implementation we need to have simple send and receive routines and a separate stop routine anyway |
I love the suggestion for procedure Detect_Connection I would like to see Slave_* functions/procedures. Having said this, and I only want to be an I2C slave, then I need to implement the Master* just for the sake of it. Could it be maybe better to have: Just throwing ideas around. |
I'm in favor of having separate child packages for Slave ( I never programmed a slave and don't know what is needed. We can probably copy the idea from C or Python APIs. |
regarding slave: I found some C code which claims to work, but I just did not have the time yet, but it is on my to do list |
If we're going to consider breaking HAL compatibility, forcing every implementation and consumer of the HAL drivers to update, I think there are a few other things to keep in mind. We can leverage Alire's crate versioning to differentiate a 1.x branch of HAL from 0.x, or we could just create a new The HAL interfaces currently cannot be verified by gnatprove as they use constructs not allowed in SPARK. I think at least making this an option for HAL implementations is a worthwhile goal. I'd love to see a test suite similar to ACATS, but for HAL driver implementations. I don't know exactly what this would look like, but I'm imagining a hardware-in-the-loop solution with two microcontrollers connected to each other, one running tests, the other verifying that it's sending the right signals at the right time. It may be possible to do this entirely within qemu, which would be great for automated integration testing. Specific to the proposed I2C interface changes, I don't think removing support for 10 bit addresses is a good idea. While uncommon, these devices do exist and most I2C controllers support them well. The I do wonder if there is space for a higher level In summary, I think breaking the HAL interface is a bigger challenge than this proposal makes it seem and we should consider the broader implications of these changes before diving in with diffs and pull requests. |
Breaking the the interface should come as a last resort. But the interface as it is has flaws that can easily be mitigated by some documenting comments. I have my proposal now in hal-i2c.ads and hal-i2c-master.ads.
As for the addresses, the 7bit addresses and 10bit addresses are separate address spaces. There can be devices with the 10bit address 0x40 and with the 7bit address 0x40 on the same bus. The current interface does not permit to distinguish between the two. We either need an additional parameter I2C_Address_Size or have two distinct address types and overload the routines appropriately. |
I do agree, that breaking existing code should be the last option. I would strongly suggest, that the crate versioning should help here. But this requires very strict references in the client code using HAL. I learnt to my surprise, that bumping up a version seems to be not fully followed for all changes, which is not something I would recommend for real life systems. So maybe this is a chance to help the community to adapt strict versioning (which should always be the case to begin with, even removing a space shall be a patch level version very like the Maven world in Java with POM.XML where we use alire.toml as an equivalent) |
I think the ecosystem is still small enough to make this kind of changes. And as you said, leveraging on semantic versioning to make this easier for everyone. I am against a
I agree that this is a worthwhile goal, I don't know which part of the current
That's also a good idea, difficult to put in place in my opinion but you already did a great job testing the
The problem with QEMU is that adding support for a given MCU is a lot of work. I think the hardware way and the RP2040 with PIO makes it even more doable. I see a
Or maybe the other way around, the
Then the
We could provide not only the
I agree, and the HAL should stay as low level as possible in my opinion. Close to the protocol.
Sound like this would rely a lot on dynamic memory, it is probably doable but I see this as a library built on top of
I am afraid it will be impossible to make this MCU agnostic. What we could do however, is to define an optional power management interface. package HAL.Power is
type Instance is interface;
subtype Class is Instance'Class;
type State_Kind is (Power_Up, Power_Down, Suspended);
function Support (This : Instance; Kind : State_Kind) return Boolean is abstract;
function State (This : Instance) return State_Kind is abstract
with Post'Class => This.Support (State'Result);
procedure Up (This : in out Instance) is abstract
with Pre'Class => This.Support (Power_Up),
Post'Class => This.State = Power_Up;
procedure Down (This : in out Instance) is abstract
with Pre'Class => This.Support (Power_Down),
Post'Class => This.State = Power_Down;
procedure Suspend (This : in out Instance) is abstract
with Pre'Class => This.Support (Suspended),
Post'Class => This.State = Suspended;end HAL.Power; type I2C_Controller is new HAL.I2C.I2C_Port and HAL.Power.Instance with private; |
@Fabien-Chouteau I want to perform an I2C controller (master) test I will test your I2C controller driver Send 3 bytes to device 16#42# |
Using
Full output here: https://gist.github.com/JeremyGrosser/b805aab9f3f94533679b5453e0884afa |
Right, you can't even declare the access type ^^ |
I want to return to the discussion about the I2C addresses. There are two distinct address spaces (7bit and 10bit addresses) and there are two common ways to store 7bit addresses, either in the lower 7 bits 6:0 or in the upper 7 bits 7:1 of a byte. It is the same information, just differently represented in a byte. The latter is sometimes called a 8bit address. subtype I2C_Address is UInt10; I found no comment or documentation if that is intended to be a 7, 8, or 10bit address. I only learned by looking at the code in -- 7 and 10-bit addresses are distinct types
subtype I2C_7bit_Address is UInt7 range 8 .. 16#77#;
-- 8-bit addresses are actually 7-bit addresses shifted by 1 bit
subtype I2C_8bit_Address is UInt8 range 16#10# .. 16#EE#;
subtype I2C_10bit_Address is UInt10;
subtype I2C_Address is I2C_8bit_Address;
-- for backward compatibility to hal-0.3.0 There a now several design choices:
type I2C_Address_Kind is (I2C_7bit, I2C_8bit, I2C_10bit);
procedure Transmit
(This : in out I2C_Master_Port;
Addr : I2C_Address;
Data : I2C_Data;
Status : out I2C_Status;
Addr_Kind : I2C_Address_Kind := I2C_8bit;
Timeout : Natural := 1000) is abstract;
procedure Transmit
(This : in out I2C_Master_Port;
Addr : I2C_7bit_Address;
Data : I2C_Data;
Status : out I2C_Status;
Timeout : Natural := 1000) is abstract;
procedure Transmit
(This : in out I2C_Master_Port;
Addr : I2C_8bit_Address;
Data : I2C_Data;
Status : out I2C_Status;
Timeout : Natural := 1000) is abstract;
procedure Transmit
(This : in out I2C_Master_Port;
Addr : I2C_10bit_Address;
Data : I2C_Data;
Status : out I2C_Status;
Timeout : Natural := 1000) is abstract; These two alternatives can have tree variants: The advantage of alternative 1) is that it is the least intrusive. I don't like it as it weakens the type system, you have to specify the actual type in a additional parameter. That is not Ada-style. Alternative 2 is more work but we get strong typing. As for the variants, my favorite is c). That is what most libraries and documents do |
I am worried about exponential number of sub-programs. |
I don't think that limiting the address choice to a start procedure helps a lot. The very first byte must already encode in bit 0 if the following action is either a read or a write. That alone requires us to have at least the four cases
|
I think the hal-i2c.ads lacks some comments on how to use it. Here are some ideas for modifications:
The text was updated successfully, but these errors were encountered: