-
Notifications
You must be signed in to change notification settings - Fork 8.4k
net: openthread: Host-Processor support #47256
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
Conversation
Add a Kconfig option for SPI peripheral devices' default init priority. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
This commit adds support to use OpenThread on a host-processor device, connected to an RCP device over SPI. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
Add a Kconfig option for a host-controller to enable RCP restoration. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
pdgendt
left a comment
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.
Added a self-review for some comments/fixes.
| required: false | ||
| description: Interrupt pin | ||
|
|
||
| Optional interript pin asserted by the RCP |
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.
| Optional interript pin asserted by the RCP | |
| Optional interrupt pin asserted by the RCP |
| #ifdef CONFIG_OPENTHREAD_HOSTPROCESSOR_SPI | ||
| #include "spi_interface.hpp" | ||
|
|
||
| typedef ot::Spinel::RadioSpinel<SpiInterface, RadioSpinelContext> PlatformSpiRadioSpinel; |
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.
| typedef ot::Spinel::RadioSpinel<SpiInterface, RadioSpinelContext> PlatformSpiRadioSpinel; | |
| typedef ot::Spinel::RadioSpinel<SpiInterface, RadioSpinelContext> PlatformRadioSpinel; |
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.
For my own understanding and for the sake of argumenting the use of C++ code here (it's kind of a gray area when it comes to the Zephyr codebase), please correct me if I'm wrong:
- In order to implement OT host functionality, we need to use an
ot::Spinel::RadioSpineltemplate class, which takes two template parameters:InterfaceTypeandProcessContextType. The latter is not a concern, butInterfaceTypeis expected to be a class implementing certain methods (defined inspi_interface.hpp), therefore there's no other way around than using C++ for that. - The
ot::Spinel::RadioSpineltemplate class does not expose a C API, therefore the spinel-basedotPlatRadio*driver also needs to be implemented in C++.
Is that more or less correct?
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.
- Yes, kind of, we could try to re-implement the entire
Spinelprotocol, however this would be almost impossible to maintain. - Yes
| { | ||
| OT_UNUSED_VARIABLE(aInstance); | ||
|
|
||
| SuccessOrDie(RadioSpinelInstance().GetIeeeEui64(aIeeeEui64)); |
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.
Not sure if the SuccessOrDie is the best approach to "fail".
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.
MIght not be the best idea, from what I've seen the newlib wrapper for this function will simply end up in a busy-loop.
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.
Some caveat here, the included radio_spinel_impl.hpp also uses these functions a lot.
|
|
||
| if (!data->ready) { | ||
| data->ready = true; | ||
| gpio_add_callback(config->irq_gpio.port, &data->irq_gpio_callback); |
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.
| gpio_add_callback(config->irq_gpio.port, &data->irq_gpio_callback); | |
| if (config->irq_gpio.port) { | |
| gpio_add_callback(config->irq_gpio.port, &data->irq_gpio_callback); | |
| } |
| /* | ||
| * Copyright (c) 2019, The OpenThread Authors. | ||
| * All rights reserved. | ||
| * | ||
| * Redistribution and use in source and binary forms, with or without | ||
| * modification, are permitted provided that the following conditions are met: | ||
| * 1. Redistributions of source code must retain the above copyright | ||
| * notice, this list of conditions and the following disclaimer. | ||
| * 2. Redistributions in binary form must reproduce the above copyright | ||
| * notice, this list of conditions and the following disclaimer in the | ||
| * documentation and/or other materials provided with the distribution. | ||
| * 3. Neither the name of the copyright holder nor the | ||
| * names of its contributors may be used to endorse or promote products | ||
| * derived from this software without specific prior written permission. | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| * POSSIBILITY OF SUCH DAMAGE. | ||
| */ |
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 original header from the posix ported SPI implementation.
| struct RadioSpinelContext { | ||
| otInstance *mInstance; | ||
| }; |
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.
Simply wraps an instance pointer, as the Process method only accepts const arguments.
rlubos
left a comment
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.
Some initial high-level feedback after digesting (and hopefully understanding) this codebase.
| } | ||
|
|
||
| #ifdef CONFIG_OPENTHREAD_HOSTPROCESSOR | ||
| uint64_t otPlatTimeGet(void) |
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 wonder if it'd make sense to create time.c platform implementation and implement API defined in OT's time.h in there, there are only 2 functions in there, but currently, they're scattered around different files.
| #ifdef CONFIG_OPENTHREAD_HOSTPROCESSOR_SPI | ||
| #include "spi_interface.hpp" | ||
|
|
||
| typedef ot::Spinel::RadioSpinel<SpiInterface, RadioSpinelContext> PlatformSpiRadioSpinel; |
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.
For my own understanding and for the sake of argumenting the use of C++ code here (it's kind of a gray area when it comes to the Zephyr codebase), please correct me if I'm wrong:
- In order to implement OT host functionality, we need to use an
ot::Spinel::RadioSpineltemplate class, which takes two template parameters:InterfaceTypeandProcessContextType. The latter is not a concern, butInterfaceTypeis expected to be a class implementing certain methods (defined inspi_interface.hpp), therefore there's no other way around than using C++ for that. - The
ot::Spinel::RadioSpineltemplate class does not expose a C API, therefore the spinel-basedotPlatRadio*driver also needs to be implemented in C++.
Is that more or less correct?
| { | ||
| OT_UNUSED_VARIABLE(aInstance); | ||
|
|
||
| SuccessOrDie(RadioSpinelInstance().GetIeeeEui64(aIeeeEui64)); |
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.
MIght not be the best idea, from what I've seen the newlib wrapper for this function will simply end up in a busy-loop.
| endif() | ||
|
|
||
| if(CONFIG_OPENTHREAD_HOSTPROCESSOR) | ||
| # Inject our platform spinel implementation |
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.
Can you elaborate on why is it needed to inject those sources into OT libs, why can't it end up in the openthread_platform library with other platform files?
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 OpenThread build system has private compile definitions for each library. This was the easiest way to make sure exactly the same definitions are set.
Because of the C++ template for the RadioSpinel instance, which is header-only.
| .get_capabilities = ot_spinel_get_capabilities, | ||
| .cca = ot_spinel_cca, | ||
| .set_channel = ot_spinel_set_channel, | ||
| .filter = ot_spinel_filter, | ||
| .set_txpower = ot_spinel_set_txpower, | ||
| .tx = ot_spinel_tx, | ||
| .start = ot_spinel_start, | ||
| .stop = ot_spinel_stop, | ||
| .configure = ot_spinel_configure, |
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.
Are those dummy-implementations even needed, couldn't they be just NULL pointers? Noone should actaully call them as the radio layer for OT gets a custom implementation for this configuration.
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 wasn't sure how to add this file, but if the API isn't called from other subsystems, I can leave them as NULL. Isn't some shell command able to call these?
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.
AFAIK they're not.
| * Copyright (c) 2019, The OpenThread Authors. | ||
| * All rights reserved. | ||
| * | ||
| * Redistribution and use in source and binary forms, with or without |
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 is a problem, AFAIK no license other than Apache-2.0 is allowed in Zephyr tree.
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, I figured that much. If this blocks the PR, I could move this into the zephyrproject/openthread repo.
But then the code is split across repositories.
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.
That's also an option, although still not perfect, as we're aiming to keep the fork as close to the original repo as possible. Pehrpas you could ask the OT community if they're if we reuse parts of the code under Zephyr license? It seems that there's not that much overlap between the original file and the version you've posted here.
pdgendt
left a comment
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.
@rlubos Thanks for the review, I'm going to clean it up and I'll also try to add the HDCL (UART) so it's easier to test with an USB dongle.
See my responses for more information.
| .get_capabilities = ot_spinel_get_capabilities, | ||
| .cca = ot_spinel_cca, | ||
| .set_channel = ot_spinel_set_channel, | ||
| .filter = ot_spinel_filter, | ||
| .set_txpower = ot_spinel_set_txpower, | ||
| .tx = ot_spinel_tx, | ||
| .start = ot_spinel_start, | ||
| .stop = ot_spinel_stop, | ||
| .configure = ot_spinel_configure, |
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 wasn't sure how to add this file, but if the API isn't called from other subsystems, I can leave them as NULL. Isn't some shell command able to call these?
| endif() | ||
|
|
||
| if(CONFIG_OPENTHREAD_HOSTPROCESSOR) | ||
| # Inject our platform spinel implementation |
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 OpenThread build system has private compile definitions for each library. This was the easiest way to make sure exactly the same definitions are set.
Because of the C++ template for the RadioSpinel instance, which is header-only.
| #ifdef CONFIG_OPENTHREAD_HOSTPROCESSOR_SPI | ||
| #include "spi_interface.hpp" | ||
|
|
||
| typedef ot::Spinel::RadioSpinel<SpiInterface, RadioSpinelContext> PlatformSpiRadioSpinel; |
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.
- Yes, kind of, we could try to re-implement the entire
Spinelprotocol, however this would be almost impossible to maintain. - Yes
| { | ||
| OT_UNUSED_VARIABLE(aInstance); | ||
|
|
||
| SuccessOrDie(RadioSpinelInstance().GetIeeeEui64(aIeeeEui64)); |
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.
Some caveat here, the included radio_spinel_impl.hpp also uses these functions a lot.
| * Copyright (c) 2019, The OpenThread Authors. | ||
| * All rights reserved. | ||
| * | ||
| * Redistribution and use in source and binary forms, with or without |
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, I figured that much. If this blocks the PR, I could move this into the zephyrproject/openthread repo.
But then the code is split across repositories.
|
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
|
I'm going to pick this up again later. |
This PR adds support to operate as an OpenThread Host-Processor connected to an RCP radio controller over SPI. Both FTD and MTD modes are supported.
Some remarks up for improvement:
Tested on a custom board using NXP's i.MX RT1064 connected to a Nordic nRF52840.