-
-
Notifications
You must be signed in to change notification settings - Fork 779
cyw43439: add support for CYW43439 wifi chip #4529
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
base: master
Are you sure you want to change the base?
Conversation
Added support for the PIO half-duplex SPI interface for the RP2040 chip to provide read/write functionalities for communicating with the CYW43439 chip available on the Raspberry Pi Pico W board. Support is also added in the board main. A minimal WiFi HIL for the Cypress 43439 chips was added. Both WiFi HIL and EthernetTap HIL implementation were provided for the RP2040 PIO.
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 really nice, just a few ideas.
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 suggest that we add a firmware
folder in Tock where we put these kinds of 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.
Created a firmware
directory in root
boards/raspberry_pi_pico/src/main.rs
Outdated
#[no_mangle] | ||
#[link_section = ".stack_buffer"] | ||
static mut STACK_MEMORY: [u8; 0x1500] = [0; 0x1500]; | ||
static mut STACK_MEMORY: [u8; 0x6000] = [0; 0x6000]; |
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.
Is there any way we could reduce this size? Do we inow what causes 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.
I missed to modify this after adding a static buffer for packet construction. Fixed it now
>; | ||
type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureRp2040Sensor>; | ||
|
||
const WIFI: bool = option_env!("WIFI").is_some(); |
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.
What about adding a a feature in and assigning WIFI
to cfg
?
Is there a reason why we would want to disable WiFi?
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 think it's more that we don't want capsules like Ethernet to be available for Picos without Wifi. I tried using a wifi feature at first but the Tock board Makefile doesn't provide any "cargo flags" variable. Adding that would require re-writing some of the Makefile rules and I didn't want to create any clutter. My idea was that for Pico W we'd build with WIFI=1 make
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 should be a capsule as this chip might be uses with other microcontrollers.
sm.set_enabled(true); | ||
} | ||
|
||
pub fn cyw43_spi_program_init( |
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.
Is this just an example?
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.
It's used for initializing the PIO in cyw43439.rs
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.
Given that we have a bunch of these, one more can't hurt.
kernel/src/hil/wifi_cyw43.rs
Outdated
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
// Copyright OxidOS Automotive 2025. | ||
|
||
//! Interfaces for CYW43439 WiFi devices |
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 we document here how these traits relate to each other and how they should be used?
Changed back the stack size. Moved firmware files to root. Fixed bug from calling recv in the transmit_frame method in rp2040/cyw43439.
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.
Here's some quick notes from skimming this. Not a full pass yet.
@@ -0,0 +1,5 @@ | |||
# Wifi firmware blobs | |||
|
|||
Firmware obtained from https://github.com/georgerobotics/cyw43-driver/tree/main/firmware |
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.
Why from some random github project? Does Infineon or Raspberry Pi not provide them directly?
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, I see. We're actually copying Embassy here: https://github.com/embassy-rs/embassy/tree/main/cyw43-firmware
We could possibly get them directly from Infineon: https://github.com/Infineon/wifi-host-driver/tree/master/WHD/COMPONENT_WIFI5/resources/firmware/COMPONENT_43439 and https://github.com/Infineon/wifi-resources (for the "Country Locale Matrix")
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.
We discussed on the call today possibly relying on an external crate for firmware blobs. Maybe the same Crate embassy uses: https://crates.io/crates/cyw43-firmware
That should probably be discussed on a Core team call for approval.
sm.set_enabled(true); | ||
} | ||
|
||
pub fn cyw43_spi_program_init( |
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.
Given that we have a bunch of these, one more can't hurt.
_2mA = 0, | ||
_4mA = 1, | ||
_8mA = 2, | ||
_12mA = 3, |
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 leading underscore here is misleading. It's often used for "internal" things in other languages.
These should match the datasheet whenever possible, and to the extend possible. Maybe call them DRIVE_2MA
, DRIVE_4MA
, etc.?
_2mA = 0, | ||
_4mA = 1, | ||
_8mA = 2, | ||
_12mA = 3, |
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.
Update these to match whatever the "DRIVE" values are named above if you change them.
} | ||
} | ||
|
||
pub static NVRAM: &[u8] = b" |
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 also came from a source, right? That should be cited. Looks like it can be found here: https://github.com/Infineon/wifi-resources It would be good to double-check that matches though.
/// ## Arguments | ||
/// | ||
/// - `ssid`: SSID of found network | ||
fn scanned_network(&self, ssid: Ssid); |
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.
Is there any way to know what kind of encryption it uses?
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 think it would be fine to put this in the board's directory.
Adding a new top-level directory is probably not something we want to do. Putting it in chips/
is potentially an option, but I think would require some discussion and a plan for what types of binary blobs are acceptable and under what situations.
Another option is to embed the bytes in a rust file.
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.
We discussed this on the Network working group call and we're considering an external crate that the CYW* WiFi capsule would rely on which would contain the binary blobs. Notably, they're licensed differently than the rest of the Tock kernel and there are some concerns there.
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 would probably still be easiest to include from the board, then.
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 seems general enough to just be called wifi.rs
.
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.
Event though we discussed this during type networking call, I kind of agree with @bradjc that this seems general enough. I do not see how other devices might need anything else here.
macro_rules! impl_bytes { | ||
($t:ident) => { | ||
impl $t { | ||
/// Bytes consumed by this type. | ||
pub const SIZE: usize = core::mem::size_of::<Self>(); | ||
|
||
/// Create from byte array. | ||
#[allow(unused)] | ||
pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self { | ||
let alignment = core::mem::align_of::<Self>(); | ||
assert_eq!( | ||
bytes.as_ptr().align_offset(alignment), | ||
0, | ||
"{} is not aligned", | ||
core::any::type_name::<Self>() | ||
); | ||
unsafe { core::mem::transmute(bytes) } | ||
} | ||
|
||
/// Create from mutable byte array. | ||
#[allow(unused)] | ||
pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self { | ||
let alignment = core::mem::align_of::<Self>(); | ||
assert_eq!( | ||
bytes.as_ptr().align_offset(alignment), | ||
0, | ||
"{} is not aligned", | ||
core::any::type_name::<Self>() | ||
); | ||
|
||
unsafe { core::mem::transmute(bytes) } | ||
} | ||
} | ||
}; | ||
} |
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 worried about having these unsafes here in general, and based on learning how macros work in Rust having unsafe
in a macro is even more scary. It's not clear to me what impl_bytes
does or how necessary it is versus using a safe approach.
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 file might also be copied directly from Embassy, if I recall what we discussed on the Network working group call. Maybe we should be re-implementing these for Tock.
pub(super) fn as_bytes<T: Sized>(data: &T) -> &[u8] { | ||
unsafe { | ||
core::slice::from_raw_parts( | ||
core::ptr::from_ref::<T>(data) as *const u8, | ||
core::mem::size_of::<T>(), | ||
) | ||
} | ||
} | ||
|
||
pub(super) fn slice8_mut(x: &mut [u32]) -> &mut [u8] { | ||
let len = x.len() * 4; | ||
unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } | ||
} | ||
|
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.
With these unsafes I don't know how necessary they are, but it would be good to add a # Safety
comment that explains why they are safe.
/// ## Arguments | ||
/// | ||
/// - `ssid`: SSID of found network | ||
fn scanned_network(&self, ssid: Ssid); |
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.
fn scanned_network(&self, ssid: Ssid); | |
fn scanned_network(&self, ssid: Ssid, encryption: Option<Encryption>, signal_strength: Option<u8>); |
#[non_exhaustive]
enum Encryption {
Open,
Wep,
Wpa1,
Wpa2,
Wpa3,
}
signal_strength
defined in abs(dBm)
.
Just to make it more generic.
@irina-nita @alexandruradovici @JADarius This seems quite close, but waiting on some feedback. Is there a timeline/estimate/plan for this? |
Hey, sorry for the lack of activity on this PR. I'm currently working on wrapping up and testing the migration from |
Pull Request Overview
This pull request adds:
chips/cyw43439
: support for the PIO half-duplex SPI interface for the RP2040 chip used to communicate with the CYW43439 chip available on the Raspberry Pi Pico W boardboards/raspberry_pi_pico
for enabling the PIO configuration and Ethernet Tap capsulehil/wifi_cyw43
: minimal WiFi HIL for peripherals that interact with the CYW43439 or other similar Cypress chips. The HIL contains four traits that provide interfaces for initializing the device and getting the MAC address, scanning networks and configuring station/access point mode.Testing Strategy
libtock-c
lwIP exampleTODO or Help Wanted
This PR needs to add an abstract interface for communicating with the CYW4343x chips. Besides the peripheral used for reading/writing to the chip, the process should be the same
Documentation Updated
/docs
, or no updates are required.Formatting
make prepush
.