-
Notifications
You must be signed in to change notification settings - Fork 2k
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
drivers/cc110x: add power off (sleep) functions #12294
Conversation
|
||
/* | ||
* Set CS pin high so the device gets de-selected, and thus | ||
* the sleep mode transition takes place |
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.
This already happens in cc110x_cmd()
which calls spi_transfer_bytes()
which de-selects the CS GPIO at the end.
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.
Oh right, I had it on a previous version, will remove it.
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.
More feedback and testing next week, I'm currently on vacation. I like the PR however very much, that feature is highly needed. 👍
|
||
cc110x_cmd(dev, CC110X_STROBE_IDLE); | ||
dev->state = CC110X_STATE_IDLE; | ||
} |
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.
The approach here seems to be unreliable to me. You could just issue the IDLE strobe and afterwards be 100% sure what the transceiver state is, as otherwise you rely on the driver state to always reflect the internal transceiver state. The driver tries to actually do this, but I would not try to rely on this when not needed
tests/driver_cc110x/sc_cc110x.c
Outdated
case 1: | ||
for (unsigned i = 0; i < CC110X_NUM; i++){ | ||
printf("Waking up CC110x #%u:\n", i); | ||
cc110x_power_on(&_cc110x_devs[i]); |
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.
This will not work, as this function was never be intended to be used that way. It will only make sure the transceiver has enough time to stabilise crystal and power, so that the following SPI transfers are working.
The function name is very unfortunate. I think the current cc110x_power_on()
should be renamed, so that the name can be used for powering on the transceiver.
I think that a call to what currently is cc110x_power_on()
and to cc110x_rx()
would be sufficient to bring the transceiver back online, provided that the configuration registers keep their content. But I'd like to check the data sheet to confrim this
tests/driver_cc110x/sc_cc110x.c
Outdated
case 1: | ||
for (unsigned i = 0; i < CC110X_NUM; i++){ | ||
printf("Waking up CC110x #%u:\n", i); | ||
cc110x_power_on(&_cc110x_devs[i]); |
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.
This will not work, as this function was never be intended to be used that way. It will only make sure the transceiver has enough time to stabilise crystal and power, so that the following SPI transfers are working.
The function name is very unfortunate. I think the current cc110x_power_on()
should be renamed, so that the name can be used for powering on the transceiver.
I think that a call to what currently is cc110x_power_on()
and to cc110x_rx()
would be sufficient to bring the transceiver back online, provided that the configuration registers keep their content. But I'd like to check the data sheet to confrim this
Before I forget: The user facing API should be in |
OK, the datasheet says that all relevant config registers retain their values during sleep mode. So waking up the transceiver could be implemented as trivial as this: int cc110x_wake_up(cc110x_t *dev) {
if (cc110x_acquire(dev) != SPI_OK) {
return -EIO;
}
cc110x_power_on(dev);
cc110x_enter_rx_mode(dev);
cc110x_release(dev);
return 0;
} But I'm not sure if this should actually be user facing API, as instead the common netdev driver interface ( const netopt_state_t sleep = NETOPT_STATE_SLEEP;
netdev_driver_t::set(NETOPT_STATE, &sleep, sizeof(sleep)); I think this way the user could use |
I'd say both are necessary. At least on my application all the netdev layer puts some overhead with very little benefit. I'm reworking the PR to reflect your comments, will push shortly. |
I was trying to add the netdev layer for this but it seems that the whole driver is not using it for several things, e.g. if I set the sleep mode with const netopt_state_t rx = NETOPT_STATE_RX;
netdev_driver_t::set(NETOPT_STATE, &rx, sizeof(rx)); So I propose I expose the direct API driver and use it on the example, and then a rework to extend the usage for netopt for the most used modes (TX, RX, IDLE, SLEEP). |
1534136
to
6f07dab
Compare
I don't think that setting other states than sleep makes sense, e.g. what data should the device send when the state is set to TX? |
Actually if you set I don't know what this is used for and setting all the other states seems odd to me too. I just copied what the other drivers were doing, but thinking about it it's probably better not to set the state if it makes no sense. |
It was originally introduced to allow for IEEE 802.15.4e (TSCH). |
(I don't know if it was ever used for that) |
I was referring to something like this which is not implemented in the same way for the cc110x. The states are set and tracked using that function. |
Not that this function is basically empty. It never sets the state with two exceptions: For the reset and for sending a preloaded frame. Before implementing this: Please keep in mind that this will break the state machine of the driver, so that significant effort (and overhead in ROM and RAM) would be needed to fix it. And so far no reason was presented on why this would be needed. So what is the whole point in this? |
So summing up: I think that only setting The following semantics make sense to me
|
OK, the discussion about how to make this feature available under a common API seems to stall this PR. It also seems that more discussion on this aspect is needed. So I think we have two options to handle this:
I'm personally fine with both options. |
I see no problem in merging this as-is and adding the netdev integration later. |
So what is the hold up? |
Well, on my side, at least a rebase and small refactoring of some things I found. I'll try to do it ASAP, but don't wait for it for this release IMHO. |
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.
Looks good to me. Two inline comments. Please squash right away.
@@ -175,3 +175,34 @@ int cc110x_set_channel(cc110x_t *dev, uint8_t channel) | |||
dev->netdev.event_callback(&dev->netdev, NETDEV_EVENT_FHSS_CHANGE_CHANNEL); | |||
return 0; | |||
} | |||
|
|||
int cc110x_wakeup(cc110x_t *dev) |
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'd rather have this called cc110x_power_on()
to match the name of cc110x_power_off()
. Maybe the existing cc110x_power_on()
function could be renamed to cc110x_low_level_power_on()
, or cc110x_init_chip()
, or ...?
if (cc110x_acquire(dev) != SPI_OK) { | ||
return -EIO; | ||
} | ||
|
||
cc110x_power_on(dev); |
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'm not sure if this is safe to do. The current cc110x_power_on()
will reconfigure the CS pin as a GPIO to signal the chip to boot up, wait for the upper bound the chip needs to boot, and than perform spi_init_cs()
again.
Calling spi_init_cs()
while the SPI interface is acquired might cause issues. Even if all SPI drivers would support this, cc110x_power_on()
takes ages. So this would block the SPI bus, which might be shared with other devices, for way longer than usual operation. This could, thus, prevent the use of the power saving features in real-time scenarios.
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.
Yeah you're right, I'll check what's the current status at this point, to see if a "reinit" is really needed.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
Contribution description
This PR attempts to re-add the sleep functions which were removed due to the driver complete rewrite. Unfortunately, I don't have the required hardware to perform an actual power consumption test. I can gladly make changes if someone has means to test the power consumption.
Testing procedure
Use the provided commands on the test application.
Issues/PRs references
Follow up #10340