Comments (10)
I think I see what you mean. I can implement the InputPin trait on top of an Input and invert it there. I did not think about that!
from embedded-hal.
@therealprof is_low
and is_high
can certainly be useful if you actually need to figure out if the pin is grounded or not but that is usually not the case. Normally you just set the invert register to make the logic levels of the port registers make sense depending what is connected.
Lets say you have something shifting in bytes on a port. Some of the pins, for whatever reason, is inverted. Instead of adding instructions to flip some of the bits you just set the inverting register and read the bytes from the port directly.
from embedded-hal.
is_set(), is_clear(), set(), clear()?
from embedded-hal.
set/clear are nice verbs for output pins but it seems a bit unusual to talk about is_set
on an input pin. I think it's fair to just say if the input pin is_high
then it's a logic high, and if the specific MCU has inverted the sense of the pins, that means logic highs correspond to low voltages.
In other words high
/low
refer to logic states of the pins and usually that refers to voltage levels, but not on inverted pins.
from embedded-hal.
@Fulkerson It's specifically the job of a hal implementation to ensure that is_high()
yields true if the logic level on a pin is high. If there's some magic that may change the interpretation of a register read then it's the job of the implementation to translate it correctly into a high/low level.
from embedded-hal.
but that is usually not the case
I could not disagree more. That is exactly what you want. The HAL is meant to abstract the hardware so that there is a common interface translating between generic drivers and hardware. If a driver needs to know whether the voltage level on a pin is high or low it would ask for that information using the is_high()
or is_low()
method and it's the HAL implementations responsibility to reliably deliver the correct result and abstract over the fact that somehow the register is inverted.
Lets say you have something shifting in bytes on a port. Some of the pins, for whatever reason, is inverted. Instead of adding instructions to flip some of the bits you just set the inverting register and read the bytes from the port directly.
As I said: if the MCU knows that the result is inverted it's the implementations job to abstract it. If this is hardware choice (i.e. GPIO pin is inverted via external hardware) then it's the job of the application to make sure the inversion is properly accounted for.
If you really wanted to support that inversion in an hal implementation for the LPC810 (and others) you can also implement a separate InputPin
/OutputPin
state which sets this up and accounts for it in the implementation of is_low()
and is_high()
.
from embedded-hal.
@adamgreig Fair enough. I usually work higher up in the stack and not a lot with microcontrollers. On Linux embedded systems it is common to specify whether something is active high or active low and configure the port so that when the peripheral (be it a button or amplifier or whatever) is considered active (button is pressed, amplifier is powered on etc) it corresponds to a digital one.
In the long run I think it is important that the HAL clearly states what the methods are. I.e. is low
the logic or the actual state of the physical pin? Otherwise it's easy to end up with different implementations behaving differently.
from embedded-hal.
On Linux embedded systems it is common to specify whether something is active high or active low and configure the port so that when the peripheral (be it a button or amplifier or whatever) is considered active (button is pressed, amplifier is powered on etc) it corresponds to a digital one.
We're doing that, too. ;) But the interpretation of what is active or inactive is left to a specific driver or the application and not handled by the lower layers.
In the long run I think it is important that the HAL clearly states what the methods are. I.e. is low the logic or the actual state of the physical pin? Otherwise it's easy to end up with different implementations behaving differently.
Yes, that situation is actually a bit more complex than it may sound on first glance. There's plenty of discussion about the details in #29 and at least another one I can't find right now.
from embedded-hal.
I could not disagree more. That is exactly what you want. The HAL is meant to abstract the hardware so that there is a common interface translating between generic drivers and hardware. If a driver needs to know whether the voltage level on a pin is high or low it would ask for that information using the is_high() or is_low() method and it's the HAL implementations responsibility to reliably deliver the correct result and abstract over the fact that somehow the register is inverted.
I have a hard time thinking of a driver that needs to know what the actual voltage on a digital pin is. Usually a driver only care about the peripheral on the other end of the line and not what components are in the way. There are many times the electrical signal may be inverted on the way to the destination. Many times the protocol dictates how the electrical connection should look like, but it is far from always the case.
If you really wanted to support that inversion in an hal implementation for the LPC810 (and others) you can also implement a separate InputPin/OutputPin state which sets this up and accounts for it in the implementation of is_low() and is_high()
That is sort of my point! I envision myself adding a mode for InputPin
that is Inverted or something along the line which sets the INV
register appropriately but at that point I think the high/low wording becomes confusing. I am used to refer to high/low when discussing specifics of a schematic. There voltage is the only thing that matters. When translating that to code the constant inversions becomes overly complicated for my poor brain. Especially when working with lots of pins in a large code base. I would rather set up my gpios once and not having to refer to the schematics 6 months later.
We're doing that, too. ;) But the interpretation of what is active or inactive is left to a specific driver or the application and not handled by the lower layers.
That is perfectly fine for simple things like LEDs (is it active low or high?) but driver code quickly becomes very complex when adding interrupt pins to an ethernet driver or whatever, and you have to specify for each raw GPIO the driver is using if it is active high or not. Better put it in the gpio interface like with pullups and similar in my opinion.
I believe we are of the same opinion the matter. Whether a pin should invert its logic or not should be a configuration of the pin. If it is configured to be non inverting, low should be grounded. If it is configured to be inverting high should be grounded. My main argument is that I think using high and low is confusing when introducing inversion to pins.
from embedded-hal.
I have a hard time thinking of a driver that needs to know what the actual voltage on a digital pin is.
The real voltage is irrelevant. The only question is: Is it considered a high level or a low level (or is it floating/in between). There're very clear definitions for that.
Usually a driver only care about the peripheral on the other end of the line and not what components are in the way.
Exactly.
I am used to refer to high/low when discussing specifics of a schematic.
And this goes hand in hand with what the HAL does.
I would rather set up my gpios once and not having to refer to the schematics 6 months later.
Not sure what's preventing you from doing that. That's exactly how it's supposed to work: The application sets up the peripherals using the hal implementation according to the schematics and then uses them (either directly or by handing them off to some driver).
but driver code quickly becomes very complex when adding interrupt pins to an ethernet driver or whatever
How so? The whole point of the abstraction is to keep the drivers simple and generic.
A driver doesn't have to (and shouldn't!) worry about interrupts at all, that's the job of an interrupt handler which has to be platform specific anyway. But yeah, interrupts are still kind of a sad story, the setup is far too manual...
My main argument is that I think using high and low is confusing when introducing inversion to pins.
And I still don't get why. Can you link any datasheet of any active component that does not mention high or low? Any digital signal consists of high/low levels/edges so it is important to know what the current state directly at the pin is if you want to use it to work with an external component. If you have an external inversion somewhere then you'll obviously need to account for that fact in your setup but it doesn't change anything about the level directly at the pin. An is_high()
in a regular pin configuration corresponds to a logic high level you could measure with a multimeter on that very pin.
Most likely I would even argue against supporting that inversion flag on the GPIO. I can see why it exists for other languages where software signal inversion might cost instruction cycles, but in Rust any level-inverting adapter on a regular pin (which will work with any MCU) shouldn't require any additional instructions.
from embedded-hal.
Related Issues (20)
- Read not implemented for &mut [u8] HOT 1
- README: Links to LICENSE-APACHE and LICENSE-MIT are not found
- How do I share an I2c bus between tasks? HOT 1
- Implment `Clone` for async DelayNs HOT 2
- Multipin serial spi interface trait
- embedded-hal-bus no longer builds with target thumbv6m-none-eabi HOT 6
- Split embedded-can? HOT 3
- feature request: embedded_io_async::try_read HOT 2
- Upstreaming some concepts built up in `embedded-time` HOT 1
- Why was ADC removed? HOT 2
- [Discussion] Should sensor driver developers target `embedded-hal-async` only?
- Shared SPI bus between devices with different SPI modes HOT 2
- The Crate Does not Compile when the `defmt-03` Feature is Enabled HOT 4
- honor `ErrorKind::Interrupted` in `write_all()`? HOT 4
- Revisiting the possibility of including generic sensor traits HOT 1
- Generic bus traits HOT 4
- e-h-async and e-io-async broken on stable due to unexpected cfg "nightly" HOT 1
- Add `BlockDevice` trait to embedded-io HOT 1
- Clarification Needed for I2C Transaction Contract
- Error: out of range branch target (expected an integer in the range -4096 to 4095
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from embedded-hal.