Skip to content
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

Closed
wants to merge 4 commits into from

Conversation

kYc0o
Copy link
Contributor

@kYc0o kYc0o commented Sep 24, 2019

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

@kYc0o kYc0o added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: drivers Area: Device drivers labels Sep 24, 2019
@kYc0o kYc0o requested a review from maribu September 24, 2019 10:05
@miri64 miri64 changed the title Pr/add cc110x poweroff drivers/cc110x: add power off (sleep) functions Sep 24, 2019

/*
* Set CS pin high so the device gets de-selected, and thus
* the sleep mode transition takes place
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Member

@maribu maribu left a 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;
}
Copy link
Member

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

case 1:
for (unsigned i = 0; i < CC110X_NUM; i++){
printf("Waking up CC110x #%u:\n", i);
cc110x_power_on(&_cc110x_devs[i]);
Copy link
Member

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

case 1:
for (unsigned i = 0; i < CC110X_NUM; i++){
printf("Waking up CC110x #%u:\n", i);
cc110x_power_on(&_cc110x_devs[i]);
Copy link
Member

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

@maribu
Copy link
Member

maribu commented Sep 24, 2019

Before I forget: The user facing API should be in drivers/include/cc110x.h. All.other headers are for driver internal stuff. cc110x_communication.h was ment for (high level SPI) communication with the transceiver.

@maribu
Copy link
Member

maribu commented Sep 29, 2019

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 (netdev_driver_t::set() and netdev_driver_t::get()) could be used like this:

    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 ifconfig to put the device to sleep mode and wake it back up.

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 8, 2019

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.

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 8, 2019

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 netdev_driver_t::set(NETOPT_STATE, &sleep, sizeof(sleep)) I suppose there should be also something like:

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).

@kuguhome-infra kuguhome-infra force-pushed the pr/add_cc110x_poweroff branch from 1534136 to 6f07dab Compare October 8, 2019 16:18
@maribu
Copy link
Member

maribu commented Oct 8, 2019

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?

@benpicco
Copy link
Contributor

benpicco commented Oct 8, 2019

what data should the device send when the state is set to TX?

Actually if you set NETOPT_PRELOADING (and the driver implements it), a packet would not be sent until you set the state to TX.

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.

@miri64
Copy link
Member

miri64 commented Oct 8, 2019

I don't know what this is used for and setting all the other states seems odd to me too.

It was originally introduced to allow for IEEE 802.15.4e (TSCH).

@miri64
Copy link
Member

miri64 commented Oct 8, 2019

(I don't know if it was ever used for that)

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 9, 2019

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.

@maribu
Copy link
Member

maribu commented Oct 9, 2019

I was referring to something like this

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?

@maribu
Copy link
Member

maribu commented Oct 9, 2019

So summing up: I think that only setting NETOPT_STATE_SLEEP and NETOPT_STATE_IDLE should be settable, and setting everything else as state should simple return -ENOTSUP.

The following semantics make sense to me

  1. set(NETOPT_STATE, NETOPT_STATE_SLEEP):
    • If already sleeping: Return success and ignore
    • Else: Abort any pending TX or RX and go to sleep
  2. set(NETOPT_STATE, NETOPT_STATE_IDLE)
    • For any state except sleeping: Return success and ignore
    • If currently sleeping: Wake up the transceiver

@maribu
Copy link
Member

maribu commented Oct 16, 2019

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:

  1. Get the sleep/awake functionality in with a custom API for now, add the common API later on when the path for that is clear
  2. Wait for the discussion on the common API to conclude before continuing to work on this API

I'm personally fine with both options.

@benpicco
Copy link
Contributor

I see no problem in merging this as-is and adding the netdev integration later.

@miri64
Copy link
Member

miri64 commented Jun 25, 2020

I see no problem in merging this as-is and adding the netdev integration later.

So what is the hold up?

@kYc0o
Copy link
Contributor Author

kYc0o commented Jun 25, 2020

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.

Copy link
Member

@maribu maribu left a 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)
Copy link
Member

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 ...?

Comment on lines +181 to +185
if (cc110x_acquire(dev) != SPI_OK) {
return -EIO;
}

cc110x_power_on(dev);
Copy link
Member

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.

Copy link
Contributor Author

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.

@stale
Copy link

stale bot commented Jan 30, 2021

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.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Jan 30, 2021
@stale stale bot closed this Mar 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers State: stale State: The issue / PR has no activity for >185 days Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants