-
Notifications
You must be signed in to change notification settings - Fork 7.8k
STM32WB0x: Add PM support (suspend-to-ram) #94402
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: main
Are you sure you want to change the base?
Changes from all commits
0148d5a
dc75210
6d281a8
85f6d6b
02868b7
1c30da4
68ee408
be88807
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Copyright (c) 2025 STMicroelectronics | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
zephyr_library_sources_ifdef(CONFIG_PM board.c) |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,44 @@ | ||||
/* | ||||
* Copyright (c) 2025 STMicroelectronics | ||||
* | ||||
* SPDX-License-Identifier: Apache-2.0 | ||||
*/ | ||||
|
||||
#include <zephyr/init.h> | ||||
#include "stm32wb0x_ll_pwr.h" | ||||
|
||||
/* Implement the correct Pull-up/pull-down for GPIOA and GPIOB | ||||
* to reach the minimum power consumption. | ||||
*/ | ||||
static int board_pupd_init(void) | ||||
{ | ||||
LL_PWR_EnableGPIOPullUp(LL_PWR_GPIO_A, | ||||
LL_PWR_GPIO_BIT_0| | ||||
LL_PWR_GPIO_BIT_1| | ||||
LL_PWR_GPIO_BIT_2| | ||||
LL_PWR_GPIO_BIT_3); | ||||
|
||||
LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, | ||||
LL_PWR_GPIO_BIT_8| | ||||
LL_PWR_GPIO_BIT_9| | ||||
LL_PWR_GPIO_BIT_10| | ||||
LL_PWR_GPIO_BIT_11); | ||||
|
||||
LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, | ||||
LL_PWR_GPIO_BIT_0| | ||||
LL_PWR_GPIO_BIT_3| | ||||
LL_PWR_GPIO_BIT_6| | ||||
LL_PWR_GPIO_BIT_7); | ||||
|
||||
LL_PWR_EnableGPIOPullUp(LL_PWR_GPIO_B, | ||||
LL_PWR_GPIO_BIT_1| | ||||
LL_PWR_GPIO_BIT_2| | ||||
LL_PWR_GPIO_BIT_4| | ||||
LL_PWR_GPIO_BIT_5| | ||||
LL_PWR_GPIO_BIT_14| | ||||
LL_PWR_GPIO_BIT_15); | ||||
|
||||
return 0; | ||||
} | ||||
|
||||
SYS_INIT(board_pupd_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use zephyr/include/zephyr/platform/hooks.h Line 70 in 965bcd6
Also, this should be in the SoC hook. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why should it be in the SoC hook? Would you please explain more? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The operations performed appear to not be board specific. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. These power pull-up/pull-down configurations are board specific. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,8 +97,10 @@ LOG_MODULE_REGISTER(adc_stm32wb0, CONFIG_ADC_LOG_LEVEL); | |
#define ADC_CHANNEL_TYPE_DIFF (0x02U) /* Differential */ | ||
#define ADC_CHANNEL_TYPE_INVALID (0xFFU) /* Invalid */ | ||
|
||
#define STM32_HCLK_FREQUENCY DT_PROP(DT_NODELABEL(rcc), clock_frequency) | ||
|
||
Comment on lines
+100
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should be able to put that definition in a header somewhere - or in fact, it may already be! - instead of re-defining it in every driver. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about defining it in include/zephyr/dt-bindings/clock/stm32_common_clocks.h There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This header is for DT bindings only, it should just contain (un)packing macros for DT->driver exchanges. I think placing the definition in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case, it's only for WB0x. What about other STM32 products? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it could go in here? I was suggesting Name should be changed if we place it in the general file, maybe to something like Note that the definition will be unused on all other STM32 until we clean-up the SYS_CLOCK_HW_CYCLES_PER_SEC mess, which will be done in another PR, hence why having something WB0-specific for now is fine (IMO) |
||
/** See RM0505 §6.2.1 "System clock details" */ | ||
BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC >= (8 * 1000 * 1000), | ||
BUILD_ASSERT(STM32_HCLK_FREQUENCY >= (8 * 1000 * 1000), | ||
"STM32WB0: system clock frequency must be at least 8MHz to use ADC"); | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -11,6 +11,8 @@ | |||||
#include <zephyr/bluetooth/hci_types.h> | ||||||
#include <zephyr/drivers/bluetooth.h> | ||||||
#include <zephyr/drivers/entropy.h> | ||||||
#include <zephyr/pm/policy.h> | ||||||
#include <zephyr/pm/device.h> | ||||||
#include "bleplat_cntr.h" | ||||||
#include "ble_stack.h" | ||||||
#include "stm32wb0x_hal_radio_timer.h" | ||||||
|
@@ -31,15 +33,8 @@ LOG_MODULE_REGISTER(bt_driver); | |||||
#define DT_DRV_COMPAT st_hci_stm32wb0 | ||||||
|
||||||
/* Max HS startup time expressed in system time (1953 us / 2.4414 us) */ | ||||||
#define MAX_HS_STARTUP_TIME 320 | ||||||
#define BLE_WKUP_PRIO 0 | ||||||
#define BLE_WKUP_FLAGS 0 | ||||||
#define BLE_TX_RX_PRIO 0 | ||||||
#define BLE_TX_RX_FLAGS 0 | ||||||
#define CPU_WKUP_PRIO 1 | ||||||
#define CPU_WKUP_FLAGS 0 | ||||||
#define BLE_ERROR_PRIO 3 | ||||||
#define BLE_ERROR_FLAGS 0 | ||||||
#define BLE_RXTX_SEQ_PRIO 3 | ||||||
#define BLE_RXTX_SEQ_FLAGS 0 | ||||||
#define PKA_PRIO 2 | ||||||
|
@@ -56,9 +51,29 @@ LOG_MODULE_REGISTER(bt_driver); | |||||
#define EVT_VENDOR_CODE_LSB 3 | ||||||
#define EVT_VENDOR_CODE_MSB 4 | ||||||
|
||||||
#if (defined(CONFIG_SOC_STM32WB06) || defined(CONFIG_SOC_STM32WB07)) && defined(CONFIG_PM) | ||||||
#error "At the moment, PM is not supported for WB06 & WB07" | ||||||
#endif /* (CONFIG_SOC_STM32WB06 || CONFIG_SOC_STM32WB07) && CONFIG_PM */ | ||||||
|
||||||
static uint32_t __noinit dyn_alloc_a[BLE_DYN_ALLOC_SIZE >> 2]; | ||||||
static uint8_t buffer_out_mem[MAX_EVENT_SIZE]; | ||||||
static struct k_work_delayable hal_radio_timer_work, ble_stack_work; | ||||||
static struct k_work_delayable ble_stack_work; | ||||||
|
||||||
#if CONFIG_PM_DEVICE | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
apply everywhere for Kconfig symbols There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which style do you suggest? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
either is fine. |
||||||
/* ST Proprietary extended event */ | ||||||
#define HCI_EXT_EVT 0x82 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
#define ACI_HAL_END_OF_RADIO_ACTIVITY_VSEVT_CODE 0x0004 | ||||||
#define STATE_ALL_BITMASK 0xFFFF | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
#define STATE_IDLE 0x00 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
struct bt_hci_ext_evt_hdr { | ||||||
uint8_t type; | ||||||
uint8_t evt; | ||||||
uint16_t len; | ||||||
uint16_t vs_code; | ||||||
uint8_t last_state; | ||||||
uint8_t next_state; | ||||||
} __packed; | ||||||
#endif /* CONFIG_PM_DEVICE */ | ||||||
|
||||||
static struct net_buf *get_rx(uint8_t *msg); | ||||||
static PKA_HandleTypeDef hpka; | ||||||
|
@@ -77,6 +92,43 @@ int BLEPLAT_NvmGet(void) | |||||
return 0; | ||||||
} | ||||||
|
||||||
#if CONFIG_PM_DEVICE | ||||||
/* Inform Zephyr PM about wakeup event from radio */ | ||||||
static void register_radio_event(uint32_t time, bool unregister) | ||||||
{ | ||||||
int64_t value_ms, ticks; | ||||||
static struct pm_policy_event radio_evt; | ||||||
static bool first_time = true; | ||||||
|
||||||
if (unregister) { | ||||||
if (!first_time) { | ||||||
first_time = true; | ||||||
pm_policy_event_unregister(&radio_evt); | ||||||
} | ||||||
} else { | ||||||
value_ms = HAL_RADIO_TIMER_DiffSysTimeMs(time, HAL_RADIO_TIMER_GetCurrentSysTime()); | ||||||
ticks = k_ms_to_ticks_floor64(value_ms) + k_uptime_ticks(); | ||||||
if (first_time) { | ||||||
pm_policy_event_register(&radio_evt, ticks); | ||||||
first_time = false; | ||||||
} else { | ||||||
pm_policy_event_update(&radio_evt, ticks); | ||||||
} | ||||||
} | ||||||
} | ||||||
#endif /* CONFIG_PM_DEVICE */ | ||||||
|
||||||
uint8_t BLEPLAT_SetRadioTimerValue(uint32_t Time, uint8_t EventType, uint8_t CalReq) | ||||||
{ | ||||||
uint8_t retval; | ||||||
|
||||||
retval = HAL_RADIO_TIMER_SetRadioTimerValue(Time, EventType, CalReq); | ||||||
#if CONFIG_PM_DEVICE | ||||||
register_radio_event(Time, false); | ||||||
#endif /* CONFIG_PM_DEVICE */ | ||||||
return retval; | ||||||
} | ||||||
|
||||||
static void blestack_process(struct k_work *work) | ||||||
{ | ||||||
BLE_STACK_Tick(); | ||||||
|
@@ -85,11 +137,6 @@ static void blestack_process(struct k_work *work) | |||||
} | ||||||
} | ||||||
|
||||||
static void vtimer_process(struct k_work *work) | ||||||
{ | ||||||
HAL_RADIO_TIMER_Tick(); | ||||||
} | ||||||
|
||||||
/* "If, since the last power-on or reset, the Host has ever issued a legacy | ||||||
* advertising command and then issues an extended advertising command, or | ||||||
* has ever issued an extended advertising command and then issues a legacy | ||||||
|
@@ -196,9 +243,24 @@ void send_event(uint8_t *buffer_out, uint16_t buffer_out_length, int8_t overflow | |||||
|
||||||
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); | ||||||
struct hci_data *hci = dev->data; | ||||||
/* Construct net_buf from event data */ | ||||||
struct net_buf *buf = get_rx(buffer_out); | ||||||
struct net_buf *buf; | ||||||
|
||||||
#if CONFIG_PM_DEVICE | ||||||
struct bt_hci_ext_evt_hdr *vs_evt = (struct bt_hci_ext_evt_hdr *)(buffer_out); | ||||||
|
||||||
if (vs_evt->type == HCI_EXT_EVT) { | ||||||
if (vs_evt->evt == BT_HCI_EVT_VENDOR) { | ||||||
if ((vs_evt->vs_code == ACI_HAL_END_OF_RADIO_ACTIVITY_VSEVT_CODE) && | ||||||
(vs_evt->next_state == STATE_IDLE)) { | ||||||
register_radio_event(0, true); | ||||||
} | ||||||
return; | ||||||
} | ||||||
} | ||||||
#endif /* CONFIG_PM_DEVICE */ | ||||||
|
||||||
/* Construct net_buf from event data */ | ||||||
buf = get_rx(buffer_out); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the NULL check should be 1st, and it should result in a panic or reset or something if it's not excepted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the purpose of "the NULL check should be 1st," Can you explain more? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I meant is
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment, the null check is implemented in the |
||||||
if (buf) { | ||||||
/* Handle the received HCI data */ | ||||||
LOG_DBG("New event %p len %u type %u", buf, buf->len, buf->data[0]); | ||||||
|
@@ -210,28 +272,13 @@ void send_event(uint8_t *buffer_out, uint16_t buffer_out_length, int8_t overflow | |||||
|
||||||
void HAL_RADIO_TIMER_TxRxWakeUpCallback(void) | ||||||
{ | ||||||
k_work_schedule(&hal_radio_timer_work, K_NO_WAIT); | ||||||
k_work_schedule(&ble_stack_work, K_NO_WAIT); | ||||||
} | ||||||
|
||||||
void HAL_RADIO_TIMER_CpuWakeUpCallback(void) | ||||||
{ | ||||||
k_work_schedule(&hal_radio_timer_work, K_NO_WAIT); | ||||||
k_work_schedule(&ble_stack_work, K_NO_WAIT); | ||||||
} | ||||||
|
||||||
void HAL_RADIO_TxRxCallback(uint32_t flags) | ||||||
{ | ||||||
BLE_STACK_RadioHandler(flags); | ||||||
k_work_schedule(&ble_stack_work, K_NO_WAIT); | ||||||
k_work_schedule(&hal_radio_timer_work, K_NO_WAIT); | ||||||
} | ||||||
|
||||||
ISR_DIRECT_DECLARE(RADIO_TIMER_TXRX_WKUP_IRQHandler) | ||||||
{ | ||||||
HAL_RADIO_TIMER_TXRX_WKUP_IRQHandler(); | ||||||
ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency */ | ||||||
return 1; | ||||||
} | ||||||
|
||||||
ISR_DIRECT_DECLARE(RADIO_TXRX_IRQHandler) | ||||||
|
@@ -248,59 +295,57 @@ ISR_DIRECT_DECLARE(RADIO_TXRX_SEQ_IRQHandler) | |||||
return 1; | ||||||
} | ||||||
|
||||||
ISR_DIRECT_DECLARE(RADIO_TIMER_CPU_WKUP_IRQHandler) | ||||||
{ | ||||||
HAL_RADIO_TIMER_TimeoutCallback(); | ||||||
HAL_RADIO_TIMER_CpuWakeUpCallback(); | ||||||
ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency */ | ||||||
return 1; | ||||||
} | ||||||
|
||||||
ISR_DIRECT_DECLARE(RADIO_TIMER_ERROR_IRQHandler) | ||||||
{ | ||||||
volatile uint32_t debug_cmd; | ||||||
|
||||||
BLUE->DEBUGCMDREG |= 1; | ||||||
/* If the device is configured with CLK_SYS = 64MHz | ||||||
* and BLE clock = 16MHz, a register read is necessary | ||||||
* to ensure interrupt register is properly cleared | ||||||
* due to AHB down converter latency | ||||||
*/ | ||||||
debug_cmd = BLUE->DEBUGCMDREG; | ||||||
LOG_ERR("Timer error"); | ||||||
ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency */ | ||||||
return 1; | ||||||
} | ||||||
|
||||||
/* Function called from PKA_IRQHandler() context. */ | ||||||
void PKAMGR_IRQCallback(void) | ||||||
{ | ||||||
k_work_schedule(&ble_stack_work, K_NO_WAIT); | ||||||
} | ||||||
|
||||||
static int _PKA_IRQHandler(void *args) | ||||||
static void _PKA_IRQHandler(void *args) | ||||||
{ | ||||||
ARG_UNUSED(args); | ||||||
|
||||||
HAL_PKA_IRQHandler(&hpka); | ||||||
ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency */ | ||||||
return 1; | ||||||
} | ||||||
|
||||||
static void ble_isr_installer(void) | ||||||
{ | ||||||
IRQ_DIRECT_CONNECT(RADIO_TIMER_TXRX_WKUP_IRQn, BLE_WKUP_PRIO, | ||||||
RADIO_TIMER_TXRX_WKUP_IRQHandler, BLE_WKUP_FLAGS); | ||||||
IRQ_DIRECT_CONNECT(RADIO_TXRX_IRQn, BLE_TX_RX_PRIO, RADIO_TXRX_IRQHandler, BLE_TX_RX_FLAGS); | ||||||
IRQ_DIRECT_CONNECT(RADIO_TIMER_CPU_WKUP_IRQn, CPU_WKUP_PRIO, | ||||||
RADIO_TIMER_CPU_WKUP_IRQHandler, CPU_WKUP_FLAGS); | ||||||
IRQ_DIRECT_CONNECT(RADIO_TXRX_SEQ_IRQn, BLE_RXTX_SEQ_PRIO, RADIO_TXRX_SEQ_IRQHandler, | ||||||
BLE_RXTX_SEQ_FLAGS); | ||||||
IRQ_DIRECT_CONNECT(RADIO_TIMER_ERROR_IRQn, BLE_ERROR_PRIO, RADIO_TIMER_ERROR_IRQHandler, | ||||||
BLE_ERROR_FLAGS); | ||||||
IRQ_CONNECT(PKA_IRQn, PKA_PRIO, _PKA_IRQHandler, NULL, PKA_FLAGS); | ||||||
} | ||||||
|
||||||
#if defined(CONFIG_PM_DEVICE) | ||||||
static int ble_pm_action(const struct device *dev, | ||||||
enum pm_device_action action) | ||||||
{ | ||||||
static uint32_t PKA_CR_vr; | ||||||
|
||||||
switch (action) { | ||||||
case PM_DEVICE_ACTION_SUSPEND: | ||||||
LL_PWR_EnableWU_EWBLE(); | ||||||
PKA_CR_vr = PKA->CR; | ||||||
/* TBD: Manage PKA save for WB06 & WB07 */ | ||||||
break; | ||||||
case PM_DEVICE_ACTION_RESUME: | ||||||
LL_PWR_DisableWU_EWBLE(); | ||||||
/* TBD: Manage PKA restore for WB06 & WB07 */ | ||||||
PKA->CLRFR = PKA_CLRFR_PROCENDFC | PKA_CLRFR_RAMERRFC | PKA_CLRFR_ADDRERRFC; | ||||||
PKA->CR = PKA_CR_vr; | ||||||
ble_isr_installer(); | ||||||
mathieuchopstm marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
irq_enable(RADIO_TXRX_IRQn); | ||||||
irq_enable(RADIO_TXRX_SEQ_IRQn); | ||||||
irq_enable(PKA_IRQn); | ||||||
break; | ||||||
default: | ||||||
return -ENOTSUP; | ||||||
} | ||||||
|
||||||
return 0; | ||||||
} | ||||||
#endif /* CONFIG_PM_DEVICE */ | ||||||
|
||||||
static void rng_get_random(void *num, size_t size) | ||||||
{ | ||||||
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); | ||||||
|
@@ -450,7 +495,6 @@ static int bt_hci_stm32wb0_send(const struct device *dev, struct net_buf *buf) | |||||
static int bt_hci_stm32wb0_open(const struct device *dev, bt_hci_recv_t recv) | ||||||
{ | ||||||
struct hci_data *data = dev->data; | ||||||
RADIO_TIMER_InitTypeDef VTIMER_InitStruct = {MAX_HS_STARTUP_TIME, 0, 0}; | ||||||
RADIO_HandleTypeDef hradio = {0}; | ||||||
BLE_STACK_InitTypeDef BLE_STACK_InitParams = { | ||||||
.BLEStartRamAddress = (uint8_t *)dyn_alloc_a, | ||||||
|
@@ -487,8 +531,6 @@ static int bt_hci_stm32wb0_open(const struct device *dev, bt_hci_recv_t recv) | |||||
ble_isr_installer(); | ||||||
hradio.Instance = RADIO; | ||||||
HAL_RADIO_Init(&hradio); | ||||||
HAL_RADIO_TIMER_Init(&VTIMER_InitStruct); | ||||||
|
||||||
HW_AES_Init(); | ||||||
hpka.Instance = PKA; | ||||||
HAL_PKA_Init(&hpka); | ||||||
|
@@ -503,9 +545,10 @@ static int bt_hci_stm32wb0_open(const struct device *dev, bt_hci_recv_t recv) | |||||
#endif /* CONFIG_BT_EXT_ADV */ | ||||||
|
||||||
aci_adv_nwk_init(); | ||||||
|
||||||
#if CONFIG_PM_DEVICE | ||||||
aci_hal_set_radio_activity_mask(STATE_ALL_BITMASK); | ||||||
#endif /* CONFIG_PM_DEVICE */ | ||||||
data->recv = recv; | ||||||
k_work_init_delayable(&hal_radio_timer_work, vtimer_process); | ||||||
k_work_init_delayable(&ble_stack_work, blestack_process); | ||||||
k_work_schedule(&ble_stack_work, K_NO_WAIT); | ||||||
|
||||||
|
@@ -517,10 +560,12 @@ static DEVICE_API(bt_hci, drv) = { | |||||
.send = bt_hci_stm32wb0_send, | ||||||
}; | ||||||
|
||||||
PM_DEVICE_DT_INST_DEFINE(0, ble_pm_action); | ||||||
|
||||||
Comment on lines
+563
to
+564
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move this to the HCI_DEVICE_INIT() macro:
Suggested change
+ #define HCI_DEVICE_INIT(inst) \
+ PM_DEVICE_DT_INST_DEFINE(inst, ble_pm_action);
static struct hci_data hci_data_##inst = { \
}; \ |
||||||
#define HCI_DEVICE_INIT(inst) \ | ||||||
static struct hci_data hci_data_##inst = { \ | ||||||
}; \ | ||||||
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &hci_data_##inst, NULL, \ | ||||||
DEVICE_DT_INST_DEFINE(inst, NULL, PM_DEVICE_DT_INST_GET(0), &hci_data_##inst, NULL, \ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) | ||||||
|
||||||
/* Only one instance supported */ | ||||||
|
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.
There should be a way to use fts and gpio hog to do this.
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.
AFAIK, gpio hog is used to automatically set a GPIO pin at boot, but in this file these pull-up/pull-down configs are related to PWR register and they will be applied when the SoC enters
suspend-to-ram
state. In other words, they are not used inactive
state.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.
Actually, we do keep
PWRC_CR1.APC
at default value and configure GPIO pull-up/pull-down viaPWR
on WB0 series:zephyr/drivers/gpio/gpio_stm32.c
Lines 177 to 198 in 80ab4b8
so this configuration would be applied all the time, as far as I understand. (and most importantly: lost if the application changes the pins' configuration!)
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.
You're right. So, I should implement these pull-up/pull-down configs in the board's DTS 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.
Yes. You should use a GPIO hog as suggested by @erwango.
See example here:
zephyr/boards/st/steval_stwinbx1/steval_stwinbx1.dts
Lines 128 to 137 in db15de5
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.
As far as I noticed, it sets the pin state at boot time, and it's not related to pull-up/pull-down configs. It doesn't support
bias-pull-up
andbias-pull-down
properties.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.
Have you tried using
gpios = <xx GPIO_PULL_UP>
/gpios = <xx GPIO_PULL_DOWN>
? From my understanding of the hog driver, it should work.