← index #11247Issue #16799
Related · high · value 0.353
QUERY · ISSUE

[RP2-W] WiFi in unusable state, cyw43_spi_init() -> bus_data assert fails

openby ThomasChropened 2023-04-12updated 2023-11-06
bugport-rp2

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

CANDIDATE · ISSUE

Raspberry Pi Pico2 W - Wifi fails to start if CPU is overclocked

closedby chrisibopened 2025-02-23updated 2025-05-05
bugport-rp2

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

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied