Skip to content

Commit 041099f

Browse files
mbolivar-nordiccfriedt
authored andcommitted
Bluetooth: Controller: clean up nRF DFE
The way we currently handle direction finding extension (DFE) support on Nordic nRF5 controllers relies on required devicetree properties related to DFE in the "nordic,nrf-radio" node. That doesn't make sense on radios without DFE support, though. Any .dtsi for an SoC without DFE support which has such a node would require extraneous DFE related properties like dfe-antenna-num. Instead of making the properties required, mark them optional. We indicate the presence of DFE support via a new 'dfe-supported' boolean property which the SoC .dtsi files can set (or not) depending on support. This gives us the opportunity to do some cleanup in the Kconfig, removing CONFIG_HAS_HW_NRF_RADIO_BLE_DF since we know from the devicetree whether DFE support is available. Handle that change appropriately in radio_df.c. This gives us an opportunity to improve readability in the devicetree-related macro magic in that file. Signed-off-by: Martí Bolívar <[email protected]>
1 parent 50b267f commit 041099f

File tree

9 files changed

+137
-111
lines changed

9 files changed

+137
-111
lines changed

dts/arm/nordic/nrf52820.dtsi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@
5656
reg = <0x40001000 0x1000>;
5757
interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>;
5858
status = "okay";
59-
dfe-antenna-num = <0>;
60-
dfe-pdu-antenna = <0xFF>;
59+
dfe-supported;
6160
};
6261

6362
uart0: uart@40002000 {

dts/arm/nordic/nrf52833.dtsi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@
5555
reg = <0x40001000 0x1000>;
5656
interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>;
5757
status = "okay";
58-
dfe-antenna-num = <0>;
59-
dfe-pdu-antenna = <0xFF>;
58+
dfe-supported;
6059
};
6160

6261
uart0: uart@40002000 {

dts/arm/nordic/nrf5340_cpunet.dtsi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@
7272
reg = <0x41008000 0x1000>;
7373
interrupts = <8 NRF_DEFAULT_IRQ_PRIORITY>;
7474
status = "okay";
75-
dfe-antenna-num = <0>;
76-
dfe-pdu-antenna = <0xFF>;
75+
dfe-supported;
7776
};
7877

