From 943b992bfcd026089168c18622124675f1658811 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 30 Sep 2022 14:17:46 -0500 Subject: [PATCH 1/3] Improve cyw43.set_power_management documentation .. and provide 4 preset values --- ports/raspberrypi/bindings/cyw43/__init__.c | 41 ++++++++++++++++++--- ports/raspberrypi/bindings/cyw43/__init__.h | 16 ++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/ports/raspberrypi/bindings/cyw43/__init__.c b/ports/raspberrypi/bindings/cyw43/__init__.c index cdd600bddc..2957a428c4 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.c +++ b/ports/raspberrypi/bindings/cyw43/__init__.c @@ -31,7 +31,6 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "bindings/cyw43/__init__.h" - //| class CywPin: //| """A class that represents a GPIO pin attached to the wifi chip. //| @@ -49,14 +48,42 @@ const mp_obj_type_t cyw43_pin_type = { ) }; +//| PM_STANDARD: int +//| """The standard power management mode""" +//| PM_AGGRESSIVE: int +//| """Aggressive power management mode for optimial power usage at the cost of performance""" +//| PM_PERFORMANCE: int +//| """Performance power management mode where more power is used to increase performance""" +//| PM_DISABLED: int +//| """Disable power management and always use highest power mode""" +//| //| def set_power_management(value: int) -> None: //| """Set the power management register //| -//| According to Raspberry Pi documentation, the value 0xa11140 -//| increases responsiveness at the cost of higher power usage. +//| For transmitter power, see ``wifi.Radio.txpower``. +//| This controls software power saving features inside the cyw43 chip. +//| it does not control transmitter power. //| -//| Besides this value, there appears to be no other public documentation -//| of the values that can be used. +//| The value is interpreted as a 24-bit hexadecimal number of the form +//| ``0x00adbrrm``. +//| +//| The low 4 bits, ``m``, are the power management mode: +//| * 0: disabled +//| * 1: aggressive power saving which reduces wifi throughput +//| * 2: Power saving with High througput +//| +//| The next 8 bits, ``r``, specify "the maximum time to wait before going back to sleep" for power management mode 2. The units of ``r`` are 10ms. +//| +//| The next 4 bits, ``b``, are the "wake period is measured in beacon periods". +//| +//| The next 4 bits, ``d``, specify the "wake interval measured in DTIMs. If this is set to 0, the wake interval is measured in beacon periods". +//| +//| The top 4 bits, ``a``, specifies the "wake interval sent to the access point" +//| +//| Several ``PM_`` constants gathered from various sources are included +//| in this module. According to Raspberry Pi documentation, the value 0xa11140 +//| (called `cyw43.PM_DISABLED` here) increases responsiveness at the cost of higher power +//| usage. //| """ //| STATIC mp_obj_t cyw43_set_power_management(const mp_obj_t value_in) { @@ -83,6 +110,10 @@ STATIC const mp_rom_map_elem_t cyw43_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cyw43) }, { MP_ROM_QSTR(MP_QSTR_CywPin), MP_ROM_QSTR(MP_QSTR_CywPin) }, { MP_ROM_QSTR(MP_QSTR_set_power_management), &cyw43_set_power_management_obj }, + { MP_ROM_QSTR(MP_QSTR_PM_STANDARD), MP_ROM_INT(PM_STANDARD) }, + { MP_ROM_QSTR(MP_QSTR_PM_AGGRESSIVE), MP_ROM_INT(PM_AGGRESSIVE) }, + { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(PM_PERFORMANCE) }, + { MP_ROM_QSTR(MP_QSTR_PM_DISABLED), MP_ROM_INT(PM_DISABLED) }, }; STATIC MP_DEFINE_CONST_DICT(cyw43_module_globals, cyw43_module_globals_table); diff --git a/ports/raspberrypi/bindings/cyw43/__init__.h b/ports/raspberrypi/bindings/cyw43/__init__.h index 5dcdfba52b..dc1651392d 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.h +++ b/ports/raspberrypi/bindings/cyw43/__init__.h @@ -32,3 +32,19 @@ extern const mp_obj_type_t cyw43_pin_type; const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj); const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj); + +#define CONSTANT_CYW43_PM_VALUE(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \ + (li_assoc << 20 | /* listen interval sent to ap */ \ + li_dtim_period << 16 | \ + li_beacon_period << 12 | \ + (pm2_sleep_ret_ms / 10) << 4 | /* cyw43_ll_wifi_pm multiplies this by 10 */ \ + pm_mode /* CYW43_PM2_POWERSAVE_MODE etc */) + +// CYW43_DEFAULT_PM (except a compile-time constant) +#define PM_STANDARD CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 200, 1, 1, 10) +// CYW43_AGGRESSIVE_PM (except a compile-time constant) +#define PM_AGGRESSIVE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 2000, 1, 1, 10) +// CYW43_PERFORMANCE_PM (except a compile-time constant) +#define PM_PERFORMANCE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 20, 1, 1, 1) +// The 0xa11140 magic value +#define PM_DISABLED CONSTANT_CYW43_PM_VALUE(CYW43_NO_POWERSAVE_MODE, 200, 1, 1, 10) From d3e85d165e1f28005c4404f02c6c05dcd713fdde Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 30 Sep 2022 14:21:37 -0500 Subject: [PATCH 2/3] Set cyw43 power management as needed, default to disabled .. the value actually needs to be enforced each time the STA or AP is enabled, because internally there's a call to cyw43_wifi_pm with the library's defaut power management value, not ours. Add a getter, though it only returns our idea of what the power management register is set to, it doesn't read out from the actual hardware, sadly. --- ports/raspberrypi/bindings/cyw43/__init__.c | 22 +++++++++++++++++++-- ports/raspberrypi/bindings/cyw43/__init__.h | 3 +++ ports/raspberrypi/common-hal/wifi/Radio.c | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ports/raspberrypi/bindings/cyw43/__init__.c b/ports/raspberrypi/bindings/cyw43/__init__.c index 2957a428c4..207a3d8545 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.c +++ b/ports/raspberrypi/bindings/cyw43/__init__.c @@ -31,6 +31,14 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "bindings/cyw43/__init__.h" + + +static int power_management_value = PM_DISABLED; + +void bindings_cyw43_wifi_enforce_pm() { + cyw43_wifi_pm(&cyw43_state, power_management_value); +} + //| class CywPin: //| """A class that represents a GPIO pin attached to the wifi chip. //| @@ -55,7 +63,7 @@ const mp_obj_type_t cyw43_pin_type = { //| PM_PERFORMANCE: int //| """Performance power management mode where more power is used to increase performance""" //| PM_DISABLED: int -//| """Disable power management and always use highest power mode""" +//| """Disable power management and always use highest power mode. CircuitPython sets this value at reset time, because it provides the best reliability.""" //| //| def set_power_management(value: int) -> None: //| """Set the power management register @@ -88,11 +96,20 @@ const mp_obj_type_t cyw43_pin_type = { //| STATIC mp_obj_t cyw43_set_power_management(const mp_obj_t value_in) { mp_int_t value = mp_obj_get_int(value_in); - cyw43_wifi_pm(&cyw43_state, value); + power_management_value = value; + bindings_cyw43_wifi_enforce_pm(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(cyw43_set_power_management_obj, cyw43_set_power_management); +//| def get_power_management() -> int: +//| """Retrieve the power management register""" +//| +STATIC mp_obj_t cyw43_get_power_management() { + return mp_obj_new_int(power_management_value); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(cyw43_get_power_management_obj, cyw43_get_power_management); + const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj) { if (!mp_obj_is_type(obj, &mcu_pin_type) && !mp_obj_is_type(obj, &cyw43_pin_type)) { mp_raise_TypeError_varg(translate("Expected a %q or %q"), mcu_pin_type.name, cyw43_pin_type.name); @@ -110,6 +127,7 @@ STATIC const mp_rom_map_elem_t cyw43_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cyw43) }, { MP_ROM_QSTR(MP_QSTR_CywPin), MP_ROM_QSTR(MP_QSTR_CywPin) }, { MP_ROM_QSTR(MP_QSTR_set_power_management), &cyw43_set_power_management_obj }, + { MP_ROM_QSTR(MP_QSTR_get_power_management), &cyw43_get_power_management_obj }, { MP_ROM_QSTR(MP_QSTR_PM_STANDARD), MP_ROM_INT(PM_STANDARD) }, { MP_ROM_QSTR(MP_QSTR_PM_AGGRESSIVE), MP_ROM_INT(PM_AGGRESSIVE) }, { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(PM_PERFORMANCE) }, diff --git a/ports/raspberrypi/bindings/cyw43/__init__.h b/ports/raspberrypi/bindings/cyw43/__init__.h index dc1651392d..c543f7b9e1 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.h +++ b/ports/raspberrypi/bindings/cyw43/__init__.h @@ -28,6 +28,7 @@ #pragma once #include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" extern const mp_obj_type_t cyw43_pin_type; const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj); @@ -48,3 +49,5 @@ const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj); #define PM_PERFORMANCE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 20, 1, 1, 1) // The 0xa11140 magic value #define PM_DISABLED CONSTANT_CYW43_PM_VALUE(CYW43_NO_POWERSAVE_MODE, 200, 1, 1, 10) + +extern void bindings_cyw43_wifi_enforce_pm(void); diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 9ed69d6000..23414491d6 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -35,6 +35,7 @@ #include "shared/runtime/interrupt_char.h" #include "py/gc.h" #include "py/runtime.h" +#include "bindings/cyw43/__init__.h" #include "shared-bindings/ipaddress/IPv4Address.h" #include "shared-bindings/wifi/ScannedNetworks.h" #include "shared-bindings/wifi/AuthMode.h" @@ -152,6 +153,7 @@ void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self) { void common_hal_wifi_radio_start_station(wifi_radio_obj_t *self) { cyw43_arch_enable_sta_mode(); + bindings_cyw43_wifi_enforce_pm(); } void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) { @@ -159,6 +161,7 @@ void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) { void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint8_t authmode, uint8_t max_connections) { mp_raise_NotImplementedError(NULL); + bindings_cyw43_wifi_enforce_pm(); } void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) { @@ -173,6 +176,7 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t // TODO use connect_async so we can service bg tasks & check for ctrl-c during // connect int result = cyw43_arch_wifi_connect_timeout_ms((const char *)ssid, (const char *)password, CYW43_AUTH_WPA2_AES_PSK, timeout_ms); + bindings_cyw43_wifi_enforce_pm(); switch (result) { case 0: return WIFI_RADIO_ERROR_NONE; From 40c2de833dd0c85bd94db22240b72ee30a5c5c76 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 1 Oct 2022 10:08:33 -0500 Subject: [PATCH 3/3] doc improvements --- ports/raspberrypi/bindings/cyw43/__init__.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/raspberrypi/bindings/cyw43/__init__.c b/ports/raspberrypi/bindings/cyw43/__init__.c index 207a3d8545..89a1e9be2a 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.c +++ b/ports/raspberrypi/bindings/cyw43/__init__.c @@ -59,11 +59,11 @@ const mp_obj_type_t cyw43_pin_type = { //| PM_STANDARD: int //| """The standard power management mode""" //| PM_AGGRESSIVE: int -//| """Aggressive power management mode for optimial power usage at the cost of performance""" +//| """Aggressive power management mode for optimal power usage at the cost of performance""" //| PM_PERFORMANCE: int //| """Performance power management mode where more power is used to increase performance""" //| PM_DISABLED: int -//| """Disable power management and always use highest power mode. CircuitPython sets this value at reset time, because it provides the best reliability.""" +//| """Disable power management and always use highest power mode. CircuitPython sets this value at reset time, because it provides the best connectivity reliability.""" //| //| def set_power_management(value: int) -> None: //| """Set the power management register @@ -78,7 +78,7 @@ const mp_obj_type_t cyw43_pin_type = { //| The low 4 bits, ``m``, are the power management mode: //| * 0: disabled //| * 1: aggressive power saving which reduces wifi throughput -//| * 2: Power saving with High througput +//| * 2: Power saving with high througput //| //| The next 8 bits, ``r``, specify "the maximum time to wait before going back to sleep" for power management mode 2. The units of ``r`` are 10ms. //|