[RP2-W] WiFi in unusable state, cyw43_spi_init() -> bus_data assert fails
So this seems to be a tough one for me.
I've got a Raspberry Pi Pico W. I've attached an BME280 Sensor via I2C, the connected Pins are:
BME VCC = Pico PinNo 36 (3V3(OUT))
BME GND = Pico PinNo 38 (GND)
BME SDA = Pico PinNo 11 (I2C0 SDA)
BME SCL = Pico PinNo 12 (I2C0 SCL)
And here is the code:
import time
import ustruct
import machine
import network
import usocket
# Globals
sensorid = 99
sensoraddr = 0x76
sendseconds = 60
secondstrywificonnect = 10
REG_DATA = 0xF7
REG_CONTROL = 0xF4
REG_CONFIG = 0xF5
REG_CONTROL_HUM = 0xF2
REG_HUM_MSB = 0xFD
REG_HUM_LSB = 0xFE
OVERSAMPLE_TEMP = 2
OVERSAMPLE_PRES = 2
MODE = 1
while True:
try:
# Connect to WiFi
wlan = network.WLAN(network.STA_IF)
if wlan.isconnected() == False:
wlan.active(True)
wlan.connect('FRITZ!Box 7490', 'x')
second = 0
while wlan.isconnected() == False:
time.sleep(1)
second += 1
if second > secondstrywificonnect:
machine.reset()
# Initialize I2C
i2c = machine.I2C(0, sda=machine.Pin(8), scl=machine.Pin(9), freq=100000)
# Set Oversampling
OVERSAMPLE_HUM = 2
i2c.writeto_mem(sensoraddr, REG_CONTROL_HUM, bytearray([OVERSAMPLE_HUM]))
control = OVERSAMPLE_TEMP << 5 | OVERSAMPLE_PRES << 2 | MODE
i2c.writeto_mem(sensoraddr, REG_CONTROL, bytearray([control]))
# Read Calibration data from sensor
cal1 = i2c.readfrom_mem(sensoraddr, 0x88, 24)
cal2 = i2c.readfrom_mem(sensoraddr, 0xA1, 1)
cal3 = i2c.readfrom_mem(sensoraddr, 0xE1, 7)
# Convert bytes to words
dig_T1 = ustruct.unpack('H', cal1[0:2])[0]
dig_T2 = ustruct.unpack('h', cal1[2:4])[0]
dig_T3 = ustruct.unpack('h', cal1[4:6])[0]
dig_P1 = ustruct.unpack('H', cal1[6:8])[0]
dig_P2 = ustruct.unpack('h', cal1[8:10])[0]
dig_P3 = ustruct.unpack('h', cal1[10:12])[0]
dig_P4 = ustruct.unpack('h', cal1[12:14])[0]
dig_P5 = ustruct.unpack('h', cal1[14:16])[0]
dig_P6 = ustruct.unpack('h', cal1[16:18])[0]
dig_P7 = ustruct.unpack('h', cal1[18:20])[0]
dig_P8 = ustruct.unpack('h', cal1[20:22])[0]
dig_P9 = ustruct.unpack('h', cal1[22:24])[0]
dig_H1 = ustruct.unpack('B', cal2[0:1])[0]
dig_H2 = ustruct.unpack('h', cal3[0:2])[0]
dig_H3 = ustruct.unpack('B', cal3[2:3])[0]
dig_H4 = ustruct.unpack('b', cal3[3:4])[0]
dig_H4 = (dig_H4 << 24) >> 20
dig_H4 = dig_H4 | (ustruct.unpack('b', cal3[4:5])[0] & 0x0F)
dig_H5 = ustruct.unpack('b', cal3[5:6])[0]
dig_H5 = (dig_H5 << 24) >> 20
dig_H5 = dig_H5 | (ustruct.unpack('B', cal3[4:5])[0] >> 4 & 0x0F)
dig_H6 = ustruct.unpack('b', cal3[6:7])[0]
# Wait in ms (Datasheet Appendix B: Measurement time and current calculation)
wait_time = 1.25 + (2.3 * OVERSAMPLE_TEMP) + ((2.3 * OVERSAMPLE_PRES) + 0.575) + (
(2.3 * OVERSAMPLE_HUM) + 0.575)
time.sleep(wait_time / 1000)
# Read temperature/pressure/humidity
data = i2c.readfrom_mem(sensoraddr, REG_DATA, 8)
pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
hum_raw = (data[6] << 8) | data[7]
# Refine temperature
var1 = ((temp_raw >> 3 - dig_T1 << 1) * dig_T2) >> 11
var2 = (((((temp_raw >> 4) - dig_T1) * ((temp_raw >> 4) - dig_T1)) >> 12) * dig_T3) >> 14
t_fine = var1 + var2
temperature = float(((t_fine * 5) + 128) >> 8)
# Refine pressure and adjust for temperature
var1 = t_fine / 2.0 - 64000.0
var2 = var1 * var1 * dig_P6 / 32768.0
var2 = var2 + var1 * dig_P5 * 2.0
var2 = var2 / 4.0 + dig_P4 * 65536.0
var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0
var1 = (1.0 + var1 / 32768.0) * dig_P1
if var1 == 0:
pressure = 0
else:
pressure = 1048576.0 - pres_raw
pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1
var1 = dig_P9 * pressure * pressure / 2147483648.0
var2 = pressure * dig_P8 / 32768.0
pressure = pressure + (var1 + var2 + dig_P7) / 16.0
# Refine humidity
humidity = t_fine - 76800.0
humidity = (hum_raw - (dig_H4 * 64.0 + dig_H5 / 16384.0 * humidity)) * (
dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * humidity * (1.0 + dig_H3 / 67108864.0 * humidity)))
humidity = humidity * (1.0 - dig_H1 * humidity / 524288.0)
if humidity > 100:
humidity = 100
elif humidity < 0:
humidity = 0
# Data is ready
temperature = temperature / 100.0
pressure = pressure / 100.0
humidity = humidity
# Send data to the Internet, a Post Request with http - we don't use SSL here!
content = b'sensorid=' + str(sensorid) + '&temp=' + str(temperature) + '&press=' + str(
pressure) + '&hum=' + str(humidity) + '&password=x'
addr_info = usocket.getaddrinfo("x.de", 80)
addr = addr_info[0][-1]
sock = usocket.socket()
sock.connect(addr)
sock.send(b'POST /x.php HTTP/1.1\r\n')
sock.send(b'Host: x.de\r\n')
sock.send(b'Content-Type: application/x-www-form-urlencoded\r\n')
sock.send(b'Content-Length: ' + str(len(content)) + '\r\n')
sock.send(b'\r\n')
sock.send(content)
sock.send(b'\r\n\r\n')
sock.close()
# We're done
time.sleep(sendseconds)
except Exception as e:
print(e)
time.sleep(sendseconds)
(don't talk about code quality here - the code is old, and it is ugly as *** - I know...)
PS: This code runs on an ESP32 with Micropython without any problems whatsoever!
Firmware:
rp2-pico-w-20230411-unstable-v1.19.1-1014-gbde222ce8.uf2
And now the problem: When I send this code to the pico all runs fine, and is working like it should. UNTIL I remove power for even a short time. After that the WIFI is bricked and I can't do anything with it. Even resetting, rebooting, deinit() doesn't work anymore.
Here the status then:
>>> wlan = network.WLAN(network.STA_IF)
>>> wlan
<CYW43 STA down 0.0.0.0>
>>> wlan.deinit()
>>> wlan.active(True)
>>> wlan
<CYW43 STA down 0.0.0.0>
>>> wlan.scan()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 1] EPERM
>>> wlan.active(False)
>>> wlan.deinit()
>>> wlan.active(True)
>>> wlan.scan()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 1] EPERM
>>> wlan.status()
0
(connect() does also fail, of course!)
There seems to be no way to get wifi running again. I think after some time (maybe the lease-time of the FritzBox?) it will work again - but there must be a way to get out of this!
I tried to reproduce it without the I2C Connected, but that doesn't give the same problems, however, after the problem has been triggered it doesn't mater if I2C is sill connected. It won't work anyway. Still I'm not sure what exactly triggers the problem, I can't test the whole code without I2C, so I can't rule that out reliably.
Even this simple code fails then:
import rp2
import time
import network
wid = "FRITZ!Box 7490"
wpass = "x"
secondstrywificonnect = 10
print(str(time.ticks_ms()) + ': Trying to connect')
# Connect to WiFi
wlan = network.WLAN(network.STA_IF)
if wlan.isconnected() == False:
wlan.active(True)
wlan.connect(wid, wpass)
second = 0
while wlan.isconnected() == False:
time.sleep(1)
second += 1
print("Still trying")
if second > secondstrywificonnect:
print("Failed!")
else:
print("Connected!")
#rp2.country('DE')
#wlan.deinit()
#wlan.config(pm = 0xa11140)
#wlan.active(True)
So I'm not quite sure how I got there, but it seems to be that there is a possibility to "brick" the Wifi.
Any ideas on how to approach that further?
Update: Deleting the Lease from the FritzBox does seem to help... but there must be a trick to do that from the Pico itself...
Raspberry Pi Pico2 W - Wifi fails to start if CPU is overclocked
Port, board and/or hardware
RPI_PICO_2_W
MicroPython version
MicroPython v1.25.0-preview.307.g4364d9411 on 2025-02-23; Raspberry Pi Pico 2 W with RP2350
Reproduction
Save the following code onto the Pico 2 W and run it with either CPU_FREQ = 300_000_000 or CPU_FREQ = 150_000_000 uncommented.
When using the overclocked frequency, the following error is printed and the access point is not available to connect to: [CYW43] Failed to start CYW43
When using the default frequency the access point can be connected to and no errors are printed
import machine
import network
"""
When overclocked we get
[CYW43] Failed to start CYW43
When using default CPU frequency
the wifi starts fine
"""
CPU_FREQ = 300_000_000 # overclocked
#CPU_FREQ = 150_000_000 # default
machine.freq(CPU_FREQ)
wifi = network.WLAN(network.WLAN.IF_AP)
wifi.config(
ssid="pico2w_ap",
channel=10,
security=network.WLAN.SEC_OPEN,
)
wifi.active(True)
Expected behaviour
WiFi should work if the CPU is overclocked
Observed behaviour
When the CPU is overclocked, the wireless card firmware does not appear to initialize correctly:
[CYW43] Failed to start CYW43
Additional Information
My testing setup has 2 I2C devices connected: an OLED display GP0 & GP1 and a battery-backed realtime clock on GP2 & GP3. The code above does not initialize these devices, so I don't think their presence should have any impact; it looks like simply changing the CPU frequency is enough.
Doing a little trial-and-error changing the frequencies in the script above it looks like 270MHz is the upper limit of what the wifi can handle. Is this a known limitation of the firmware?
Code of Conduct
Yes, I agree