Open adsnaider opened 1 year ago
Hmm. A quick fix would be to rebind in the loop, but this shouldn't occur in the first place.
Are you able to try out the code here? If it is intermittent it could be the chip missing the chip-select: https://github.com/newAM/w5500-rs/issues/252#issuecomment-1670593061
Oh, that's really odd, that seems to be working :O
Edit: Fyi, that specifically works when I have
spi_cs.set_high().unwrap();
w5500_hl::ll::eh0::reset(&mut w5500_reset, &mut delay).unwrap();
when I set the SPI
:/ Your chip probably has a fast clock speed and the default HAL implementation doesn't assert chip select low for long enough. I haven't merged that "fix" yet because I don't have a good solution for embedded-hal 1.0 yet.
Interesting find. Do you know if that will cause a problem with networking as well?
We've only seen it in these two locations so far, but it will cause problems with any accesses over the SPI bus given enough time.
I'm experiencing something similar. My setup:
Cargo.toml
relevant section
panic-halt = "0.2.0"
embedded-hal = "1.0"
ufmt = "0.2.0"
nb = "1.1.0"
w5500-ll = { version = "0.12.0", features = ["eh0"] }
w5500-hl = { version = "0.11.0" }
w5500-dhcp = "0.6.0"
w5500-mqtt = { version = "0.3.0" }
[dependencies.embedded-hal-v0]
version = "0.2.3"
package = "embedded-hal"
[dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal"
rev = "3e362624547462928a219c40f9ea8e3a64f21e5f"
features = ["arduino-mega2560"]
main.rs
//...
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap_or_else(|| panic!());
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);
let mut d10 = pins.d10.into_output();
let mut d53 = pins.d53.into_output();
let mut d4 = pins.d4.into_output();
d4.set_high();
d10.set_low();
let (mut spi, mut cs) = arduino_hal::Spi::new(
dp.SPI,
pins.d52.into_output(),
pins.d51.into_output(),
pins.d50.into_pull_up_input(),
d53,
spi::Settings {mode: embedded_hal::spi::MODE_0, ..spi::Settings::default()}
);
cs.set_high().unwrap(); //trying this as a suggestion from GH issue - no effect
let mut w5500 = W5500::new(spi, cs);
//below are setup_socket and udp_bind calls
// dhcp.setup_socket(&mut w5500).unwrap();
let simr: u8 = w5500.simr().unwrap();
w5500.set_simr(LOCAL_SOCKET.bitmask() | simr).unwrap();
const MASK: SocketInterruptMask = SocketInterruptMask::ALL_MASKED.unmask_recv();
w5500.set_sn_imr(LOCAL_SOCKET, MASK).unwrap();
w5500.close(LOCAL_SOCKET).unwrap();
w5500.set_sipr(&Ipv4Addr::UNSPECIFIED).unwrap();
// w5500.udp_bind(LOCAL_SOCKET, 68).unwrap();
ufmt::uwriteln!(&mut serial, "W5500 bind1\r").unwrap_infallible();
w5500.set_sn_cr(LOCAL_SOCKET, SocketCommand::Close).unwrap();
ufmt::uwriteln!(&mut serial, "W5500 bind2\r").unwrap_infallible();
while w5500.sn_sr(LOCAL_SOCKET).unwrap() != Ok(SocketStatus::Closed) {
match w5500.sn_sr(LOCAL_SOCKET).unwrap() {
Ok(status) => {
ufmt::uwriteln!(&mut serial, "W5500 waiting1: {}\r", (status as u8)).unwrap_infallible();
}
Err(f) => {
ufmt::uwriteln!(&mut serial, "W5500 waiting1 err: {}\r", f).unwrap_infallible();
}
}
// w5500.write(0x0, 0x0, &[0x80]).unwrap();
// arduino_hal::delay_ms(1000);
}
ufmt::uwriteln!(&mut serial, "W5500 bind3\r").unwrap_infallible();
w5500.set_sn_port(LOCAL_SOCKET, 68).unwrap();
ufmt::uwriteln!(&mut serial, "W5500 bind4\r").unwrap_infallible();
const MODE: SocketMode = SocketMode::DEFAULT.set_protocol(Protocol::Udp);
ufmt::uwriteln!(&mut serial, "W5500 bind5\r").unwrap_infallible();
w5500.set_sn_mr(LOCAL_SOCKET, MODE).unwrap();
ufmt::uwriteln!(&mut serial, "W5500 bind6\r").unwrap_infallible();
w5500.set_sn_cr(LOCAL_SOCKET, SocketCommand::Open).unwrap();
// This will not hang, the socket status will always change to Udp
// after a open command with SN_MR set to UDP.
// (unless you do somthing silly like holding the W5500 in reset)
ufmt::uwriteln!(&mut serial, "W5500 bind7\r").unwrap_infallible();
while w5500.sn_sr(LOCAL_SOCKET).unwrap() != Ok(SocketStatus::Udp) {
match w5500.sn_sr(LOCAL_SOCKET).unwrap() {
Ok(status) => {
ufmt::uwriteln!(&mut serial, "W5500 waiting2: {}\r", (status as u8)).unwrap_infallible();
}
Err(f) => {
ufmt::uwriteln!(&mut serial, "W5500 waiting2 err: {}\r", f).unwrap_infallible();
}
}
// w5500.set_sn_port(LOCAL_SOCKET, 68).unwrap();
// w5500.set_sn_mr(LOCAL_SOCKET, MODE).unwrap();
// w5500.set_sn_cr(LOCAL_SOCKET, SocketCommand::Open).unwrap();
// w5500.write(0x0, 0x0, &[0x80]).unwrap();
// arduino_hal::delay_ms(1000);
} //HANGS
This
while w5500.sn_sr(LOCAL_SOCKET).unwrap() != Ok(SocketStatus::Udp)
hangs yielding
Starting
W5500 bind1
W5500 bind2
W5500 bind3
W5500 bind4
W5500 bind5
W5500 bind6
W5500 bind7
W5500 waiting2: 0
W5500 waiting2: 0
W5500 waiting2: 0
W5500 waiting2 err: 37 <-------- happens sometimes, rather rarely
W5500 waiting2: 0
W5500 waiting2: 0
W5500 waiting2: 0
...
Is there any chance to get this working?
it is "fixed" (read: worked around) for EH0 on the main branch. I have been meaning to make a release, I'll do that today.
For EH1 there's no control for me, so it's up to the HAL authors to keep CS high long enough to meet the hold times. The W5500 base trait can also just be implemented directly if changing the HAL isn't easy.
Thanks
I'm pasting updated snippet.
Cargo.toml
[dependencies]
panic-halt = "0.2.0"
embedded-hal = "1.0.0"
ufmt = "0.2.0"
nb = "1.1.0"
w5500-ll = { version = "0.13.0", features = ["eh0"] }
w5500-hl = { version = "0.12.0" }
w5500-dhcp = "0.7.0"
w5500-mqtt = { version = "0.4.0" }
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap_or_else(|| panic!());
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);
let mut d10 = pins.d10.into_output();
let seed: u64 = 872398473984;
d10.set_low();
let (mut spi, mut cs) = arduino_hal::Spi::new(
dp.SPI,
pins.d52.into_output(),
pins.d51.into_output(),
pins.d50.into_pull_up_input(),
pins.d53.into_output(),
spi::Settings {mode: embedded_hal::spi::MODE_0, ..spi::Settings::default()}
// spi::Settings::default()
);
ufmt::uwriteln!(&mut serial, "Starting\r").unwrap_infallible();
cs.set_high().unwrap();
let mut w5500 = W5500::new(spi, cs);
let mut dhcp: Client = Client::new(LOCAL_SOCKET, seed, LOCAL_MAC, HOSTNAME);
ufmt::uwriteln!(&mut serial, "W5500 socket_setup\r").unwrap_infallible();
dhcp.setup_socket(&mut w5500).unwrap();
It is still stuck, should it work?
Yeah, that should work. I have been running a DHCP client device for a little over a year now without issues.
What is the system frequency and SPI bus frequency of your device?
Describe the Problem
I'm building an application with the w5500-evb-pico. Upon setting up the SPI and initializing the registers, I used the
Udp::udp_bind
call to bind Sn0 to some port. However, this often blocks forever (or until the watchdog resets the chip). I've narrowed it down toin
udp_bind
being the problematic loop and the reason is that the SocketStatus is Closed for some reason. This happens more often than not and I'm not sure what the issue may be here. I've tried with 2 different wiznets and both experience the same problem.Expected Behaviour
udp_bind
doesn't block.Steps to Reproduce
Setup a w5500-evb-pico, connected over ethernet to a computer. Initialize the w5500 eh0 vdm
I can share some source code as well but it's not much different from what's here: https://github.com/newAM/w5500-issue-252/blob/main/src/main.rs, but I can try running that specifically to see if I have the same issue on that source.