7978
rng: random@41009000 {

dts/bindings/net/wireless/nordic,nrf-radio.yaml

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ description: |
1616
---------------------------
1717
1818
Some radios support the Bluetooth Direction Finding Extension (DFE).
19+
The 'dfe-supported' property will be set when it is available.
1920
In this case, the 'dfegpio[n]-gpios' properties configure GPIO pins
2021
to use to drive antenna switching.
2122
@@ -91,22 +92,31 @@ properties:
9192
interrupts:
9293
required: true
9394

95+
dfe-supported:
96+
type: boolean
97+
description: |
98+
If set, the radio hardware supports the Direction Finding Extension.
99+
This property should be treated as read-only and should not be overridden;
100+
the correct value is provided for your target's SoC already.
101+
94102
dfe-antenna-num:
95103
type: int
96-
required: true
104+
required: false
97105
description: |
98-
Number of available antennas.
106+
Number of available antennas for the Direction Finding Extension.
99107
100-
Value zero means no antenna available. If provided value different than
101-
zero, it must be greater or equal to two.
108+
This should only be set if dfe-supported is true. If you set this
109+
property, the value must be at least two.
102110
103111
dfe-pdu-antenna:
104112
type: int
105-
required: true
113+
required: false
106114
description: |
107115
Antenna switch pattern to be used for transmission of PDU before start
108116
of transmission of Constant Tone Extension.
109117
118+
This should only be set if dfe-supported is true.
119+
110120
This pattern is stored in SWITCHPATTERN[0] before actual antenna
111121
switching patterns. This pattern will also be used to drive GPIOs
112122
when the radio releases control of GPIOs used to switch antennas.
@@ -115,7 +125,8 @@ properties:
115125
type: phandle-array
116126
required: false
117127
description: |
118-
Pin select for DFE pin 0.
128+
Pin select for DFE pin 0. This should only be set if dfe-supported
129+
is true.
119130
120131
For example, to use P0.2 on an nRF5x SoC:
121132

soc/arm/nordic_nrf/Kconfig.peripherals

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,6 @@ config HAS_HW_NRF_RADIO_BLE_CODED
133133
config HAS_HW_NRF_RADIO_IEEE802154
134134
bool
135135

136-
config HAS_HW_NRF_RADIO_BLE_DF
137-
bool
138-
139136
config HAS_HW_NRF_RNG
140137
bool
141138

soc/arm/nordic_nrf/nrf52/Kconfig.soc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ config SOC_NRF52820
160160
select HAS_HW_NRF_RADIO_BLE_2M
161161
select HAS_HW_NRF_RADIO_TX_PWR_HIGH
162162
select HAS_HW_NRF_RADIO_BLE_CODED
163-
select HAS_HW_NRF_RADIO_BLE_DF
164163
select HAS_HW_NRF_RNG
165164
select HAS_HW_NRF_RTC0
166165
select HAS_HW_NRF_RTC1
@@ -296,7 +295,6 @@ config SOC_NRF52833
296295
select HAS_HW_NRF_RADIO_TX_PWR_HIGH
297296
select HAS_HW_NRF_RADIO_BLE_CODED
298297
select HAS_HW_NRF_RADIO_IEEE802154
299-
select HAS_HW_NRF_RADIO_BLE_DF
300298
select HAS_HW_NRF_RNG
301299
select HAS_HW_NRF_RTC0
302300
select HAS_HW_NRF_RTC1

soc/arm/nordic_nrf/nrf53/Kconfig.soc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ config SOC_NRF5340_CPUNET
8686
select HAS_HW_NRF_RADIO_BLE_2M
8787
select HAS_HW_NRF_RADIO_BLE_CODED
8888
select HAS_HW_NRF_RADIO_IEEE802154
89-
select HAS_HW_NRF_RADIO_BLE_DF
9089
select HAS_HW_NRF_RNG
9190
select HAS_HW_NRF_RTC0
9291
select HAS_HW_NRF_RTC1

subsys/bluetooth/controller/Kconfig.ll_sw_split

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
if BT_LL_SW_SPLIT
77

8+
DT_PATH_NORDIC_RADIO := $(dt_nodelabel_path,radio)
9+
DT_NORDIC_RADIO_DFE_SUPPORTED := $(dt_node_has_bool_prop,$(DT_PATH_NORDIC_RADIO),dfe-supported)
10+
811
config BT_LLL_VENDOR_NORDIC
912
bool "Use Nordic LLL"
1013
depends on SOC_COMPATIBLE_NRF
@@ -31,7 +34,7 @@ config BT_LLL_VENDOR_NORDIC
3134
select BT_CTLR_SYNC_PERIODIC_SUPPORT
3235
select BT_CTLR_ADV_ISO_SUPPORT
3336
select BT_CTLR_SYNC_ISO_SUPPORT
34-
select BT_CTLR_DF_SUPPORT if HAS_HW_NRF_RADIO_BLE_DF
37+
select BT_CTLR_DF_SUPPORT if $(DT_NORDIC_RADIO_DFE_SUPPORTED)
3538
select BT_CTLR_CHAN_SEL_2_SUPPORT
3639
select BT_CTLR_MIN_USED_CHAN_SUPPORT
3740
select BT_CTLR_DTM_HCI_SUPPORT

subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c

Lines changed: 113 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -15,90 +15,138 @@
1515
#include "radio_df.h"
1616
#include "radio_internal.h"
1717

18-
/* @brief Minimum antennas number required if antenna switching is enabled */
19-
#define DF_ANT_NUM_MIN 2
20-
/* @brief Value that used to check if PDU antenna pattern is not set */
21-
#define DF_PDU_ANT_NOT_SET 0xFF
22-
/* @brief Value to set antenna GPIO pin as not connected */
23-
#define DF_GPIO_PIN_NOT_SET 0xFF
24-
/* @brief Number of PSEL_DFEGPIO registers in Radio peripheral */
25-
#define DF_PSEL_GPIO_NUM 8
26-
/* @brief Maximum index number related with count of PSEL_DFEGPIO registers in
27-
* Radio peripheral. It is used in macros only e.g. UTIL_LISTIFY that
28-
* evaluate indices in an inclusive way.
18+
/* Devicetree node identifier for the radio node. */
19+
#define RADIO_NODE DT_NODELABEL(radio)
20+
21+
/* Value to set for unconnected antenna GPIO pins. */
22+
#define DFE_PSEL_NOT_SET 0xFF
23+
/* Number of PSEL_DFEGPIO[n] registers in the radio peripheral. */
24+
#define MAX_DFE_GPIO 8
25+
/* Run a macro 'fn' on each available DFE GPIO index, from 0 to
26+
* MAX_DFE_GPIO-1, with the given parenthesized separator.
2927
*/
30-
#define DF_PSEL_GPIO_NUM_MAX_IDX 7
28+
#define FOR_EACH_DFE_GPIO(fn, sep) \
29+
FOR_EACH(fn, sep, 0, 1, 2, 3, 4, 5, 6, 7)
3130

32-
/* @brief Direction Finding antenna matrix configuration */
31+
/* Direction Finding antenna matrix configuration */
3332
struct df_ant_cfg {
3433
uint8_t ant_num;
3534
/* Selection of GPIOs to be used to switch antennas by Radio */
36-
uint8_t dfe_gpio[DF_PSEL_GPIO_NUM];
35+
uint8_t dfe_gpio[MAX_DFE_GPIO];
3736
};
3837

39-
#define RADIO DT_NODELABEL(radio)
40-
#define DFE_GPIO_PSEL(idx) \
41-
COND_CODE_1(DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios), \
42-
(NRF_DT_GPIOS_TO_PSEL(RADIO, dfegpio##idx##_gpios)), \
43-
(DF_GPIO_PIN_NOT_SET))
38+
#define DFE_GPIO_PSEL(idx) \
39+
NRF_DT_GPIOS_TO_PSEL_OR(RADIO_NODE, dfegpio##idx##_gpios, \
40+
DFE_PSEL_NOT_SET)
4441

4542
#define DFE_GPIO_PIN_DISCONNECT (RADIO_PSEL_DFEGPIO_CONNECT_Disconnected << \
4643
RADIO_PSEL_DFEGPIO_CONNECT_Pos)
4744

48-
#define COUNT_GPIO(idx, _) + DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios)
49-
#define DFE_GPIO_NUM (UTIL_LISTIFY(DF_PSEL_GPIO_NUM, COUNT_GPIO, _))
45+
#define HAS_DFE_GPIO(idx) DT_NODE_HAS_PROP(RADIO_NODE, dfegpio##idx##_gpios)
5046

51-
/* DFE_GPIO_NUM_IS_ZERO is required to correctly compile COND_CODE_1 in
52-
* DFE_GPIO_ALLOWED_ANT_NUM macro. DFE_GPIO_NUM does not expand to literal 1
53-
* So it is not possible to use it as a conditional in COND_CODE_1 argument.
47+
/* The number of dfegpio[n]-gpios properties which are set. */
48+
#define DFE_GPIO_NUM (FOR_EACH_DFE_GPIO(HAS_DFE_GPIO, (+)))
49+
50+
/* The minimum number of antennas required to enable antenna switching. */
51+
#define MIN_ANTENNA_NUM 2
52+
53+
/* The maximum number of antennas supported by the number of
54+
* dfegpio[n]-gpios properties which are set.
5455
*/
5556
#if (DFE_GPIO_NUM > 0)
56-
#define DFE_GPIO_NUM_IS_ZERO 1
57+
#define MAX_ANTENNA_NUM BIT(DFE_GPIO_NUM)
5758
#else
58-
#define DFE_GPIO_NUM_IS_ZERO EMPTY
59+
#define MAX_ANTENNA_NUM 0
5960
#endif
6061

61-
#define DFE_GPIO_ALLOWED_ANT_NUM COND_CODE_1(DFE_GPIO_NUM_IS_ZERO, \
62-
(BIT(DFE_GPIO_NUM)), (0))
62+
/* PDU_ANTENNA is defined outside of the #if block below because
63+
* radio_df_pdu_antenna_switch_pattern_get() can get called even when
64+
* the preprocessor condition being tested is 0. In this case, we use
65+
* the default value of 0.
66+
*/
67+
#define PDU_ANTENNA DT_PROP_OR(RADIO_NODE, dfe_pdu_antenna, 0)
68+
69+
uint8_t radio_df_pdu_antenna_switch_pattern_get(void)
70+
{
71+
return PDU_ANTENNA;
72+
}
6373

6474
#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) || \
6575
defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
6676

67-
/* Check if there is enough pins configured to represent each pattern
68-
* for given antennas number.
77+
/*
78+
* Check that we have an antenna switch pattern for the DFE idle
79+
* state. (In DFE idle state, the radio peripheral transmits or
80+
* receives PDUs.)
6981
*/
70-
BUILD_ASSERT((DT_PROP(RADIO, dfe_antenna_num) <= DFE_GPIO_ALLOWED_ANT_NUM), "Insufficient "
71-
"number of GPIO pins configured.");
72-
BUILD_ASSERT((DT_PROP(RADIO, dfe_antenna_num) >= DF_ANT_NUM_MIN), "Insufficient "
73-
"number of antennas provided.");
74-
BUILD_ASSERT(!IS_ENABLED(CONFIG_BT_CTLR_DF_INIT_ANT_SEL_GPIOS) ||
75-
(DT_PROP(RADIO, dfe_pdu_antenna) != DF_PDU_ANT_NOT_SET), "Missing "
76-
"antenna pattern used to select antenna for PDU Tx.");
77-
78-
/* Check if dfegpio#-gios property has flag cell set to zero */
79-
#define DFE_GPIO_PIN_FLAGS(idx) (DT_GPIO_FLAGS(RADIO, dfegpio##idx##_gpios))
80-
#define DFE_GPIO_PIN_IS_FLAG_ZERO(idx) \
81-
COND_CODE_1(DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios), \
82-
(BUILD_ASSERT((DFE_GPIO_PIN_FLAGS(idx) == 0), \
83-
"Flags value of GPIO pin property must be" \
84-
"zero.")), \
85-
(EMPTY))
86-
87-
#define DFE_GPIO_PIN_LIST(idx, _) idx,
88-
FOR_EACH(DFE_GPIO_PIN_IS_FLAG_ZERO, (;),
89-
UTIL_LISTIFY(DF_PSEL_GPIO_NUM_MAX_IDX, DFE_GPIO_PIN_LIST))
90-
91-
#if DT_NODE_HAS_STATUS(RADIO, okay)
92-
const static struct df_ant_cfg ant_cfg = {
93-
.ant_num = DT_PROP(RADIO, dfe_antenna_num),
94-
.dfe_gpio = {
95-
FOR_EACH(DFE_GPIO_PSEL, (,),
96-
UTIL_LISTIFY(DF_PSEL_GPIO_NUM_MAX_IDX, DFE_GPIO_PIN_LIST))
82+
83+
#define HAS_PDU_ANTENNA DT_NODE_HAS_PROP(RADIO_NODE, dfe_pdu_antenna)
84+
85+
BUILD_ASSERT(HAS_PDU_ANTENNA,
86+
"Missing antenna pattern used to select antenna for PDU Tx "
87+
"during the DFE Idle state. "
88+
"Set the dfe-pdu-antenna devicetree property.");
89+
90+
void radio_df_ant_switch_pattern_set(const uint8_t *patterns, uint8_t len)
91+
{
92+
/* SWITCHPATTERN is like a moving pointer to an underlying buffer.
93+
* Each write stores a value and moves the pointer to new free position.
94+
* When read it returns number of stored elements since last write to
95+
* CLEARPATTERN. There is no need to use a subscript operator.
96+
*
97+
* Some storage entries in the buffer has special purpose for DFE
98+
* extension in radio:
99+
* - SWITCHPATTERN[0] for idle period (PDU Tx/Rx),
100+
* - SWITCHPATTERN[1] for guard and reference period,
101+
* - SWITCHPATTERN[2] and following for switch-sampling slots.
102+
* Due to that in SWITCHPATTER[0] there is stored a pattern provided by
103+
* DTS property dfe_pdu_antenna. This limits number of supported antenna
104+
* switch patterns by one.
105+
*/
106+
NRF_RADIO->SWITCHPATTERN = PDU_ANTENNA;
107+
for (uint8_t idx = 0; idx < len; ++idx) {
108+
NRF_RADIO->SWITCHPATTERN = patterns[idx];
97109
}
110+
}
111+
112+
/*
113+
* Check that the number of antennas has been set, and that enough
114+
* pins are configured to represent each pattern for the given number
115+
* of antennas.
116+
*/
117+
118+
#define HAS_ANTENNA_NUM DT_NODE_HAS_PROP(RADIO_NODE, dfe_antenna_num)
119+
120+
BUILD_ASSERT(HAS_ANTENNA_NUM,
121+
"You must set the dfe-antenna-num property in the radio node "
122+
"to enable antenna switching.");
123+
124+
#define ANTENNA_NUM DT_PROP_OR(RADIO_NODE, dfe_antenna_num, 0)
125+
126+
BUILD_ASSERT(!HAS_ANTENNA_NUM || (ANTENNA_NUM <= MAX_ANTENNA_NUM),
127+
"Insufficient number of GPIO pins configured. "
128+
"Set more dfegpio[n]-gpios properties.");
129+
BUILD_ASSERT(!HAS_ANTENNA_NUM || (ANTENNA_NUM >= MIN_ANTENNA_NUM),
130+
"Insufficient number of antennas provided. "
131+
"Increase the dfe-antenna-num property.");
132+
133+
/*
134+
* Check that each dfegpio[n]-gpios property has a zero flags cell.
135+
*/
136+
137+
#define ASSERT_DFE_GPIO_FLAGS_ARE_ZERO(idx) \
138+
BUILD_ASSERT(DT_GPIO_FLAGS(RADIO_NODE, dfegpio##idx##_gpios) == 0, \
139+
"The flags cell in each dfegpio[n]-gpios " \
140+
"property must be zero.")
141+
142+
FOR_EACH_DFE_GPIO(ASSERT_DFE_GPIO_FLAGS_ARE_ZERO, (;));
143+
144+
/* Stores the dfegpio[n]-gpios property values.
145+
*/
146+
const static struct df_ant_cfg ant_cfg = {
147+
.ant_num = ANTENNA_NUM,
148+
.dfe_gpio = { FOR_EACH_DFE_GPIO(DFE_GPIO_PSEL, (,)) }
98149
};
99-
#else
100-
#error "DF antenna switching feature requires dfe_antenna_num to be enabled in DTS"
101-
#endif
102150

103151
/* @brief Function configures Radio with information about GPIO pins that may be
104152
* used to drive antenna switching during CTE Tx/RX.
@@ -111,10 +159,10 @@ void radio_df_ant_switching_pin_sel_cfg(void)
111159
{
112160
uint8_t pin_sel;
113161

114-
for (uint8_t idx = 0; idx < DF_PSEL_GPIO_NUM; ++idx) {
162+
for (uint8_t idx = 0; idx < MAX_DFE_GPIO; ++idx) {
115163
pin_sel = ant_cfg.dfe_gpio[idx];
116164

117-
if (pin_sel != DF_GPIO_PIN_NOT_SET) {
165+
if (pin_sel != DFE_PSEL_NOT_SET) {
118166
nrf_radio_dfe_pattern_pin_set(NRF_RADIO,
119167
pin_sel,
120168
idx);
@@ -141,12 +189,12 @@ void radio_df_ant_switching_gpios_cfg(void)
141189
{
142190
uint8_t pin_sel;
143191

144-
for (uint8_t idx = 0; idx < DF_PSEL_GPIO_NUM; ++idx) {
192+
for (uint8_t idx = 0; idx < MAX_DFE_GPIO; ++idx) {
145193
pin_sel = ant_cfg.dfe_gpio[idx];
146-
if (pin_sel != DF_GPIO_PIN_NOT_SET) {
194+
if (pin_sel != DFE_PSEL_NOT_SET) {
147195
nrf_gpio_cfg_output(pin_sel);
148196

149-
if (BIT(idx) & DT_PROP(RADIO, dfe_pdu_antenna)) {
197+
if (BIT(idx) & PDU_ANTENNA) {
150198
nrf_gpio_pin_set(pin_sel);
151199
} else {
152200
nrf_gpio_pin_clear(pin_sel);
@@ -316,33 +364,6 @@ void radio_df_ant_switch_pattern_clear(void)
316364
NRF_RADIO->CLEARPATTERN = RADIO_CLEARPATTERN_CLEARPATTERN_Clear;
317365
}
318366

319-
void radio_df_ant_switch_pattern_set(const uint8_t *patterns, uint8_t len)
320-
{
321-
/* SWITCHPATTERN is like a moving pointer to underlying buffer.
322-
* Each write stores a value and moves the pointer to new free position.
323-
* When read it returns number of stored elements since last write to
324-
* CLEARPATTERN. There is no need to use subscript operator.
325-
*
326-
* Some storage entries in the buffer has special purpose for DFE
327-
* extension in radio:
328-
* - SWITCHPATTERN[0] for idle period (PDU Tx/Rx),
329-
* - SWITCHPATTERN[1] for guard and reference period,
330-
* - SWITCHPATTERN[2] and following for switch-sampling slots.
331-
* Due to that in SWITCHPATTER[0] there is stored a pattern provided by
332-
* DTS property dfe_pdu_antenna. This limits number of supported antenna
333-
* switch patterns by one.
334-
*/
335-
NRF_RADIO->SWITCHPATTERN = DT_PROP(RADIO, dfe_pdu_antenna);
336-
for (uint8_t idx = 0; idx < len; ++idx) {
337-
NRF_RADIO->SWITCHPATTERN = patterns[idx];
338-
}
339-
}
340-
341-
uint8_t radio_df_pdu_antenna_switch_pattern_get(void)
342-
{
343-
return DT_PROP(RADIO, dfe_pdu_antenna);
344-
}
345-
346367
void radio_df_reset(void)
347368
{
348369
radio_df_mode_set(RADIO_DFEMODE_DFEOPMODE_Disabled);

0 commit comments

Comments
 (0)