From f758cc1cc91f95b2d3edd8cf00b076ebd034fc78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Mi=C5=9B?= Date: Wed, 7 Mar 2018 18:32:25 +0100 Subject: [PATCH] [nrf52840] update radio driver to 178ecb3514e5f46282bf2108b56aecf5b8db6728 (#2601) --- examples/platforms/nrf52840/Makefile.am | 81 +- examples/platforms/nrf52840/diag.c | 16 +- examples/platforms/nrf52840/fem.c | 11 +- examples/platforms/nrf52840/platform-config.h | 33 +- examples/platforms/nrf52840/platform-fem.h | 13 +- examples/platforms/nrf52840/radio.c | 124 +- .../drivers/radio/fem/nrf_fem_control.c | 364 +++ .../drivers/radio/fem/nrf_fem_control_api.h | 160 +- .../radio/fem/nrf_fem_control_common.c | 224 -- .../radio/fem/nrf_fem_control_config.h | 13 +- .../radio/fem/nrf_fem_control_direct.c | 91 - .../radio/fem/nrf_fem_control_internal.h | 82 - .../radio/fem/nrf_fem_control_softdevice.c | 78 - .../drivers/radio/hal/nrf_radio.h | 497 +-- .../mac_features/nrf_802154_ack_timeout.c | 146 + .../mac_features/nrf_802154_ack_timeout.h | 103 + .../radio/mac_features/nrf_802154_csma_ca.c | 234 ++ .../radio/mac_features/nrf_802154_csma_ca.h | 105 + .../radio/mac_features/nrf_802154_filter.c | 433 +++ .../radio/mac_features/nrf_802154_filter.h | 78 + .../drivers/radio/nrf_802154.c | 686 ++++ .../drivers/radio/nrf_802154.h | 951 ++++++ .../radio/nrf_802154_ack_pending_bit.c | 413 +++ ...ing_bit.h => nrf_802154_ack_pending_bit.h} | 20 +- .../drivers/radio/nrf_802154_config.h | 462 +++ ...radio802154_const.h => nrf_802154_const.h} | 77 +- .../drivers/radio/nrf_802154_core.c | 2791 +++++++++++++++++ ...rv_radio802154_fsm.h => nrf_802154_core.h} | 121 +- .../drivers/radio/nrf_802154_core_hooks.c | 185 ++ .../drivers/radio/nrf_802154_core_hooks.h | 95 + .../radio/nrf_802154_critical_section.c | 220 ++ ...ection.h => nrf_802154_critical_section.h} | 59 +- ...radio802154_debug.c => nrf_802154_debug.c} | 10 +- ...radio802154_debug.h => nrf_802154_debug.h} | 51 +- ...tification.h => nrf_802154_notification.h} | 67 +- .../radio/nrf_802154_notification_direct.c | 110 + ...on_swi.c => nrf_802154_notification_swi.c} | 49 +- .../drivers/radio/nrf_802154_pib.c | 194 ++ ...drv_radio802154_pib.h => nrf_802154_pib.h} | 72 +- ...rity_drop.h => nrf_802154_priority_drop.h} | 16 +- ...ct.c => nrf_802154_priority_drop_direct.c} | 8 +- ...p_swi.c => nrf_802154_priority_drop_swi.c} | 14 +- ...ion.h => nrf_802154_procedures_duration.h} | 41 +- ...o802154_request.h => nrf_802154_request.h} | 64 +- .../drivers/radio/nrf_802154_request_direct.c | 139 + .../drivers/radio/nrf_802154_request_swi.c | 189 ++ ...02154_revision.c => nrf_802154_revision.c} | 12 +- ...02154_revision.h => nrf_802154_revision.h} | 12 +- ...154_rx_buffer.c => nrf_802154_rx_buffer.c} | 24 +- ...154_rx_buffer.h => nrf_802154_rx_buffer.h} | 18 +- .../drivers/radio/nrf_802154_swi.c | 821 +++++ .../drivers/radio/nrf_802154_swi.h | 222 ++ .../drivers/radio/nrf_802154_types.h | 124 + .../drivers/radio/nrf_drv_radio802154.c | 478 --- .../drivers/radio/nrf_drv_radio802154.h | 768 ----- .../nrf_drv_radio802154_ack_pending_bit.c | 238 -- .../radio/nrf_drv_radio802154_config.h | 199 -- .../nrf_drv_radio802154_critical_section.c | 123 - .../drivers/radio/nrf_drv_radio802154_fsm.c | 2281 -------------- .../nrf_drv_radio802154_notification_direct.c | 78 - .../drivers/radio/nrf_drv_radio802154_pib.c | 230 -- .../nrf_drv_radio802154_request_direct.c | 144 - .../radio/nrf_drv_radio802154_request_swi.c | 236 -- .../drivers/radio/nrf_drv_radio802154_swi.c | 673 ---- .../drivers/radio/nrf_drv_radio802154_swi.h | 178 -- ...radio802154_clock.h => nrf_802154_clock.h} | 36 +- ...clock_nodrv.c => nrf_802154_clock_nodrv.c} | 34 +- ...154_clock_sdk.c => nrf_802154_clock_sdk.c} | 28 +- ...radio802154_timer.h => nrf_802154_timer.h} | 52 +- .../platform/timer/nrf_802154_timer_nodrv.c | 411 +++ ...4_timer_none.c => nrf_802154_timer_none.c} | 12 +- .../drivers/radio/raal/nrf_raal_api.h | 23 +- .../drivers/radio/raal/nrf_raal_config.h | 8 +- .../radio/raal/single_phy/single_phy.c | 15 +- .../raal/softdevice/nrf_raal_softdevice.c | 101 +- .../raal/softdevice/nrf_raal_softdevice.h | 2 +- .../timer_scheduler/nrf_802154_timer_sched.c | 405 +++ .../timer_scheduler/nrf_802154_timer_sched.h | 158 + 78 files changed, 11249 insertions(+), 6885 deletions(-) create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h delete mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.c rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_ack_pending_bit.h => nrf_802154_ack_pending_bit.h} (85%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_config.h rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_const.h => nrf_802154_const.h} (59%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_fsm.h => nrf_802154_core.h} (53%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_critical_section.h => nrf_802154_critical_section.h} (53%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_debug.c => nrf_802154_debug.c} (95%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_debug.h => nrf_802154_debug.h} (78%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_notification.h => nrf_802154_notification.h} (56%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_direct.c rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_notification_swi.c => nrf_802154_notification_swi.c} (57%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.c rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_pib.h => nrf_802154_pib.h} (70%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_priority_drop.h => nrf_802154_priority_drop.h} (82%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_priority_drop_direct.c => nrf_802154_priority_drop_direct.c} (89%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_priority_drop_swi.c => nrf_802154_priority_drop_swi.c} (84%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_procedures_duration.h => nrf_802154_procedures_duration.h} (72%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_request.h => nrf_802154_request.h} (55%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_revision.c => nrf_802154_revision.c} (92%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_revision.h => nrf_802154_revision.h} (89%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_rx_buffer.c => nrf_802154_rx_buffer.c} (73%) rename third_party/NordicSemiconductor/drivers/radio/{nrf_drv_radio802154_rx_buffer.h => nrf_802154_rx_buffer.h} (83%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_802154_types.h delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_direct.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_swi.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c delete mode 100644 third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h rename third_party/NordicSemiconductor/drivers/radio/platform/clock/{nrf_drv_radio802154_clock.h => nrf_802154_clock.h} (77%) rename third_party/NordicSemiconductor/drivers/radio/platform/clock/{nrf_drv_radio802154_clock_nodrv.c => nrf_802154_clock_nodrv.c} (79%) rename third_party/NordicSemiconductor/drivers/radio/platform/clock/{nrf_drv_radio802154_clock_sdk.c => nrf_802154_clock_sdk.c} (79%) rename third_party/NordicSemiconductor/drivers/radio/platform/timer/{nrf_drv_radio802154_timer.h => nrf_802154_timer.h} (71%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_nodrv.c rename third_party/NordicSemiconductor/drivers/radio/platform/timer/{nrf_drv_radio802154_timer_none.c => nrf_802154_timer_none.c} (87%) create mode 100644 third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.h diff --git a/examples/platforms/nrf52840/Makefile.am b/examples/platforms/nrf52840/Makefile.am index 769b3e281..ad858b1aa 100644 --- a/examples/platforms/nrf52840/Makefile.am +++ b/examples/platforms/nrf52840/Makefile.am @@ -38,7 +38,7 @@ COMMONCPPFLAGS -DCONFIG_GPIO_AS_PINRESET \ -DNRF52840_XXAA \ -DENABLE_FEM=1 \ - -DNRF_DRV_RADIO802154_PROJECT_CONFIG=\"platform-config.h\" \ + -DNRF_802154_PROJECT_CONFIG=\"platform-config.h\" \ -I$(top_srcdir)/include \ -I$(top_srcdir)/examples/platforms \ -I$(top_srcdir)/src/core \ @@ -83,10 +83,9 @@ PLATFORM_COMMON_SOURCES SINGLEPHY_SOURCES = \ flash_nosd.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_direct.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_direct.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_direct.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c \ $(NULL) @@ -98,11 +97,10 @@ SOFTDEVICE_SOURCES flash_sd.c \ softdevice.c \ softdevice.h \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_swi.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_swi.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_swi.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c \ $(NULL) @@ -129,17 +127,19 @@ PLATFORM_SOURCES endif RADIO_DRIVER_SOURCES = \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_sdk.c \ - @top_builddir@/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer_none.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_sdk.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_none.c \ $(NULL) NORDICSEMI_SOURCES = \ @@ -212,29 +212,34 @@ noinst_HEADERS $(top_srcdir)/third_party/NordicSemiconductor/device/nrf52840_peripherals.h \ $(top_srcdir)/third_party/NordicSemiconductor/device/system_nrf52840.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/clock/nrf_drv_clock.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_const.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_procedures_duration.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_config.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_const.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_procedures_duration.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/hal/nrf_radio.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock.h \ - $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.h \ $(top_srcdir)/third_party/NordicSemiconductor/hal/nrf_assert.h \ $(top_srcdir)/third_party/NordicSemiconductor/hal/nrf_clock.h \ $(top_srcdir)/third_party/NordicSemiconductor/hal/nrf_gpio.h \ diff --git a/examples/platforms/nrf52840/diag.c b/examples/platforms/nrf52840/diag.c index f74810a5a..79ee93ae1 100644 --- a/examples/platforms/nrf52840/diag.c +++ b/examples/platforms/nrf52840/diag.c @@ -46,7 +46,7 @@ #include #include -#include +#include #include typedef enum { kDiagTransmitModeIdle, kDiagTransmitModePackets, kDiagTransmitModeCarrier } DiagTrasmitMode; @@ -100,10 +100,10 @@ static void appendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLe static bool startCarrierTransmision(void) { - nrf_drv_radio802154_channel_set(sChannel); - nrf_drv_radio802154_tx_power_set(sTxPower); + nrf_802154_channel_set(sChannel); + nrf_802154_tx_power_set(sTxPower); - return nrf_drv_radio802154_continuous_carrier(); + return nrf_802154_continuous_carrier(); } static void processListen(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) @@ -333,14 +333,14 @@ static void processCcaThreshold(otInstance *aInstance, int argc, char *argv[], c { (void)aInstance; - otError error = OT_ERROR_NONE; - nrf_drv_radio802154_cca_cfg_t ccaConfig; + otError error = OT_ERROR_NONE; + nrf_802154_cca_cfg_t ccaConfig; otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE); if (argc == 0) { - nrf_drv_radio802154_cca_cfg_get(&ccaConfig); + nrf_802154_cca_cfg_get(&ccaConfig); snprintf(aOutput, aOutputMaxLen, "cca threshold: %u\r\n", ccaConfig.ed_threshold); } @@ -355,7 +355,7 @@ static void processCcaThreshold(otInstance *aInstance, int argc, char *argv[], c ccaConfig.mode = NRF_RADIO_CCA_MODE_ED; ccaConfig.ed_threshold = (uint8_t)value; - nrf_drv_radio802154_cca_cfg_set(&ccaConfig); + nrf_802154_cca_cfg_set(&ccaConfig); snprintf(aOutput, aOutputMaxLen, "set cca threshold to %u\r\nstatus 0x%02x\r\n", ccaConfig.ed_threshold, error); } diff --git a/examples/platforms/nrf52840/fem.c b/examples/platforms/nrf52840/fem.c index 34ed19083..da3002ceb 100644 --- a/examples/platforms/nrf52840/fem.c +++ b/examples/platforms/nrf52840/fem.c @@ -41,11 +41,11 @@ #include "platform-fem.h" #define ENABLE_FEM 1 -#include +#include void PlatformFemSetConfigParams(const PlatformFemConfigParams *aConfig) { - nrf_drv_radio802154_fem_control_cfg_t cfg; + nrf_802154_fem_control_cfg_t cfg; memset(&cfg, 0, sizeof(cfg)); @@ -57,9 +57,8 @@ void PlatformFemSetConfigParams(const PlatformFemConfigParams *aConfig) cfg.lna_cfg.gpio_pin = aConfig->mLnaCfg.mGpioPin; cfg.ppi_ch_id_clr = aConfig->mPpiChIdClr; cfg.ppi_ch_id_set = aConfig->mPpiChIdSet; - cfg.radio_ppi_grp = aConfig->mRadioPpiGrp; - cfg.timer_ppi_grp = aConfig->mTimerPpiGrp; - cfg.gpiote_ch_id = aConfig->mGpioteChId; + cfg.pa_gpiote_ch_id = aConfig->mGpiotePaChId; + cfg.lna_gpiote_ch_id = aConfig->mGpioteLnaChId; - nrf_drv_radio802154_fem_control_cfg_set(&cfg); + nrf_802154_fem_control_cfg_set(&cfg); } diff --git a/examples/platforms/nrf52840/platform-config.h b/examples/platforms/nrf52840/platform-config.h index 155861863..adf28a090 100644 --- a/examples/platforms/nrf52840/platform-config.h +++ b/examples/platforms/nrf52840/platform-config.h @@ -352,23 +352,44 @@ ******************************************************************************/ /** - * @def NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES + * @def NRF_802154_PENDING_SHORT_ADDRESSES * * Number of slots containing short addresses of nodes for which pending data is stored. * */ -#ifndef NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES -#define NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES OPENTHREAD_CONFIG_MAX_CHILDREN +#ifndef NRF_802154_PENDING_SHORT_ADDRESSES +#define NRF_802154_PENDING_SHORT_ADDRESSES OPENTHREAD_CONFIG_MAX_CHILDREN #endif /** - * @def NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES + * @def NRF_802154_PENDING_EXTENDED_ADDRESSES * * Number of slots containing extended addresses of nodes for which pending data is stored. * */ -#ifndef NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES -#define NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES OPENTHREAD_CONFIG_MAX_CHILDREN +#ifndef NRF_802154_PENDING_EXTENDED_ADDRESSES +#define NRF_802154_PENDING_EXTENDED_ADDRESSES OPENTHREAD_CONFIG_MAX_CHILDREN +#endif + +/** + * @def NRF_802154_CSMA_CA_ENABLED + * + * If CSMA-CA procedure should be enabled by the driver. Disabling CSMA-CA procedure improves + * driver performance. + * + */ +#ifndef NRF_802154_CSMA_CA_ENABLED +#define NRF_802154_CSMA_CA_ENABLED 0 +#endif + +/** + * @def NRF_802154_ACK_TIMEOUT_ENABLED + * + * If ACK timeout feature should be enabled in the driver. + * + */ +#ifndef NRF_802154_ACK_TIMEOUT_ENABLED +#define NRF_802154_ACK_TIMEOUT_ENABLED 0 #endif #endif // PLATFORM_CONFIG_H_ diff --git a/examples/platforms/nrf52840/platform-fem.h b/examples/platforms/nrf52840/platform-fem.h index c4ead70e1..d279f7ff5 100644 --- a/examples/platforms/nrf52840/platform-fem.h +++ b/examples/platforms/nrf52840/platform-fem.h @@ -94,13 +94,12 @@ typedef struct */ typedef struct { - PlatformFemConfigPaLna mPaCfg; /**< Power Amplifier configuration */ - PlatformFemConfigPaLna mLnaCfg; /**< Low Noise Amplifier configuration */ - uint8_t mPpiChIdSet; /**< PPI channel used for radio pin setting */ - uint8_t mPpiChIdClr; /**< PPI channel used for radio pin clearing */ - uint8_t mTimerPpiGrp; /**< PPI group used for disabling timer match PPI. */ - uint8_t mRadioPpiGrp; /**< PPI group used for disabling radio disabled PPI. */ - uint8_t mGpioteChId; /**< GPIOTE channel used for radio pin toggling */ + PlatformFemConfigPaLna mPaCfg; /**< Power Amplifier configuration */ + PlatformFemConfigPaLna mLnaCfg; /**< Low Noise Amplifier configuration */ + uint8_t mPpiChIdSet; /**< PPI channel used for radio pin setting */ + uint8_t mPpiChIdClr; /**< PPI channel used for radio pin clearing */ + uint8_t mGpiotePaChId; /**< GPIOTE channel used for radio PA pin toggling */ + uint8_t mGpioteLnaChId; /**< GPIOTE channel used for radio LNA pin toggling */ } PlatformFemConfigParams; /** diff --git a/examples/platforms/nrf52840/radio.c b/examples/platforms/nrf52840/radio.c index 5d9ae1217..f56986572 100644 --- a/examples/platforms/nrf52840/radio.c +++ b/examples/platforms/nrf52840/radio.c @@ -51,7 +51,7 @@ #include "platform.h" #include -#include +#include #include #include @@ -74,7 +74,7 @@ enum static bool sDisabled; static otError sReceiveError = OT_ERROR_NONE; -static otRadioFrame sReceivedFrames[NRF_DRV_RADIO802154_RX_BUFFERS]; +static otRadioFrame sReceivedFrames[NRF_802154_RX_BUFFERS]; static otRadioFrame sTransmitFrame; static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE + 1]; @@ -107,7 +107,7 @@ static void dataInit(void) sReceiveError = OT_ERROR_NONE; - for (uint32_t i = 0; i < NRF_DRV_RADIO802154_RX_BUFFERS; i++) + for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++) { sReceivedFrames[i].mPsdu = NULL; } @@ -188,14 +188,14 @@ void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId) uint8_t address[SHORT_ADDRESS_SIZE]; convertShortAddress(address, aPanId); - nrf_drv_radio802154_pan_id_set(address); + nrf_802154_pan_id_set(address); } void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress) { (void)aInstance; - nrf_drv_radio802154_extended_address_set(aExtAddress->m8); + nrf_802154_extended_address_set(aExtAddress->m8); } void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress) @@ -205,18 +205,18 @@ void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress) uint8_t address[SHORT_ADDRESS_SIZE]; convertShortAddress(address, aShortAddress); - nrf_drv_radio802154_short_address_set(address); + nrf_802154_short_address_set(address); } void nrf5RadioInit(void) { dataInit(); - nrf_drv_radio802154_init(); + nrf_802154_init(); } void nrf5RadioDeinit(void) { - nrf_drv_radio802154_deinit(); + nrf_802154_deinit(); } otRadioState otPlatRadioGetState(otInstance *aInstance) @@ -228,16 +228,16 @@ otRadioState otPlatRadioGetState(otInstance *aInstance) return OT_RADIO_STATE_DISABLED; } - switch (nrf_drv_radio802154_state_get()) + switch (nrf_802154_state_get()) { - case NRF_DRV_RADIO802154_STATE_SLEEP: + case NRF_802154_STATE_SLEEP: return OT_RADIO_STATE_SLEEP; - case NRF_DRV_RADIO802154_STATE_RECEIVE: - case NRF_DRV_RADIO802154_STATE_ENERGY_DETECTION: + case NRF_802154_STATE_RECEIVE: + case NRF_802154_STATE_ENERGY_DETECTION: return OT_RADIO_STATE_RECEIVE; - case NRF_DRV_RADIO802154_STATE_TRANSMIT: + case NRF_802154_STATE_TRANSMIT: return OT_RADIO_STATE_TRANSMIT; default: @@ -296,7 +296,7 @@ otError otPlatRadioSleep(otInstance *aInstance) { (void)aInstance; - if (nrf_drv_radio802154_sleep()) + if (nrf_802154_sleep()) { clearPendingEvents(); } @@ -313,12 +313,14 @@ otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) { (void)aInstance; - nrf_drv_radio802154_channel_set(aChannel); - nrf_drv_radio802154_tx_power_set(sDefaultTxPower); - nrf_drv_radio802154_receive(); + bool result; + + nrf_802154_channel_set(aChannel); + nrf_802154_tx_power_set(sDefaultTxPower); + result = nrf_802154_receive(); clearPendingEvents(); - return OT_ERROR_NONE; + return result ? OT_ERROR_NONE : OT_ERROR_INVALID_STATE; } otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) @@ -327,9 +329,9 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) aFrame->mPsdu[-1] = aFrame->mLength; - nrf_drv_radio802154_channel_set(aFrame->mChannel); + nrf_802154_channel_set(aFrame->mChannel); - if (nrf_drv_radio802154_transmit_raw(&aFrame->mPsdu[-1], true)) + if (nrf_802154_transmit_raw(&aFrame->mPsdu[-1], true)) { clearPendingEvents(); otPlatRadioTxStarted(aInstance, aFrame); @@ -354,7 +356,7 @@ int8_t otPlatRadioGetRssi(otInstance *aInstance) { (void)aInstance; - return nrf_drv_radio802154_rssi_last_get(); + return nrf_802154_rssi_last_get(); } otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) @@ -368,21 +370,21 @@ bool otPlatRadioGetPromiscuous(otInstance *aInstance) { (void)aInstance; - return nrf_drv_radio802154_promiscuous_get(); + return nrf_802154_promiscuous_get(); } void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) { (void)aInstance; - nrf_drv_radio802154_promiscuous_set(aEnable); + nrf_802154_promiscuous_set(aEnable); } void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) { (void)aInstance; - nrf_drv_radio802154_auto_pending_bit_set(aEnable); + nrf_802154_auto_pending_bit_set(aEnable); } otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) @@ -394,7 +396,7 @@ otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t a uint8_t shortAddress[SHORT_ADDRESS_SIZE]; convertShortAddress(shortAddress, aShortAddress); - if (nrf_drv_radio802154_pending_bit_for_addr_set(shortAddress, false)) + if (nrf_802154_pending_bit_for_addr_set(shortAddress, false)) { error = OT_ERROR_NONE; } @@ -412,7 +414,7 @@ otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress otError error; - if (nrf_drv_radio802154_pending_bit_for_addr_set(aExtAddress->m8, true)) + if (nrf_802154_pending_bit_for_addr_set(aExtAddress->m8, true)) { error = OT_ERROR_NONE; } @@ -433,7 +435,7 @@ otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t uint8_t shortAddress[SHORT_ADDRESS_SIZE]; convertShortAddress(shortAddress, aShortAddress); - if (nrf_drv_radio802154_pending_bit_for_addr_clear(shortAddress, false)) + if (nrf_802154_pending_bit_for_addr_clear(shortAddress, false)) { error = OT_ERROR_NONE; } @@ -451,7 +453,7 @@ otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddre otError error; - if (nrf_drv_radio802154_pending_bit_for_addr_clear(aExtAddress->m8, true)) + if (nrf_802154_pending_bit_for_addr_clear(aExtAddress->m8, true)) { error = OT_ERROR_NONE; } @@ -467,14 +469,14 @@ void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) { (void)aInstance; - nrf_drv_radio802154_pending_bit_for_addr_reset(false); + nrf_802154_pending_bit_for_addr_reset(false); } void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) { (void)aInstance; - nrf_drv_radio802154_pending_bit_for_addr_reset(true); + nrf_802154_pending_bit_for_addr_reset(true); } otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) @@ -486,9 +488,9 @@ otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint1 clearPendingEvents(); - nrf_drv_radio802154_channel_set(aScanChannel); + nrf_802154_channel_set(aScanChannel); - if (nrf_drv_radio802154_energy_detection(sEnergyDetectionTime)) + if (nrf_802154_energy_detection(sEnergyDetectionTime)) { resetPendingEvent(kPendingEventEnergyDetectionStart); } @@ -522,14 +524,14 @@ otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) (void)aInstance; sDefaultTxPower = aPower; - nrf_drv_radio802154_tx_power_set(aPower); + nrf_802154_tx_power_set(aPower); return OT_ERROR_NONE; } void nrf5RadioProcess(otInstance *aInstance) { - for (uint32_t i = 0; i < NRF_DRV_RADIO802154_RX_BUFFERS; i++) + for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++) { if (sReceivedFrames[i].mPsdu != NULL) { @@ -547,15 +549,15 @@ void nrf5RadioProcess(otInstance *aInstance) uint8_t *bufferAddress = &sReceivedFrames[i].mPsdu[-1]; sReceivedFrames[i].mPsdu = NULL; - nrf_drv_radio802154_buffer_free_raw(bufferAddress); + nrf_802154_buffer_free_raw(bufferAddress); } } if (isPendingEventSet(kPendingEventTransmit)) { - nrf_drv_radio802154_channel_set(sTransmitFrame.mChannel); + nrf_802154_channel_set(sTransmitFrame.mChannel); - if (nrf_drv_radio802154_transmit_raw(sTransmitPsdu, true)) + if (nrf_802154_transmit_raw(sTransmitPsdu, true)) { resetPendingEvent(kPendingEventTransmit); otPlatRadioTxStarted(aInstance, &sTransmitFrame); @@ -579,7 +581,7 @@ void nrf5RadioProcess(otInstance *aInstance) if (sAckFrame.mPsdu != NULL) { - nrf_drv_radio802154_buffer_free_raw(sAckFrame.mPsdu - 1); + nrf_802154_buffer_free_raw(sAckFrame.mPsdu - 1); sAckFrame.mPsdu = NULL; } @@ -646,7 +648,7 @@ void nrf5RadioProcess(otInstance *aInstance) if (isPendingEventSet(kPendingEventSleep)) { - if (nrf_drv_radio802154_sleep()) + if (nrf_802154_sleep()) { resetPendingEvent(kPendingEventSleep); } @@ -654,20 +656,20 @@ void nrf5RadioProcess(otInstance *aInstance) if (isPendingEventSet(kPendingEventEnergyDetectionStart)) { - nrf_drv_radio802154_channel_set(sEnergyDetectionChannel); + nrf_802154_channel_set(sEnergyDetectionChannel); - if (nrf_drv_radio802154_energy_detection(sEnergyDetectionTime)) + if (nrf_802154_energy_detection(sEnergyDetectionTime)) { resetPendingEvent(kPendingEventEnergyDetectionStart); } } } -void nrf_drv_radio802154_received_raw(uint8_t *p_data, int8_t power, int8_t lqi) +void nrf_802154_received_raw(uint8_t *p_data, int8_t power, uint8_t lqi) { otRadioFrame *receivedFrame = NULL; - for (uint32_t i = 0; i < NRF_DRV_RADIO802154_RX_BUFFERS; i++) + for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++) { if (sReceivedFrames[i].mPsdu == NULL) { @@ -684,7 +686,7 @@ void nrf_drv_radio802154_received_raw(uint8_t *p_data, int8_t power, int8_t lqi) receivedFrame->mLength = p_data[0]; receivedFrame->mRssi = power; receivedFrame->mLqi = lqi; - receivedFrame->mChannel = nrf_drv_radio802154_channel_get(); + receivedFrame->mChannel = nrf_802154_channel_get(); #if OPENTHREAD_ENABLE_RAW_LINK_API uint64_t timestamp = nrf5AlarmGetCurrentTime(); receivedFrame->mMsec = timestamp / US_PER_MS; @@ -694,24 +696,24 @@ void nrf_drv_radio802154_received_raw(uint8_t *p_data, int8_t power, int8_t lqi) PlatformEventSignalPending(); } -void nrf_drv_radio802154_receive_failed(nrf_drv_radio802154_rx_error_t error) +void nrf_802154_receive_failed(nrf_802154_rx_error_t error) { switch (error) { - case NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME: + case NRF_802154_RX_ERROR_INVALID_FRAME: sReceiveError = OT_ERROR_NO_FRAME_RECEIVED; break; - case NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS: + case NRF_802154_RX_ERROR_INVALID_FCS: sReceiveError = OT_ERROR_FCS; break; - case NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR: + case NRF_802154_RX_ERROR_INVALID_DEST_ADDR: sReceiveError = OT_ERROR_DESTINATION_ADDRESS_FILTERED; break; - case NRF_DRV_RADIO802154_RX_ERROR_RUNTIME: - case NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED: + case NRF_802154_RX_ERROR_RUNTIME: + case NRF_802154_RX_ERROR_TIMESLOT_ENDED: sReceiveError = OT_ERROR_FAILED; break; @@ -722,8 +724,10 @@ void nrf_drv_radio802154_receive_failed(nrf_drv_radio802154_rx_error_t error) setPendingEvent(kPendingEventReceiveFailed); } -void nrf_drv_radio802154_transmitted_raw(uint8_t *aAckPsdu, int8_t aPower, int8_t aLqi) +void nrf_802154_transmitted_raw(const uint8_t *aFrame, uint8_t *aAckPsdu, int8_t aPower, uint8_t aLqi) { + assert(aFrame == sTransmitPsdu); + if (aAckPsdu == NULL) { sAckFrame.mPsdu = NULL; @@ -734,31 +738,33 @@ void nrf_drv_radio802154_transmitted_raw(uint8_t *aAckPsdu, int8_t aPower, int8_ sAckFrame.mLength = aAckPsdu[0]; sAckFrame.mRssi = aPower; sAckFrame.mLqi = aLqi; - sAckFrame.mChannel = nrf_drv_radio802154_channel_get(); + sAckFrame.mChannel = nrf_802154_channel_get(); } setPendingEvent(kPendingEventFrameTransmitted); } -void nrf_drv_radio802154_transmit_failed(nrf_drv_radio802154_tx_error_t error) +void nrf_802154_transmit_failed(const uint8_t *aFrame, nrf_802154_tx_error_t error) { + assert(aFrame == sTransmitPsdu); + switch (error) { - case NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL: - case NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED: + case NRF_802154_TX_ERROR_BUSY_CHANNEL: + case NRF_802154_TX_ERROR_TIMESLOT_ENDED: setPendingEvent(kPendingEventChannelAccessFailure); break; - case NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK: - case NRF_DRV_RADIO802154_TX_ERROR_NO_MEM: + case NRF_802154_TX_ERROR_INVALID_ACK: + case NRF_802154_TX_ERROR_NO_MEM: setPendingEvent(kPendingEventInvalidAck); break; } } -void nrf_drv_radio802154_energy_detected(uint8_t result) +void nrf_802154_energy_detected(uint8_t result) { - sEnergyDetected = nrf_drv_radio802154_dbm_from_energy_level_calculate(result); + sEnergyDetected = nrf_802154_dbm_from_energy_level_calculate(result); setPendingEvent(kPendingEventEnergyDetected); } diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control.c new file mode 100644 index 000000000..47c81dedc --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control.c @@ -0,0 +1,364 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements common function for Front End Module control of the nRF 802.15.4 radio driver. + * + */ + +#include "nrf_fem_control_api.h" + +#include + +#include "compiler_abstraction.h" +#include "nrf_fem_control_config.h" +#include "nrf_802154_config.h" +#include "nrf.h" +#include "hal/nrf_gpio.h" +#include "hal/nrf_gpiote.h" +#include "hal/nrf_ppi.h" +#include "hal/nrf_radio.h" +#include "hal/nrf_timer.h" + +#define NRF_FEM_TIMER_INSTANCE NRF_802154_TIMER_INSTANCE + +#if ENABLE_FEM + +static nrf_fem_control_cfg_t m_nrf_fem_control_cfg; /**< FEM controller configuration. */ + +/** Check whether pin is valid and enabled. */ +static bool pin_is_enabled(nrf_fem_control_pin_t pin) +{ + switch (pin) + { + case NRF_FEM_CONTROL_LNA_PIN: + return m_nrf_fem_control_cfg.lna_cfg.enable; + + case NRF_FEM_CONTROL_PA_PIN: + return m_nrf_fem_control_cfg.pa_cfg.enable; + + case NRF_FEM_CONTROL_ANY_PIN: + return m_nrf_fem_control_cfg.lna_cfg.enable || m_nrf_fem_control_cfg.pa_cfg.enable; + + default: + assert(false); + return false; + } +} + +/** + * @section GPIO control. + */ + +/** Initialize GPIO according to configuration provided. */ +static void gpio_init(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable) + { + nrf_gpio_cfg_output(m_nrf_fem_control_cfg.pa_cfg.gpio_pin); + nrf_gpio_pin_write(m_nrf_fem_control_cfg.pa_cfg.gpio_pin, + !m_nrf_fem_control_cfg.pa_cfg.active_high); + } + + if (m_nrf_fem_control_cfg.lna_cfg.enable) + { + nrf_gpio_cfg_output(m_nrf_fem_control_cfg.lna_cfg.gpio_pin); + nrf_gpio_pin_write(m_nrf_fem_control_cfg.lna_cfg.gpio_pin, + !m_nrf_fem_control_cfg.lna_cfg.active_high); + } +} + +/** Configure GPIOTE module. */ +static void gpiote_configure(void) +{ + nrf_gpiote_task_configure(m_nrf_fem_control_cfg.lna_gpiote_ch_id, + m_nrf_fem_control_cfg.lna_cfg.gpio_pin, + (nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None, + (nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.lna_cfg.active_high); + + nrf_gpiote_task_enable(m_nrf_fem_control_cfg.lna_gpiote_ch_id); + + nrf_gpiote_task_configure(m_nrf_fem_control_cfg.pa_gpiote_ch_id, + m_nrf_fem_control_cfg.pa_cfg.gpio_pin, + (nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None, + (nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.pa_cfg.active_high); + + nrf_gpiote_task_enable(m_nrf_fem_control_cfg.pa_gpiote_ch_id); +} + +/** + * @section PPI control. + */ + +/** Initialize PPI according to configuration provided. */ +static void ppi_init(void) +{ + /* RADIO DISABLED --> clr LNA & clr PA PPI */ + nrf_ppi_channel_and_fork_endpoint_setup( + (nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr, + (uint32_t)(&NRF_RADIO->EVENTS_DISABLED), + (m_nrf_fem_control_cfg.lna_cfg.active_high ? + (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]) : + (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id])), + (m_nrf_fem_control_cfg.pa_cfg.active_high ? + (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]) : + (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]))); +} + +/** Setup PPI to set LNA pin on a timer event. */ +static void ppi_lna_enable_setup(nrf_timer_cc_channel_t timer_cc_channel) +{ + /* TIMER0->COMPARE --> set LNA PPI */ + nrf_ppi_channel_endpoint_setup( + (nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set, + (uint32_t)(&NRF_FEM_TIMER_INSTANCE->EVENTS_COMPARE[timer_cc_channel]), + (m_nrf_fem_control_cfg.lna_cfg.active_high ? + (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id]) : + (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]))); +} + +/** Setup PPI to set PA pin on a timer event. */ +static void ppi_pa_enable_setup(nrf_timer_cc_channel_t timer_cc_channel) +{ + /* TIMER2->COMPARE --> set PA PPI */ + nrf_ppi_channel_endpoint_setup( + (nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set, + (uint32_t)(&NRF_FEM_TIMER_INSTANCE->EVENTS_COMPARE[timer_cc_channel]), + (m_nrf_fem_control_cfg.pa_cfg.active_high ? + (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]) : + (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]))); +} + +/** + * @section FEM API functions. + */ + +void nrf_fem_control_cfg_set(const nrf_fem_control_cfg_t * p_cfg) +{ + m_nrf_fem_control_cfg = *p_cfg; + + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + gpio_init(); + gpiote_configure(); + ppi_init(); + + nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr); + } +} + +void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg) +{ + *p_cfg = m_nrf_fem_control_cfg; +} + +void nrf_fem_control_activate(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr); + } +} + +void nrf_fem_control_deactivate(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr); + nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set); + } +} + +void nrf_fem_control_ppi_enable(nrf_fem_control_pin_t pin, nrf_timer_cc_channel_t timer_cc_channel) +{ + if (pin_is_enabled(pin)) + { + switch (pin) + { + case NRF_FEM_CONTROL_LNA_PIN: + ppi_lna_enable_setup(timer_cc_channel); + nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set); + break; + + case NRF_FEM_CONTROL_PA_PIN: + ppi_pa_enable_setup(timer_cc_channel); + nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set); + break; + + default: + assert(false); + break; + } + } +} + +void nrf_fem_control_ppi_disable(nrf_fem_control_pin_t pin) +{ + if (pin_is_enabled(pin)) + { + nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set); + } +} + +uint32_t nrf_fem_control_delay_get(nrf_fem_control_pin_t pin) +{ + uint32_t target_time = 1; + + if (pin_is_enabled(pin)) + { + switch (pin) + { + case NRF_FEM_CONTROL_LNA_PIN: + target_time = NRF_FEM_RADIO_RX_STARTUP_LATENCY_US - NRF_FEM_LNA_TIME_IN_ADVANCE; + break; + + case NRF_FEM_CONTROL_PA_PIN: + target_time = NRF_FEM_RADIO_TX_STARTUP_LATENCY_US - NRF_FEM_PA_TIME_IN_ADVANCE; + break; + + default: + assert(false); + break; + } + } + + return target_time; +} + +void nrf_fem_control_pin_clear(void) +{ + if (pin_is_enabled(NRF_FEM_CONTROL_PA_PIN)) + { + nrf_gpio_pin_write(m_nrf_fem_control_cfg.pa_cfg.gpio_pin, + !m_nrf_fem_control_cfg.pa_cfg.active_high); + } + + if (pin_is_enabled(NRF_FEM_CONTROL_LNA_PIN)) + { + nrf_gpio_pin_write(m_nrf_fem_control_cfg.lna_cfg.gpio_pin, + !m_nrf_fem_control_cfg.lna_cfg.active_high); + } +} + +void nrf_fem_control_timer_set(nrf_fem_control_pin_t pin, + nrf_timer_cc_channel_t timer_cc_channel, + nrf_timer_short_mask_t short_mask) +{ + if (pin_is_enabled(pin)) + { + uint32_t target_time = nrf_fem_control_delay_get(pin); + nrf_timer_shorts_enable(NRF_FEM_TIMER_INSTANCE, short_mask); + nrf_timer_cc_write(NRF_FEM_TIMER_INSTANCE, timer_cc_channel, target_time); + } +} + +void nrf_fem_control_timer_reset(nrf_fem_control_pin_t pin, nrf_timer_short_mask_t short_mask) +{ + if (pin_is_enabled(pin)) + { + nrf_timer_task_trigger(NRF_FEM_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_FEM_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + nrf_timer_shorts_disable(NRF_FEM_TIMER_INSTANCE, short_mask); + } +} + +void nrf_fem_control_ppi_fork_setup(nrf_fem_control_pin_t pin, + nrf_ppi_channel_t ppi_channel, + uint32_t task_addr) +{ + if (pin_is_enabled(pin)) + { + nrf_ppi_fork_endpoint_setup(ppi_channel, task_addr); + } +} + +void nrf_fem_control_ppi_task_setup(nrf_fem_control_pin_t pin, + nrf_ppi_channel_t ppi_channel, + uint32_t event_addr, + uint32_t task_addr) +{ + if (pin_is_enabled(pin)) + { + nrf_ppi_channel_endpoint_setup(ppi_channel, event_addr, task_addr); + nrf_ppi_channel_enable(ppi_channel); + } +} + +void nrf_fem_control_ppi_fork_clear(nrf_fem_control_pin_t pin, nrf_ppi_channel_t ppi_channel) +{ + if (pin_is_enabled(pin)) + { + nrf_ppi_fork_endpoint_setup(ppi_channel, 0); + } +} + +void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel, + uint32_t event_addr, + bool lna_pin_set, + bool pa_pin_set) +{ + uint32_t lna_task_addr = 0; + uint32_t pa_task_addr = 0; + + if (m_nrf_fem_control_cfg.lna_cfg.enable) + { + if ((lna_pin_set && m_nrf_fem_control_cfg.lna_cfg.active_high) || + (!lna_pin_set && !m_nrf_fem_control_cfg.lna_cfg.active_high)) + { + lna_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id]); + } + else + { + lna_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]); + } + } + + if (m_nrf_fem_control_cfg.pa_cfg.enable) + { + if ((pa_pin_set && m_nrf_fem_control_cfg.pa_cfg.active_high) || + (!pa_pin_set && !m_nrf_fem_control_cfg.pa_cfg.active_high)) + { + pa_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]); + } + else + { + pa_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]); + } + } + + if (lna_task_addr != 0 || pa_task_addr != 0) + { + nrf_ppi_channel_and_fork_endpoint_setup(ppi_channel, event_addr, lna_task_addr, pa_task_addr); + nrf_ppi_channel_enable(ppi_channel); + } +} + +#endif // ENABLE_FEM diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h index decd3cc54..ae0fb93d7 100644 --- a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +39,9 @@ #include #include +#include "hal/nrf_ppi.h" +#include "hal/nrf_timer.h" + #ifdef __cplusplus extern "C" { #endif @@ -59,14 +62,11 @@ extern "C" { /** Default PPI channel for pin clearing. */ #define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 19 -/** Default PPI channel group used to disable timer match PPI. */ -#define NRF_FEM_CONTROL_DEFAULT_TIMER_MATCH_PPI_GROUP 4 - -/** Default PPI channel group used to disable radio disabled PPI. */ -#define NRF_FEM_CONTROL_DEFAULT_RADIO_DISABLED_PPI_GROUP 5 +/** Default GPIOTE channel for FEM control. */ +#define NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL 6 /** Default GPIOTE channel for FEM control. */ -#define NRF_FEM_CONTROL_DEFAULT_GPIOTE_CHANNEL 7 +#define NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL 7 #if ENABLE_FEM @@ -94,15 +94,24 @@ typedef struct */ typedef struct { - nrf_fem_control_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */ - nrf_fem_control_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */ - uint8_t ppi_ch_id_set; /**< PPI channel used for radio pin setting */ - uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */ - uint8_t timer_ppi_grp; /**< PPI group used for disabling timer match PPI. */ - uint8_t radio_ppi_grp; /**< PPI group used for disabling radio disabled PPI. */ - uint8_t gpiote_ch_id; /**< GPIOTE channel used for radio pin toggling */ + nrf_fem_control_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */ + nrf_fem_control_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */ + uint8_t pa_gpiote_ch_id; /**< GPIOTE channel used for Power Amplifier pin toggling */ + uint8_t lna_gpiote_ch_id; /**< GPIOTE channel used for Low Noise Amplifier pin toggling */ + uint8_t ppi_ch_id_set; /**< PPI channel used for radio Power Amplifier and Low Noise Amplifier pins setting */ + uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */ } nrf_fem_control_cfg_t; +/** + * @brief Hardware pins controlled by the Front End Module. + */ +typedef enum +{ + NRF_FEM_CONTROL_PA_PIN, + NRF_FEM_CONTROL_LNA_PIN, + NRF_FEM_CONTROL_ANY_PIN, +} nrf_fem_control_pin_t; + /**@brief Set PA & LNA GPIO toggle configuration. * * @note This function shall not be called when radio is in use. @@ -125,44 +134,105 @@ void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg); */ void nrf_fem_control_activate(void); -/**@brief De-activate FEM controller. +/**@brief Deactivate FEM controller. * * This function should be called when radio goes to sleep. */ void nrf_fem_control_deactivate(void); -/**@brief Latch current time in FEM controller. +/**@brief Configure PPI to activate one of the Front End Module pins on an appropriate timer event. + * + * @param[in] pin The Front End Module controlled pin to be connected to the PPI. + * @param[in] timer_cc_channel Timer CC channel that triggers the @p pin activation through the PPI. * - * This function stores current time to enable precise time measurement and mitigate impact of code - * execution time. It should be called before triggering RXEN or TXEN task, and calling - * @ref nrf_fem_control_pa_set or @ref nrf_fem_control_lna_set funcitons. */ -void nrf_fem_control_time_latch(void); +void nrf_fem_control_ppi_enable(nrf_fem_control_pin_t pin, nrf_timer_cc_channel_t timer_cc_channel); -/**@brief Activate Power Amplifier (TX) pin of the Front End Module. +/**@brief Clear PPI configuration used to activate one of Front End Module pins. * - * @param[in] shorts_used Information if this operation is related to a task triggered by a short. - * @param[in] turnaround Information if TX mode is entered from RX mode (turnaround) or DISABLED (ramp up). + * @param[in] pin The Front End Module controlled pin to be disconnected from the PPI. * - * This function will set up a timer to activate the pin 5 +/- 2.5 us before radio READY event is generated. - * It will also set up a PPI to deactivate the pin on radio DISABLED event. - * - * @note This function shall always be called after @ref nrf_fem_control_time_latch function was called, - * to enable precise time measurement. - * */ -void nrf_fem_control_pa_set(bool shorts_used, bool turnaround); + */ +void nrf_fem_control_ppi_disable(nrf_fem_control_pin_t pin); -/**@brief Activate Low Noise Amplifier (RX) pin of the Front End Module. +/**@brief Calculate target time for a timer, which activates one of the Front End Module pins. + * + * @param[in] pin The Front End Module controlled pin to be activated. + * + * @return @p pin activation delay in microseconds. * - * @param[in] shorts_used Information if this operation is related to a task triggered by a short. + */ +uint32_t nrf_fem_control_delay_get(nrf_fem_control_pin_t pin); + +/**@brief Clear the Power Amplifier and the Low Noise Amplifier pins immediately. * - * This function will set up a timer to activate the pin 5 +/- 2.5 us before radio READY event is generated. - * It will also set up a PPI to deactivate the pin on radio DISABLED event. + */ +void nrf_fem_control_pin_clear(void); + +/**@brief Configure and set a timer for one of the Front End Module pins activation. + * + * @param[in] pin The Front End Module controlled pin to be activated. + * @param[in] timer_cc_channel Timer CC channel to set. + * @param[in] short_mask Mask of timer shortcuts to be enabled. * - * @note This function shall always be called after @ref nrf_fem_control_time_latch function was called, - * to enable precise time measurement. - * */ -void nrf_fem_control_lna_set(bool shorts_used); + */ +void nrf_fem_control_timer_set(nrf_fem_control_pin_t pin, + nrf_timer_cc_channel_t timer_cc_channel, + nrf_timer_short_mask_t short_mask); + +/**@brief Clear timer configuration after one of the Front End Module pins deactivation. + * + * @param[in] pin The Front End Module controlled pin that was deactivated. + * @param[in] short_mask Mask of timer shortcuts to be disabled. + * + */ +void nrf_fem_control_timer_reset(nrf_fem_control_pin_t pin, nrf_timer_short_mask_t short_mask); + +/**@brief Setup a PPI fork task necessary for one of the Front End Module pins. + * + * @param[in] pin The Front End Module controlled pin that was deactivated. + * @param[in] ppi_channel PPI channel to connect the fork task to. + * + */ +void nrf_fem_control_ppi_fork_setup(nrf_fem_control_pin_t pin, + nrf_ppi_channel_t ppi_channel, + uint32_t task_addr); + +/**@brief Setup a PPI task necessary for one of the Front End Module pins. + * + * @param[in] pin The Front End Module controlled pin that was deactivated. + * @param[in] ppi_channel PPI channel to connect the task to. + * @param[in] event_addr Address of the event to be connected to the PPI. + * @param[in] task_addr Address of the task to be connected to the PPI. + * + */ +void nrf_fem_control_ppi_task_setup(nrf_fem_control_pin_t pin, + nrf_ppi_channel_t ppi_channel, + uint32_t event_addr, + uint32_t task_addr); + +/**@brief Clear a PPI fork task configuration for one of the Front End Module pins. + * + * @param[in] pin The Front End Module controlled pin that was deactivated. + * @param[in] ppi_channel PPI channel to disconnect the fork task from. + * + */ +void nrf_fem_control_ppi_fork_clear(nrf_fem_control_pin_t pin, nrf_ppi_channel_t ppi_channel); + +/**@brief Setup PPI task and fork that set or clear Front End Module pins on a given event. + * + * @param[in] ppi_channel PPI channel to connect the task and fork to. + * @param[in] event_addr Address of the event to be connected to the PPI. + * @param[in] lna_pin_set If true, the Low Noise Amplifier pin will be set on the event @p event_addr. + * Otherwise, it will be cleared. + * @param[in] pa_pin_set If true, the Power Amplifier pin will be set on the event @p event_addr. + * Otherwise, it will be cleared. + * + */ +void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel, + uint32_t event_addr, + bool lna_pin_set, + bool pa_pin_set); #else // ENABLE_FEM @@ -170,9 +240,17 @@ void nrf_fem_control_lna_set(bool shorts_used); #define nrf_fem_control_cfg_get(...) #define nrf_fem_control_activate(...) #define nrf_fem_control_deactivate(...) -#define nrf_fem_control_time_latch(...) -#define nrf_fem_control_pa_set(...) -#define nrf_fem_control_lna_set(...) +#define nrf_fem_control_ppi_enable(...) +#define nrf_fem_control_ppi_disable(...) +#define nrf_fem_control_delay_get(...) 1 +#define nrf_fem_control_pin_clear(...) +#define nrf_fem_control_timer_set(...) +#define nrf_fem_control_timer_reset(...) +#define nrf_fem_control_ppi_fork_setup(...) +#define nrf_fem_control_ppi_task_setup(...) +#define nrf_fem_control_ppi_task_and_fork_setup(...) +#define nrf_fem_control_ppi_fork_clear(...) +#define nrf_fem_control_ppi_pin_task_setup(...) #endif // ENABLE_FEM diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c deleted file mode 100644 index 8216d96ef..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c +++ /dev/null @@ -1,224 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements common function for Front End Module control of the nRF 802.15.4 radio driver. - * - */ - -#include "nrf_fem_control_api.h" - -#include "compiler_abstraction.h" -#include "nrf_fem_control_config.h" -#include "nrf_fem_control_internal.h" -#include "nrf.h" -#include "hal/nrf_gpio.h" -#include "hal/nrf_gpiote.h" -#include "hal/nrf_ppi.h" -#include "hal/nrf_radio.h" - -static nrf_fem_control_cfg_t m_nrf_fem_control_cfg; /**< FEM controller configuration. */ -static volatile uint32_t m_time_latch; /**< Recently latched timer value. */ - -/** - * @section GPIO control. - */ - -/** Initialize GPIO according to configuration provided. */ -static void gpio_init(void) -{ - if (m_nrf_fem_control_cfg.pa_cfg.enable) - { - nrf_gpio_cfg_output(m_nrf_fem_control_cfg.pa_cfg.gpio_pin); - nrf_gpio_pin_write(m_nrf_fem_control_cfg.pa_cfg.gpio_pin, - !m_nrf_fem_control_cfg.pa_cfg.active_high); - } - - if (m_nrf_fem_control_cfg.lna_cfg.enable) - { - nrf_gpio_cfg_output(m_nrf_fem_control_cfg.lna_cfg.gpio_pin); - nrf_gpio_pin_write(m_nrf_fem_control_cfg.lna_cfg.gpio_pin, - !m_nrf_fem_control_cfg.lna_cfg.active_high); - } -} - -/** Configure GPIOTE task. */ -__STATIC_INLINE void gpiote_configure(uint8_t pin, nrf_gpiote_outinit_t init_val) -{ - nrf_gpiote_task_configure(m_nrf_fem_control_cfg.gpiote_ch_id, - pin, - NRF_GPIOTE_POLARITY_TOGGLE, - init_val); - - nrf_gpiote_task_enable(m_nrf_fem_control_cfg.gpiote_ch_id); -} - -/** - * @section PPI control. - */ - -/** Initialize PPI according to configuration provided. */ -static void ppi_init(void) -{ - nrf_ppi_channel_include_in_group((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set, - (nrf_ppi_channel_group_t)m_nrf_fem_control_cfg.timer_ppi_grp); - nrf_ppi_channel_include_in_group((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr, - (nrf_ppi_channel_group_t)m_nrf_fem_control_cfg.radio_ppi_grp); - - nrf_ppi_channel_and_fork_endpoint_setup( - (nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set, - (uint32_t)(&NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_FEM]), - (uint32_t)(&NRF_GPIOTE->TASKS_OUT[m_nrf_fem_control_cfg.gpiote_ch_id]), - (uint32_t)(&NRF_PPI->TASKS_CHG[m_nrf_fem_control_cfg.timer_ppi_grp].DIS)); - - // Workaround for FTPAN-114, disable PPI to prevent second radio DISABLED event trigger. - nrf_ppi_channel_and_fork_endpoint_setup( - (nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr, - (uint32_t)(&NRF_RADIO->EVENTS_DISABLED), - (uint32_t)(&NRF_GPIOTE->TASKS_OUT[m_nrf_fem_control_cfg.gpiote_ch_id]), - (uint32_t)(&NRF_PPI->TASKS_CHG[m_nrf_fem_control_cfg.radio_ppi_grp].DIS)); -} - -/** Enable PPI. */ -__STATIC_INLINE void ppi_enable(void) -{ - NRF_PPI->CHENSET = (1 << m_nrf_fem_control_cfg.ppi_ch_id_set) | - (1 << m_nrf_fem_control_cfg.ppi_ch_id_clr); -} - -/** Disable PPI. */ -__STATIC_INLINE void ppi_disable(void) -{ - NRF_PPI->CHENCLR = (1 << m_nrf_fem_control_cfg.ppi_ch_id_set) | - (1 << m_nrf_fem_control_cfg.ppi_ch_id_clr); -} - -/** - * @section FEM API functions. - */ - -void nrf_fem_control_cfg_set(const nrf_fem_control_cfg_t * p_cfg) -{ - m_nrf_fem_control_cfg = *p_cfg; - - if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) - { - gpio_init(); - ppi_init(); - nrf_fem_control_timer_init(); - } - else - { - nrf_fem_control_timer_deinit(); - } -} - -void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg) -{ - *p_cfg = m_nrf_fem_control_cfg; -} - -void nrf_fem_control_activate(void) -{ - if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) - { - nrf_fem_control_timer_start(); - } -} - -void nrf_fem_control_deactivate(void) -{ - if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) - { - nrf_fem_control_timer_stop(); - nrf_gpiote_task_disable(m_nrf_fem_control_cfg.gpiote_ch_id); - ppi_disable(); - } -} - -void nrf_fem_control_time_latch(void) -{ - if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) - { - m_time_latch = nrf_fem_control_timer_time_get(); - } -} - -void nrf_fem_control_pa_set(bool shorts_used, bool turnaround) -{ - uint32_t target_time; - uint32_t latency; - - latency = turnaround ? NRF_FEM_RADIO_TX_TURNAROUND_LATENCY_US : - NRF_FEM_RADIO_TX_STARTUP_LATENCY_US; - - if (m_nrf_fem_control_cfg.pa_cfg.enable) - { - gpiote_configure(m_nrf_fem_control_cfg.pa_cfg.gpio_pin, - (nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.pa_cfg.active_high); - ppi_enable(); - - uint32_t tifs = nrf_radio_ifs_get(); - - target_time = tifs <= latency ? - m_time_latch + latency - NRF_FEM_PA_TIME_IN_ADVANCE : - m_time_latch + tifs - NRF_FEM_RADIO_TIFS_DRIFT_US - NRF_FEM_PA_TIME_IN_ADVANCE; - - if (shorts_used) - { - target_time -= nrf_fem_control_irq_delay_get(); - } - - nrf_fem_control_timer_set(target_time); - } -} - -void nrf_fem_control_lna_set(bool shorts_used) -{ - uint32_t target_time; - - if (m_nrf_fem_control_cfg.lna_cfg.enable) - { - gpiote_configure(m_nrf_fem_control_cfg.lna_cfg.gpio_pin, - (nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.lna_cfg.active_high); - ppi_enable(); - - target_time = m_time_latch + NRF_FEM_RADIO_RX_STARTUP_LATENCY_US - - NRF_FEM_LNA_TIME_IN_ADVANCE; - - if (shorts_used) - { - target_time -= nrf_fem_control_irq_delay_get(); - } - - nrf_fem_control_timer_set(target_time); - } -} diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h index f964223f2..87699a2e2 100644 --- a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ extern "C" { */ /** Time in us when PA GPIO is activated before radio is ready for transmission. */ -#define NRF_FEM_PA_TIME_IN_ADVANCE 5 +#define NRF_FEM_PA_TIME_IN_ADVANCE 23 /** Time in us when LNA GPIO is activated before radio is ready for reception. */ #define NRF_FEM_LNA_TIME_IN_ADVANCE 5 @@ -53,15 +53,6 @@ extern "C" { /** Radio ramp-up time in RX mode, in us. */ #define NRF_FEM_RADIO_RX_STARTUP_LATENCY_US 40 -/** Radio turnaround from RX to TX mode, in us. */ -#define NRF_FEM_RADIO_TX_TURNAROUND_LATENCY_US 20 - -/** Radio turnaround from TX to RX mode, in us. */ -#define NRF_FEM_RADIO_RX_TURNAROUND_LATENCY_US 20 - -/** Tifs drift measured, in us. */ -#define NRF_FEM_RADIO_TIFS_DRIFT_US 20 - #else #error "Device not supported." diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c deleted file mode 100644 index 77d3c1055..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements internal functions of Front End Module control for standalone version of - * the nRF 802.15.4 radio driver. - * - */ - -#include "nrf_fem_control_internal.h" - -#include "hal/nrf_timer.h" - -static bool m_timer_started = false; /**< Information if timer is running. */ - -void nrf_fem_control_timer_start(void) -{ - if (!m_timer_started) - { - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_START); - - m_timer_started = true; - } -} - -void nrf_fem_control_timer_stop(void) -{ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP); - - m_timer_started = false; -} - -void nrf_fem_control_timer_set(uint32_t target) -{ - nrf_timer_cc_write(NRF_TIMER0, (nrf_timer_cc_channel_t)TIMER_CC_FEM, target); -} - -uint32_t nrf_fem_control_timer_time_get(void) -{ - NRF_TIMER0->TASKS_CAPTURE[TIMER_CC_CAPTURE] = 1; - return NRF_TIMER0->CC[TIMER_CC_CAPTURE]; -} - -void nrf_fem_control_timer_init(void) -{ - nrf_fem_control_timer_stop(); - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); - - nrf_timer_mode_set(NRF_TIMER0, NRF_TIMER_MODE_TIMER); - nrf_timer_bit_width_set(NRF_TIMER0, NRF_TIMER_BIT_WIDTH_32); - nrf_timer_frequency_set(NRF_TIMER0, NRF_TIMER_FREQ_1MHz); -} - -void nrf_fem_control_timer_deinit(void) -{ - nrf_fem_control_timer_stop(); - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); -} - -uint32_t nrf_fem_control_irq_delay_get(void) -{ - return 0; -} diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h deleted file mode 100644 index 464184757..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @brief Front End Module control internal functions. - * - */ - -#ifndef NRF_FEM_CONTROL_INTERNAL_H_ -#define NRF_FEM_CONTROL_INTERNAL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nrf_fem_control_api.h" - -#define TIMER_CC_FEM 3 /**< Compare channel used by the module. */ -#define TIMER_CC_CAPTURE 2 /**< Compare channel used for time capture. */ - -/**@brief Start timer used by the module. */ -void nrf_fem_control_timer_start(void); - -/**@brief Stop timer used by the module. */ -void nrf_fem_control_timer_stop(void); - -/**@brief Set timer CC target value. - * - * @param[in] target Traget time. - */ -void nrf_fem_control_timer_set(uint32_t target); - -/**@brief Get current time from the timer. - * - * @retval Current timer time. - */ -uint32_t nrf_fem_control_timer_time_get(void); - -/**@brief Initialize timer. */ -void nrf_fem_control_timer_init(void); - -/**@brief De-initialize timer. */ -void nrf_fem_control_timer_deinit(void); - -/**@brief Get configuration specific irq entry delay. - * - * @retval Delay value. - */ -uint32_t nrf_fem_control_irq_delay_get(void); - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_FEM_CONTROL_INTERNAL_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c deleted file mode 100644 index b5ef092c4..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements internal functions of Front End Module control for - * nRF 802.15.4 radio driver working with SoftDevice RAAL. - * - */ - -#include "nrf_fem_control_internal.h" - -#include "hal/nrf_timer.h" - -#define SOFTDEVICE_IRQ_ENTRY_DELAY 4UL /**< An IRQ entry delay when using SoftDevice. */ - -void nrf_fem_control_timer_start(void) -{ - // Intentionally empty. In this configuration timer is controlled by RAAL. -} - -void nrf_fem_control_timer_stop(void) -{ - // Intentionally empty. In this configuration timer is controlled by RAAL. -} - -void nrf_fem_control_timer_set(uint32_t target) -{ - nrf_timer_cc_write(NRF_TIMER0, (nrf_timer_cc_channel_t)TIMER_CC_FEM, target); -} - -uint32_t nrf_fem_control_timer_time_get(void) -{ - NRF_TIMER0->TASKS_CAPTURE[TIMER_CC_CAPTURE] = 1; - return NRF_TIMER0->CC[TIMER_CC_CAPTURE]; -} - -void nrf_fem_control_timer_init(void) -{ - // Intentionally empty. In this configuration timer is controlled by RAAL. -} - -void nrf_fem_control_timer_deinit(void) -{ - // Intentionally empty. In this configuration timer is controlled by RAAL. -} - -uint32_t nrf_fem_control_irq_delay_get(void) -{ - return SOFTDEVICE_IRQ_ENTRY_DELAY; -} diff --git a/third_party/NordicSemiconductor/drivers/radio/hal/nrf_radio.h b/third_party/NordicSemiconductor/drivers/radio/hal/nrf_radio.h index cff0540cb..4da06ca09 100644 --- a/third_party/NordicSemiconductor/drivers/radio/hal/nrf_radio.h +++ b/third_party/NordicSemiconductor/drivers/radio/hal/nrf_radio.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, Nordic Semiconductor ASA +/* Copyright (c) 2016 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,15 +80,17 @@ typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ NRF_RADIO_EVENT_ADDRESS = offsetof(NRF_RADIO_Type, EVENTS_ADDRESS), /**< Address sent or received. */ NRF_RADIO_EVENT_END = offsetof(NRF_RADIO_Type, EVENTS_END), /**< Packet transmitted or received. */ NRF_RADIO_EVENT_DISABLED = offsetof(NRF_RADIO_Type, EVENTS_DISABLED), /**< Radio has been disabled. */ + NRF_RADIO_EVENT_RSSIEND = offsetof(NRF_RADIO_Type, EVENTS_RSSIEND), /**< Sampling of receive signal strength complete. */ + NRF_RADIO_EVENT_BCMATCH = offsetof(NRF_RADIO_Type, EVENTS_BCMATCH), /**< Bit counter reached bit count value. */ NRF_RADIO_EVENT_CRCOK = offsetof(NRF_RADIO_Type, EVENTS_CRCOK), /**< Packet received with correct CRC. */ NRF_RADIO_EVENT_CRCERROR = offsetof(NRF_RADIO_Type, EVENTS_CRCERROR), /**< Packet received with incorrect CRC. */ - NRF_RADIO_EVENT_CCAIDLE = offsetof(NRF_RADIO_Type, EVENTS_CCAIDLE), /**< Wireless medium is idle. */ - NRF_RADIO_EVENT_CCABUSY = offsetof(NRF_RADIO_Type, EVENTS_CCABUSY), /**< Wireless medium is busy. */ - NRF_RADIO_EVENT_RSSIEND = offsetof(NRF_RADIO_Type, EVENTS_RSSIEND), /**< Sampling of receive signal strength complete. */ - NRF_RADIO_EVENT_MHRMATCH = offsetof(NRF_RADIO_Type, EVENTS_MHRMATCH), /**< MAC Header match found. */ NRF_RADIO_EVENT_FRAMESTART = offsetof(NRF_RADIO_Type, EVENTS_FRAMESTART), /**< IEEE 802.15.4 length field received. */ NRF_RADIO_EVENT_EDEND = offsetof(NRF_RADIO_Type, EVENTS_EDEND), /**< Energy Detection procedure ended. */ - NRF_RADIO_EVENT_BCMATCH = offsetof(NRF_RADIO_Type, EVENTS_BCMATCH), /**< Bit counter reached bit count value. */ + NRF_RADIO_EVENT_CCAIDLE = offsetof(NRF_RADIO_Type, EVENTS_CCAIDLE), /**< Wireless medium is idle. */ + NRF_RADIO_EVENT_CCABUSY = offsetof(NRF_RADIO_Type, EVENTS_CCABUSY), /**< Wireless medium is busy. */ + NRF_RADIO_EVENT_TXREADY = offsetof(NRF_RADIO_Type, EVENTS_TXREADY), /**< Radio has ramped up and is ready to be started TX path. */ + NRF_RADIO_EVENT_RXREADY = offsetof(NRF_RADIO_Type, EVENTS_RXREADY), /**< Radio has ramped up and is ready to be started RX path. */ + NRF_RADIO_EVENT_MHRMATCH = offsetof(NRF_RADIO_Type, EVENTS_MHRMATCH), /**< MAC Header match found. */ NRF_RADIO_EVENT_PHYEND = offsetof(NRF_RADIO_Type, EVENTS_PHYEND), /**< Generated in Ble_LR125Kbit, Ble_LR500Kbit and Ieee802154_250Kbit modes when last bit is sent on air. */ } nrf_radio_event_t; /*lint -restore */ @@ -102,14 +104,14 @@ typedef enum NRF_RADIO_INT_ADDRESS_MASK = RADIO_INTENSET_ADDRESS_Msk, /**< Mask for enabling or disabling an interrupt on ADDRESS event. */ NRF_RADIO_INT_END_MASK = RADIO_INTENSET_END_Msk, /**< Mask for enabling or disabling an interrupt on END event. */ NRF_RADIO_INT_DISABLED_MASK = RADIO_INTENSET_DISABLED_Msk, /**< Mask for enabling or disabling an interrupt on DISABLED event. */ + NRF_RADIO_INT_RSSIEND_MASK = RADIO_INTENSET_RSSIEND_Msk, /**< Mask for enabling or disabling an interrupt on RSSIEND event. */ + NRF_RADIO_INT_BCMATCH_MASK = RADIO_INTENSET_BCMATCH_Msk, /**< Mask for enabling or disabling an interrupt on BCMATCH event. */ NRF_RADIO_INT_CRCOK_MASK = RADIO_INTENSET_CRCOK_Msk, /**< Mask for enabling or disabling an interrupt on CRCOK event. */ NRF_RADIO_INT_CRCERROR_MASK = RADIO_INTENSET_CRCERROR_Msk, /**< Mask for enabling or disabling an interrupt on CRCERROR event. */ - NRF_RADIO_INT_CCAIDLE_MASK = RADIO_INTENSET_CCAIDLE_Msk, /**< Mask for enabling or disabling an interrupt on CCAIDLE event. */ - NRF_RADIO_INT_CCABUSY_MASK = RADIO_INTENSET_CCABUSY_Msk, /**< Mask for enabling or disabling an interrupt on CCABUSY event. */ - NRF_RADIO_INT_RSSIEND_MASK = RADIO_INTENSET_RSSIEND_Msk, /**< Mask for enabling or disabling an interrupt on RSSIEND event. */ NRF_RADIO_INT_FRAMESTART_MASK = RADIO_INTENSET_FRAMESTART_Msk, /**< Mask for enabling or disabling an interrupt on FRAMESTART event. */ NRF_RADIO_INT_EDEND_MASK = RADIO_INTENSET_EDEND_Msk, /**< Mask for enabling or disabling an interrupt on EDEND event. */ - NRF_RADIO_INT_BCMATCH_MASK = RADIO_INTENSET_BCMATCH_Msk, /**< Mask for enabling or disabling an interrupt on BCMATCH event. */ + NRF_RADIO_INT_CCAIDLE_MASK = RADIO_INTENSET_CCAIDLE_Msk, /**< Mask for enabling or disabling an interrupt on CCAIDLE event. */ + NRF_RADIO_INT_CCABUSY_MASK = RADIO_INTENSET_CCABUSY_Msk, /**< Mask for enabling or disabling an interrupt on CCABUSY event. */ NRF_RADIO_INT_PHYEND_MASK = RADIO_INTENSET_PHYEND_Msk, /**< Mask for enabling or disabling an interrupt on PHYEND event. */ } nrf_radio_int_mask_t; @@ -120,12 +122,20 @@ typedef enum typedef enum { NRF_RADIO_SHORT_READY_START_MASK = RADIO_SHORTS_READY_START_Msk, /**< Mask for setting shortcut between EVENT_READY and TASK_START. */ - NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK = RADIO_SHORTS_ADDRESS_RSSISTART_Msk, /**< Mask for setting shortcut between EVENT_ADDRESS and TASK_RSSISTART. */ NRF_RADIO_SHORT_END_DISABLE_MASK = RADIO_SHORTS_END_DISABLE_Msk, /**< Mask for setting shortcut between EVENT_END and TASK_DISABLE. */ - NRF_RADIO_SHORT_END_START_MASK = RADIO_SHORTS_END_START_Msk, /**< Mask for setting shortcut between EVENT_END and TASK_START. */ - NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK = RADIO_SHORTS_CCAIDLE_TXEN_Msk, /**< Mask for setting shortcut between EVENT_CCAIDLE and TASK_TXEN. */ NRF_RADIO_SHORT_DISABLED_TXEN_MASK = RADIO_SHORTS_DISABLED_TXEN_Msk, /**< Mask for setting shortcut between EVENT_DISABLED and TASK_TXEN. */ + NRF_RADIO_SHORT_DISABLED_RXEN_MASK = RADIO_SHORTS_DISABLED_RXEN_Msk, /**< Mask for setting shortcut between EVENT_DISABLED and TASK_RXEN. */ + NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK = RADIO_SHORTS_ADDRESS_RSSISTART_Msk, /**< Mask for setting shortcut between EVENT_ADDRESS and TASK_RSSISTART. */ + NRF_RADIO_SHORT_ADDRESS_BCSTART_MASK = RADIO_SHORTS_ADDRESS_BCSTART_Msk, /**< Mask for setting shortcut between EVENT_ADDRESS and TASK_BCSTART. */ + NRF_RADIO_SHORT_END_START_MASK = RADIO_SHORTS_END_START_Msk, /**< Mask for setting shortcut between EVENT_END and TASK_START. */ + NRF_RADIO_SHORT_RXREADY_CCASTART_MASK = RADIO_SHORTS_RXREADY_CCASTART_Msk, /**< Mask for setting shortcut between EVENT_RXREADY and TASK_CCASTART. */ + NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK = RADIO_SHORTS_CCAIDLE_TXEN_Msk, /**< Mask for setting shortcut between EVENT_CCAIDLE and TASK_TXEN. */ + NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK = RADIO_SHORTS_CCABUSY_DISABLE_Msk, /**< Mask for setting shortcut between EVENT_CCABUSY and TASK_DISABLE. */ NRF_RADIO_SHORT_FRAMESTART_BCSTART_MASK = RADIO_SHORTS_FRAMESTART_BCSTART_Msk, /**< Mask for setting shortcut between EVENT_FRAMESTART and TASK_BCSTART. */ + NRF_RADIO_SHORT_READY_EDSTART_MASK = RADIO_SHORTS_READY_EDSTART_Msk, /**< Mask for setting shortcut between EVENT_READY and TASK_EDSTART. */ + NRF_RADIO_SHORT_EDEND_DISABLE_MASK = RADIO_SHORTS_EDEND_DISABLE_Msk, /**< Mask for setting shortcut between EVENT_EDEND and TASK_DISABLE. */ + NRF_RADIO_SHORT_TXREADY_START_MASK = RADIO_SHORTS_TXREADY_START_Msk, /**< Mask for setting shortcut between EVENT_TXREADY and TASK_START. */ + NRF_RADIO_SHORT_RXREADY_START_MASK = RADIO_SHORTS_RXREADY_START_Msk, /**< Mask for setting shortcut between EVENT_RXREADY and TASK_START. */ NRF_RADIO_SHORT_PHYEND_DISABLE_MASK = RADIO_SHORTS_PHYEND_DISABLE_Msk, /**< Mask for setting shortcut between EVENT_PHYEND and TASK_DISABLE. */ NRF_RADIO_SHORT_PHYEND_START_MASK = RADIO_SHORTS_PHYEND_START_Msk, /**< Mask for setting shortcut between EVENT_PHYEND and TASK_START. */ } nrf_radio_short_mask_t; @@ -220,20 +230,14 @@ typedef enum * * @param[in] radio_int_mask Mask of interrupts. */ -__STATIC_INLINE void nrf_radio_int_enable(uint32_t radio_int_mask) -{ - NRF_RADIO->INTENSET = radio_int_mask; -} +__STATIC_INLINE void nrf_radio_int_enable(uint32_t radio_int_mask); /** * @brief Function for disabling interrupts. * * @param[in] radio_int_mask Mask of interrupts. */ -__STATIC_INLINE void nrf_radio_int_disable(uint32_t radio_int_mask) -{ - NRF_RADIO->INTENCLR = radio_int_mask; -} +__STATIC_INLINE void nrf_radio_int_disable(uint32_t radio_int_mask); /** * @brief Function for getting the state of a specific interrupt. @@ -243,10 +247,7 @@ __STATIC_INLINE void nrf_radio_int_disable(uint32_t radio_int_mask) * @retval true If the interrupt is not enabled. * @retval false If the interrupt is enabled. */ -__STATIC_INLINE bool nrf_radio_int_get(nrf_radio_int_mask_t radio_int_mask) -{ - return (bool)(NRF_RADIO->INTENCLR & radio_int_mask); -} +__STATIC_INLINE bool nrf_radio_int_get(nrf_radio_int_mask_t radio_int_mask); /** * @brief Function for getting the address of a specific task. @@ -255,20 +256,14 @@ __STATIC_INLINE bool nrf_radio_int_get(nrf_radio_int_mask_t radio_int_mask) * * @param[in] radio_task Task. */ -__STATIC_INLINE uint32_t *nrf_radio_task_address_get(nrf_radio_task_t radio_task) -{ - return (uint32_t *)((uint8_t *)NRF_RADIO + radio_task); -} +__STATIC_INLINE uint32_t *nrf_radio_task_address_get(nrf_radio_task_t radio_task); /** * @brief Function for setting a specific task. * * @param[in] radio_task Task. */ -__STATIC_INLINE void nrf_radio_task_trigger(nrf_radio_task_t radio_task) -{ - *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_task)) = NRF_RADIO_TASK_SET; -} +__STATIC_INLINE void nrf_radio_task_trigger(nrf_radio_task_t radio_task); /** * @brief Function for getting address of a specific event. @@ -277,24 +272,14 @@ __STATIC_INLINE void nrf_radio_task_trigger(nrf_radio_task_t radio_task) * * @param[in] radio_event Event. */ -__STATIC_INLINE uint32_t *nrf_radio_event_address_get(nrf_radio_event_t radio_event) -{ - return (uint32_t *)((uint8_t *)NRF_RADIO + radio_event); -} +__STATIC_INLINE uint32_t *nrf_radio_event_address_get(nrf_radio_event_t radio_event); /** * @brief Function for clearing a specific event. * * @param[in] radio_event Event. */ -__STATIC_INLINE void nrf_radio_event_clear(nrf_radio_event_t radio_event) -{ - *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)) = NRF_RADIO_EVENT_CLEAR; -#if __CORTEX_M == 0x04 - volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)); - (void)dummy; -#endif -} +__STATIC_INLINE void nrf_radio_event_clear(nrf_radio_event_t radio_event); /** * @brief Function for getting the state of a specific event. @@ -304,10 +289,7 @@ __STATIC_INLINE void nrf_radio_event_clear(nrf_radio_event_t radio_event) * @retval true If the event is not set. * @retval false If the event is set. */ -__STATIC_INLINE bool nrf_radio_event_get(nrf_radio_event_t radio_event) -{ - return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)); -} +__STATIC_INLINE bool nrf_radio_event_get(nrf_radio_event_t radio_event); /** * @brief Function for setting shortcuts. @@ -315,10 +297,7 @@ __STATIC_INLINE bool nrf_radio_event_get(nrf_radio_event_t radio_event) * @param[in] radio_short_mask Mask of shortcuts. * */ -__STATIC_INLINE void nrf_radio_shorts_enable(uint32_t radio_short_mask) -{ - NRF_RADIO->SHORTS |= radio_short_mask; -} +__STATIC_INLINE void nrf_radio_shorts_enable(uint32_t radio_short_mask); /** * @brief Function for clearing shortcuts. @@ -326,10 +305,7 @@ __STATIC_INLINE void nrf_radio_shorts_enable(uint32_t radio_short_mask) * @param[in] radio_short_mask Mask of shortcuts. * */ -__STATIC_INLINE void nrf_radio_shorts_disable(uint32_t radio_short_mask) -{ - NRF_RADIO->SHORTS &= ~radio_short_mask; -} +__STATIC_INLINE void nrf_radio_shorts_disable(uint32_t radio_short_mask); /** * @brief Function for setting shortcuts. @@ -337,10 +313,7 @@ __STATIC_INLINE void nrf_radio_shorts_disable(uint32_t radio_short_mask) * @param[in] radio_short_mask Mask of shortcuts. * */ -__STATIC_INLINE void nrf_radio_shorts_set(uint32_t radio_short_mask) -{ - NRF_RADIO->SHORTS = radio_short_mask; -} +__STATIC_INLINE void nrf_radio_shorts_set(uint32_t radio_short_mask); /** * @brief Function for getting shortcuts. @@ -348,69 +321,45 @@ __STATIC_INLINE void nrf_radio_shorts_set(uint32_t radio_short_mask) * @return Mask of shortcuts. * */ -__STATIC_INLINE uint32_t nrf_radio_shorts_get(void) -{ - return NRF_RADIO->SHORTS; -} +__STATIC_INLINE uint32_t nrf_radio_shorts_get(void); /** * @brief Function for getting present state of the radio module. */ -__STATIC_INLINE nrf_radio_state_t nrf_radio_state_get(void) -{ - return (nrf_radio_state_t) NRF_RADIO->STATE; -} +__STATIC_INLINE nrf_radio_state_t nrf_radio_state_get(void); /** * @brief Function for setting Packet Pointer to given location in memory. * * @param[in] p_radio_packet_ptr Pointer to tx or rx packet buffer. */ -__STATIC_INLINE void nrf_radio_packet_ptr_set(const void *p_radio_packet_ptr) -{ - NRF_RADIO->PACKETPTR = (uint32_t) p_radio_packet_ptr; -} +__STATIC_INLINE void nrf_radio_packet_ptr_set(const void *p_radio_packet_ptr); /** * @brief Function for getting CRC status of last received packet. */ -__STATIC_INLINE nrf_radio_crc_status_t nrf_radio_crc_status_get(void) -{ - return (nrf_radio_crc_status_t) NRF_RADIO->CRCSTATUS; -} +__STATIC_INLINE nrf_radio_crc_status_t nrf_radio_crc_status_get(void); /** * @brief Function for setting Clear Channel Assessment mode. * * @param[in] radio_cca_mode Mode of CCA */ -__STATIC_INLINE void nrf_radio_cca_mode_set(nrf_radio_cca_mode_t radio_cca_mode) -{ - NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCAMODE_Msk); - NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_mode << RADIO_CCACTRL_CCAMODE_Pos); -} +__STATIC_INLINE void nrf_radio_cca_mode_set(nrf_radio_cca_mode_t radio_cca_mode); /** * @brief Function for setting CCA Energy Busy Threshold. * * @param[in] radio_cca_ed_threshold Energy Detection threshold value. */ -__STATIC_INLINE void nrf_radio_cca_ed_threshold_set(uint8_t radio_cca_ed_threshold) -{ - NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCAEDTHRES_Msk); - NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_ed_threshold << RADIO_CCACTRL_CCAEDTHRES_Pos); -} +__STATIC_INLINE void nrf_radio_cca_ed_threshold_set(uint8_t radio_cca_ed_threshold); /** * @brief Function for setting CCA Correlator Busy Threshold. * * @param[in] radio_cca_corr_threshold Correlator Busy Threshold. */ -__STATIC_INLINE void nrf_radio_cca_corr_threshold_set(uint8_t radio_cca_corr_threshold_set) -{ - NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCACORRTHRES_Msk); - NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_corr_threshold_set << RADIO_CCACTRL_CCACORRTHRES_Pos); -} +__STATIC_INLINE void nrf_radio_cca_corr_threshold_set(uint8_t radio_cca_corr_threshold_set); /** * @brief Function for setting limit of occurances above Correlator Threshold. @@ -419,32 +368,21 @@ __STATIC_INLINE void nrf_radio_cca_corr_threshold_set(uint8_t radio_cca_corr_thr * * @param[in] radio_cca_corr_cnt Limit of occurances above Correlator Threshold */ -__STATIC_INLINE void nrf_radio_cca_corr_counter_set(uint8_t radio_cca_corr_counter_set) -{ - NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCACORRCNT_Msk); - NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_corr_counter_set << RADIO_CCACTRL_CCACORRCNT_Pos); -} +__STATIC_INLINE void nrf_radio_cca_corr_counter_set(uint8_t radio_cca_corr_counter_set); /** * @brief Function for setting Radio data rate and modulation settings. * * @param[in] radio_mode Mode of radio data rate and modulation. */ -__STATIC_INLINE void nrf_radio_mode_set(nrf_radio_mode_t radio_mode) -{ - NRF_RADIO->MODE = ((uint32_t) radio_mode << RADIO_MODE_MODE_Pos); -} +__STATIC_INLINE void nrf_radio_mode_set(nrf_radio_mode_t radio_mode); /** * @brief Function for setting Length of LENGTH field in number of bits. * * @param[in] radio_length_length Length of LENGTH field in number of bits. */ -__STATIC_INLINE void nrf_radio_config_length_field_length_set(uint8_t radio_length_length) -{ - NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_LFLEN_Msk); - NRF_RADIO->PCNF0 |= ((uint32_t) radio_length_length << RADIO_PCNF0_LFLEN_Pos); -} +__STATIC_INLINE void nrf_radio_config_length_field_length_set(uint8_t radio_length_length); /** * @brief Function for setting length of preamble on air. @@ -452,44 +390,28 @@ __STATIC_INLINE void nrf_radio_config_length_field_length_set(uint8_t radio_leng * @param[in] radio_preamble_length Length of preamble on air. */ __STATIC_INLINE void nrf_radio_config_preamble_length_set( - nrf_radio_preamble_length_t radio_preamble_length) -{ - NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_PLEN_Msk); - NRF_RADIO->PCNF0 |= ((uint32_t) radio_preamble_length << RADIO_PCNF0_PLEN_Pos); -} + nrf_radio_preamble_length_t radio_preamble_length); /** * @brief Function for setting if LENGTH field contains CRC. * * @param[in] radio_length_contains_crc True if LENGTH field should contain CRC. */ -__STATIC_INLINE void nrf_radio_config_crc_included_set(bool radio_length_contains_crc) -{ - NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_CRCINC_Msk); - NRF_RADIO->PCNF0 |= ((uint32_t) radio_length_contains_crc << RADIO_PCNF0_CRCINC_Pos); -} +__STATIC_INLINE void nrf_radio_config_crc_included_set(bool radio_length_contains_crc); /** * @brief Function for setting maximum length of packet payload. * * @param[in] radio_max_packet_length Maximum length of packet payload. */ -__STATIC_INLINE void nrf_radio_config_max_length_set(uint8_t radio_max_packet_length) -{ - NRF_RADIO->PCNF1 &= (~RADIO_PCNF1_MAXLEN_Msk); - NRF_RADIO->PCNF1 |= ((uint32_t) radio_max_packet_length << RADIO_PCNF1_MAXLEN_Pos); -} +__STATIC_INLINE void nrf_radio_config_max_length_set(uint8_t radio_max_packet_length); /** * @brief Function for setting CRC length. * * @param[in] radio_crc_length CRC length in number of bytes [0-3]. */ -__STATIC_INLINE void nrf_radio_crc_length_set(uint8_t radio_crc_length) -{ - NRF_RADIO->CRCCNF &= (~RADIO_CRCCNF_LEN_Msk); - NRF_RADIO->CRCCNF |= ((uint32_t) radio_crc_length << RADIO_CRCCNF_LEN_Pos); -} +__STATIC_INLINE void nrf_radio_crc_length_set(uint8_t radio_crc_length); /** * @brief Function for setting if address filed should be included or excluded from CRC calculation. @@ -497,21 +419,21 @@ __STATIC_INLINE void nrf_radio_crc_length_set(uint8_t radio_crc_length) * @param[in] radio_crc_skip_address Include or exclude packet address field out of CRC. */ __STATIC_INLINE void nrf_radio_crc_includes_address_set( - nrf_radio_crc_includes_addr_t radio_crc_skip_address) -{ - NRF_RADIO->CRCCNF &= (~RADIO_CRCCNF_SKIPADDR_Msk); - NRF_RADIO->CRCCNF |= ((uint32_t) radio_crc_skip_address << RADIO_CRCCNF_SKIPADDR_Pos); -} + nrf_radio_crc_includes_addr_t radio_crc_skip_address); /** * @brief Function for setting CRC polynominal. * * @param[in] radio_crc_polynominal CRC polynominal to set. */ -__STATIC_INLINE void nrf_radio_crc_polynominal_set(uint32_t radio_crc_polynominal) -{ - NRF_RADIO->CRCPOLY = (radio_crc_polynominal << RADIO_CRCPOLY_CRCPOLY_Pos); -} +__STATIC_INLINE void nrf_radio_crc_polynominal_set(uint32_t radio_crc_polynominal); + +/** + * @brief Function for getting CRC polynominal. + * + * @return CRC polynominal. + */ +__STATIC_INLINE uint32_t nrf_radio_crc_polynominal_get(void); /** * @brief Function for getting RSSI sample result. @@ -520,146 +442,335 @@ __STATIC_INLINE void nrf_radio_crc_polynominal_set(uint32_t radio_crc_polynomina * Actual received signal strength is therefore as follows: * received signal strength = - returned_value dBm . */ -__STATIC_INLINE uint8_t nrf_radio_rssi_sample_get(void) -{ - return (uint8_t)(((NRF_RADIO->RSSISAMPLE) & RADIO_RSSISAMPLE_RSSISAMPLE_Msk) >> - RADIO_RSSISAMPLE_RSSISAMPLE_Pos); -} +__STATIC_INLINE uint8_t nrf_radio_rssi_sample_get(void); /** * @brief Function for setting MAC Header Match Unit search pattern configuration. * * @param[in] radio_mhmu_search_pattern Search Pattern Configuration. */ -__STATIC_INLINE void nrf_radio_mhmu_search_pattern_set(uint32_t radio_mhmu_search_pattern) -{ - NRF_RADIO->MHRMATCHCONF = radio_mhmu_search_pattern; -} +__STATIC_INLINE void nrf_radio_mhmu_search_pattern_set(uint32_t radio_mhmu_search_pattern); /** * @brief Function for setting MAC Header Match Unit pattern mask configuration. * * @param[in] radio_mhmu_pattern_mask Pattern mask. */ -__STATIC_INLINE void nrf_radio_mhmu_pattern_mask_set(uint32_t radio_mhmu_pattern_mask) -{ - NRF_RADIO->MHRMATCHMAS = radio_mhmu_pattern_mask; -} +__STATIC_INLINE void nrf_radio_mhmu_pattern_mask_set(uint32_t radio_mhmu_pattern_mask); /** * @brief Function for setting radio ramp-up mode. * * @param[in] ramp_up_mode Radio ramp-up mode. */ -__STATIC_INLINE void nrf_radio_ramp_up_mode_set(nrf_radio_ramp_up_mode_t ramp_up_mode) -{ - NRF_RADIO->MODECNF0 &= (~RADIO_MODECNF0_RU_Msk); - NRF_RADIO->MODECNF0 |= ((uint32_t) ramp_up_mode << RADIO_MODECNF0_RU_Pos); -} +__STATIC_INLINE void nrf_radio_ramp_up_mode_set(nrf_radio_ramp_up_mode_t ramp_up_mode); /** * @brief Function for setting radio frequency. * * @param[in] radio_frequency Frequency above 2400 MHz [MHz] */ -__STATIC_INLINE void nrf_radio_frequency_set(uint32_t radio_frequency) -{ - NRF_RADIO->FREQUENCY = radio_frequency; -} +__STATIC_INLINE void nrf_radio_frequency_set(uint32_t radio_frequency); /** * @brief Function for getting radio frequency. * * @returns Frequency above 2400 MHz [MHz] */ -__STATIC_INLINE uint32_t nrf_radio_frequency_get(void) -{ - return NRF_RADIO->FREQUENCY; -} +__STATIC_INLINE uint32_t nrf_radio_frequency_get(void); /** * @brief Function for setting radio transmit power. * * @param[in] radio_tx_power Transmit power of the radio. */ -__STATIC_INLINE void nrf_radio_tx_power_set(int8_t radio_tx_power) -{ - NRF_RADIO->TXPOWER = (uint8_t) radio_tx_power; -} +__STATIC_INLINE void nrf_radio_tx_power_set(int8_t radio_tx_power); /** * @brief Function for setting Inter Frame Spacing * * @param[in] radio_ifs Inter frame spacing [us]. */ -__STATIC_INLINE void nrf_radio_ifs_set(uint32_t radio_ifs) -{ - NRF_RADIO->TIFS = radio_ifs; -} +__STATIC_INLINE void nrf_radio_ifs_set(uint32_t radio_ifs); /** * @brief Function for getting Inter Frame Spacing * * @return Current Inter Frame Spacing */ -__STATIC_INLINE uint32_t nrf_radio_ifs_get(void) -{ - return NRF_RADIO->TIFS & RADIO_TIFS_TIFS_Msk; -} +__STATIC_INLINE uint32_t nrf_radio_ifs_get(void); /** * @brief Function for setting Bit counter compare. * * @param[in] radio_bcc Bit counter compare [bits]. */ -__STATIC_INLINE void nrf_radio_bcc_set(uint32_t radio_bcc) -{ - NRF_RADIO->BCC = radio_bcc; -} +__STATIC_INLINE void nrf_radio_bcc_set(uint32_t radio_bcc); /** * @brief Function for getting Bit counter compare. */ -__STATIC_INLINE uint32_t nrf_radio_bcc_get(void) -{ - return NRF_RADIO->BCC; -} +__STATIC_INLINE uint32_t nrf_radio_bcc_get(void); /** * @brief Function for getting Energy Detection level. */ -__STATIC_INLINE uint8_t nrf_radio_ed_sample_get(void) -{ - return (uint8_t) NRF_RADIO->EDSAMPLE; -} +__STATIC_INLINE uint8_t nrf_radio_ed_sample_get(void); /** * @brief Function for setting number of iterations to perform ED scan. * * @param[in] radio_ed_loop_count Number of iterations during ED procedure. */ -__STATIC_INLINE void nrf_radio_ed_loop_count_set(uint32_t radio_ed_loop_count) -{ - NRF_RADIO->EDCNT = (radio_ed_loop_count & 0x001FFFFF); -} +__STATIC_INLINE void nrf_radio_ed_loop_count_set(uint32_t radio_ed_loop_count); /** * @brief Function for setting power mode of the radio peripheral. * * @param[in] radio_power If radio should powered on. */ -__STATIC_INLINE void nrf_radio_power_set(bool radio_power) -{ - NRF_RADIO->POWER = (uint32_t) radio_power; -} +__STATIC_INLINE void nrf_radio_power_set(bool radio_power); /** *@} **/ +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_radio_int_enable(uint32_t radio_int_mask) +{ + NRF_RADIO->INTENSET = radio_int_mask; +} + +__STATIC_INLINE void nrf_radio_int_disable(uint32_t radio_int_mask) +{ + NRF_RADIO->INTENCLR = radio_int_mask; +} + +__STATIC_INLINE bool nrf_radio_int_get(nrf_radio_int_mask_t radio_int_mask) +{ + return (bool)(NRF_RADIO->INTENCLR & radio_int_mask); +} + +__STATIC_INLINE uint32_t *nrf_radio_task_address_get(nrf_radio_task_t radio_task) +{ + return (uint32_t *)((uint8_t *)NRF_RADIO + radio_task); +} + +__STATIC_INLINE void nrf_radio_task_trigger(nrf_radio_task_t radio_task) +{ + *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_task)) = NRF_RADIO_TASK_SET; +} + +__STATIC_INLINE uint32_t *nrf_radio_event_address_get(nrf_radio_event_t radio_event) +{ + return (uint32_t *)((uint8_t *)NRF_RADIO + radio_event); +} + +__STATIC_INLINE void nrf_radio_event_clear(nrf_radio_event_t radio_event) +{ + *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)) = NRF_RADIO_EVENT_CLEAR; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_radio_event_get(nrf_radio_event_t radio_event) +{ + return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)); +} + +__STATIC_INLINE void nrf_radio_shorts_enable(uint32_t radio_short_mask) +{ + NRF_RADIO->SHORTS |= radio_short_mask; +} + +__STATIC_INLINE void nrf_radio_shorts_disable(uint32_t radio_short_mask) +{ + NRF_RADIO->SHORTS &= ~radio_short_mask; +} + +__STATIC_INLINE void nrf_radio_shorts_set(uint32_t radio_short_mask) +{ + NRF_RADIO->SHORTS = radio_short_mask; +} + +__STATIC_INLINE uint32_t nrf_radio_shorts_get(void) +{ + return NRF_RADIO->SHORTS; +} + +__STATIC_INLINE nrf_radio_state_t nrf_radio_state_get(void) +{ + return (nrf_radio_state_t) NRF_RADIO->STATE; +} + +__STATIC_INLINE void nrf_radio_packet_ptr_set(const void *p_radio_packet_ptr) +{ + NRF_RADIO->PACKETPTR = (uint32_t) p_radio_packet_ptr; +} + +__STATIC_INLINE nrf_radio_crc_status_t nrf_radio_crc_status_get(void) +{ + return (nrf_radio_crc_status_t) NRF_RADIO->CRCSTATUS; +} + +__STATIC_INLINE void nrf_radio_cca_mode_set(nrf_radio_cca_mode_t radio_cca_mode) +{ + NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCAMODE_Msk); + NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_mode << RADIO_CCACTRL_CCAMODE_Pos); +} + +__STATIC_INLINE void nrf_radio_cca_ed_threshold_set(uint8_t radio_cca_ed_threshold) +{ + NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCAEDTHRES_Msk); + NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_ed_threshold << RADIO_CCACTRL_CCAEDTHRES_Pos); +} + +__STATIC_INLINE void nrf_radio_cca_corr_threshold_set(uint8_t radio_cca_corr_threshold_set) +{ + NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCACORRTHRES_Msk); + NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_corr_threshold_set << RADIO_CCACTRL_CCACORRTHRES_Pos); +} + +__STATIC_INLINE void nrf_radio_cca_corr_counter_set(uint8_t radio_cca_corr_counter_set) +{ + NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCACORRCNT_Msk); + NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_corr_counter_set << RADIO_CCACTRL_CCACORRCNT_Pos); +} + +__STATIC_INLINE void nrf_radio_mode_set(nrf_radio_mode_t radio_mode) +{ + NRF_RADIO->MODE = ((uint32_t) radio_mode << RADIO_MODE_MODE_Pos); +} + +__STATIC_INLINE void nrf_radio_config_length_field_length_set(uint8_t radio_length_length) +{ + NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_LFLEN_Msk); + NRF_RADIO->PCNF0 |= ((uint32_t) radio_length_length << RADIO_PCNF0_LFLEN_Pos); +} + +__STATIC_INLINE void nrf_radio_config_preamble_length_set( + nrf_radio_preamble_length_t radio_preamble_length) +{ + NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_PLEN_Msk); + NRF_RADIO->PCNF0 |= ((uint32_t) radio_preamble_length << RADIO_PCNF0_PLEN_Pos); +} + +__STATIC_INLINE void nrf_radio_config_crc_included_set(bool radio_length_contains_crc) +{ + NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_CRCINC_Msk); + NRF_RADIO->PCNF0 |= ((uint32_t) radio_length_contains_crc << RADIO_PCNF0_CRCINC_Pos); +} + +__STATIC_INLINE void nrf_radio_config_max_length_set(uint8_t radio_max_packet_length) +{ + NRF_RADIO->PCNF1 &= (~RADIO_PCNF1_MAXLEN_Msk); + NRF_RADIO->PCNF1 |= ((uint32_t) radio_max_packet_length << RADIO_PCNF1_MAXLEN_Pos); +} + +__STATIC_INLINE void nrf_radio_crc_length_set(uint8_t radio_crc_length) +{ + NRF_RADIO->CRCCNF &= (~RADIO_CRCCNF_LEN_Msk); + NRF_RADIO->CRCCNF |= ((uint32_t) radio_crc_length << RADIO_CRCCNF_LEN_Pos); +} + +__STATIC_INLINE void nrf_radio_crc_includes_address_set( + nrf_radio_crc_includes_addr_t radio_crc_skip_address) +{ + NRF_RADIO->CRCCNF &= (~RADIO_CRCCNF_SKIPADDR_Msk); + NRF_RADIO->CRCCNF |= ((uint32_t) radio_crc_skip_address << RADIO_CRCCNF_SKIPADDR_Pos); +} + +__STATIC_INLINE void nrf_radio_crc_polynominal_set(uint32_t radio_crc_polynominal) +{ + NRF_RADIO->CRCPOLY = (radio_crc_polynominal << RADIO_CRCPOLY_CRCPOLY_Pos); +} + +__STATIC_INLINE uint32_t nrf_radio_crc_polynominal_get(void) +{ + return (NRF_RADIO->CRCPOLY & RADIO_CRCPOLY_CRCPOLY_Msk) >> RADIO_CRCPOLY_CRCPOLY_Pos; +} + +__STATIC_INLINE uint8_t nrf_radio_rssi_sample_get(void) +{ + return (uint8_t)(((NRF_RADIO->RSSISAMPLE) & RADIO_RSSISAMPLE_RSSISAMPLE_Msk) >> + RADIO_RSSISAMPLE_RSSISAMPLE_Pos); +} + +__STATIC_INLINE void nrf_radio_mhmu_search_pattern_set(uint32_t radio_mhmu_search_pattern) +{ + NRF_RADIO->MHRMATCHCONF = radio_mhmu_search_pattern; +} + +__STATIC_INLINE void nrf_radio_mhmu_pattern_mask_set(uint32_t radio_mhmu_pattern_mask) +{ + NRF_RADIO->MHRMATCHMAS = radio_mhmu_pattern_mask; +} + +__STATIC_INLINE void nrf_radio_ramp_up_mode_set(nrf_radio_ramp_up_mode_t ramp_up_mode) +{ + NRF_RADIO->MODECNF0 &= (~RADIO_MODECNF0_RU_Msk); + NRF_RADIO->MODECNF0 |= ((uint32_t) ramp_up_mode << RADIO_MODECNF0_RU_Pos); +} + +__STATIC_INLINE void nrf_radio_frequency_set(uint32_t radio_frequency) +{ + NRF_RADIO->FREQUENCY = radio_frequency; +} + +__STATIC_INLINE uint32_t nrf_radio_frequency_get(void) +{ + return NRF_RADIO->FREQUENCY; +} + +__STATIC_INLINE void nrf_radio_tx_power_set(int8_t radio_tx_power) +{ + NRF_RADIO->TXPOWER = (uint8_t) radio_tx_power; +} + +__STATIC_INLINE void nrf_radio_ifs_set(uint32_t radio_ifs) +{ + NRF_RADIO->TIFS = radio_ifs; +} + +__STATIC_INLINE uint32_t nrf_radio_ifs_get(void) +{ + return NRF_RADIO->TIFS & RADIO_TIFS_TIFS_Msk; +} + +__STATIC_INLINE void nrf_radio_bcc_set(uint32_t radio_bcc) +{ + NRF_RADIO->BCC = radio_bcc; +} + +__STATIC_INLINE uint32_t nrf_radio_bcc_get(void) +{ + return NRF_RADIO->BCC; +} + +__STATIC_INLINE uint8_t nrf_radio_ed_sample_get(void) +{ + return (uint8_t) NRF_RADIO->EDSAMPLE; +} + +__STATIC_INLINE void nrf_radio_ed_loop_count_set(uint32_t radio_ed_loop_count) +{ + NRF_RADIO->EDCNT = (radio_ed_loop_count & 0x001FFFFF); +} + +__STATIC_INLINE void nrf_radio_power_set(bool radio_power) +{ + NRF_RADIO->POWER = (uint32_t) radio_power; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + #ifdef __cplusplus } #endif #endif /* NRF_RADIO_H__ */ + diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.c b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.c new file mode 100644 index 000000000..4ec971a9a --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.c @@ -0,0 +1,146 @@ +/* Copyright (c) 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements ACK timeout procedure for the 802.15.4 driver. + * + */ + +#include "nrf_802154_ack_timeout.h" + +#include +#include +#include + +#include "nrf_802154_notification.h" +#include "nrf_802154_request.h" +#include "timer_scheduler/nrf_802154_timer_sched.h" + +static void timeout_timer_retry(void); + +static uint32_t m_timeout = NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT; ///< ACK timeout in us. +static nrf_802154_timer_t m_timer; ///< Timer used to notify when we are waiting too long for ACK. +static volatile bool m_procedure_is_active; +static const uint8_t * mp_frame; + +static void notify_tx_error(bool result) +{ + if (result) + { + nrf_802154_notify_transmit_failed(mp_frame, NRF_802154_TX_ERROR_NO_ACK); + } +} + +static void timeout_timer_fired(void * p_context) +{ + (void)p_context; + + if (m_procedure_is_active) + { + if (!nrf_802154_request_receive(NRF_802154_TERM_802154, + REQ_ORIG_ACK_TIMEOUT, + notify_tx_error)) + { + timeout_timer_retry(); + } + } +} + +static void timeout_timer_retry(void) +{ + /* + * Fire on next timer tick. dt value will be rounded up to nearest timer granularity + * by call to nrf_802154_timer_sched_add this will prevent potential infinite + * recursion when short delays are called from same context as nrf_802154_timer_sched_add. + */ + m_timer.dt++; + + nrf_802154_timer_sched_add(&m_timer, true); +} + +static void timeout_timer_start(void) +{ + m_timer.callback = timeout_timer_fired; + m_timer.p_context = NULL; + m_timer.t0 = nrf_802154_timer_sched_time_get(); + m_timer.dt = m_timeout; + + m_procedure_is_active = true; + + nrf_802154_timer_sched_add(&m_timer, true); +} + +static void timeout_timer_stop(void) +{ + m_procedure_is_active = false; +} + +void nrf_802154_ack_timeout_time_set(uint32_t time) +{ + m_timeout = time; +} + +bool nrf_802154_ack_timeout_tx_started_hook(const uint8_t * p_frame) +{ + mp_frame = p_frame; + timeout_timer_start(); + + return true; +} + +bool nrf_802154_ack_timeout_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig) +{ + (void)term_lvl; + + if (req_orig != REQ_ORIG_ACK_TIMEOUT) + { + timeout_timer_stop(); + } + + return true; +} + +void nrf_802154_ack_timeout_transmitted_hook(const uint8_t * p_frame) +{ + assert((p_frame == mp_frame) || (!m_procedure_is_active)); + + timeout_timer_stop(); +} + +bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error) +{ + (void)error; + assert((p_frame == mp_frame) || (!m_procedure_is_active)); + + timeout_timer_stop(); + + return true; +} diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h new file mode 100644 index 000000000..e11ca86f9 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_ACK_TIMEOUT_H__ +#define NRF_802154_ACK_TIMEOUT_H__ + +#include +#include + +#include "nrf_802154_const.h" +#include "nrf_802154_types.h" + +/** + * @defgroup nrf_802154_csma_ca 802.15.4 driver ACK timeout support + * @{ + * @ingroup nrf_802154 + * @brief ACK timeout feature. + */ + +/** + * @brief Set timeout time for ACK timeout feature. + * + * @param[in] time Timeout time in us. Timeout is started at the beginning of frame + * transmission (after transmission of PHR). + * Default value is defined in nrf_802154_config.h. + */ +void nrf_802154_ack_timeout_time_set(uint32_t time); + +/** + * @brief Abort started ACK timeout procedure. + * + * @param[in] term_lvl Termination level set by request aborting ongoing operation. + * @param[in] req_orig Module that originates this request. + * + * If ACK timeout procedure is not running during call, this function does nothing. + * + * @retval true ACK timeout procedure han been stopped. + */ +bool nrf_802154_ack_timeout_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig); + +/** + * @brief Handler of transmitted event. + * + * @param[in] p_frame Pointer to the buffer containing transmitted frame. + */ +void nrf_802154_ack_timeout_transmitted_hook(const uint8_t * p_frame); + +/** + * @brief Handler of TX failed event. + * + * @param[in] p_frame Pointer to the buffer containing frame that was not transmitted. + * @param[in] error Cause of failed transmission. + * + * @retval true TX failed event should be propagated to the MAC layer. + * @retval false TX failed event should not be propagated to the MAC layer. It is handled + * internally. + */ +bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error); + + +/** + * @brief Handler of TX started event. + * + * @param[in] p_frame Pointer to the buffer containing frame being transmitted. + * + * @retval true TX started event should be propagated to the MAC layer. + * @retval false TX started event should not be propagated to the MAC layer. It is handled + * internally. + */ +bool nrf_802154_ack_timeout_tx_started_hook(const uint8_t * p_frame); + +/** + *@} + **/ + +#endif // NRF_802154_CSMA_CA_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.c b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.c new file mode 100644 index 000000000..c5c46e584 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.c @@ -0,0 +1,234 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements CSMA-CA procedure for the 802.15.4 driver. + * + */ + +#include "nrf_802154_csma_ca.h" + +#include +#include +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_const.h" +#include "nrf_802154_notification.h" +#include "nrf_802154_request.h" +#include "timer_scheduler/nrf_802154_timer_sched.h" + +static uint8_t m_nb; ///< The number of times the CSMA-CA algorithm was required to back off while attempting the current transmission. +static uint8_t m_be; ///< Backoff exponent, which is related to how many backoff periods a device shall wait before attempting to assess a channel. + +static const uint8_t * mp_psdu; ///< Pointer to PSDU of the frame being transmitted. +static nrf_802154_timer_t m_timer; ///< Timer used to back off during CSMA-CA procedure. +static bool m_is_running; ///< Indicates if CSMA-CA procedure is running. + +/** + * @brief Perform appropriate actions for busy channel conditions. + * + * According to CSMA-CA description in 802.15.4 specification, when channel is busy NB and BE shall + * be incremented and the device shall wait random delay before next CCA procedure. If NB reaches + * macMaxCsmaBackoffs procedure fails. + * + * @retval true Procedure failed and TX failure should be notified to the next higher layer. + * @retval false Procedure is still ongoing and TX failure should be handled internally. + */ +static bool channel_busy(void); + +/** + * @brief Check if CSMA-CA is ongoing. + * + * @retval true CSMA-CA is running. + * @retval false CSMA-CA is not running currently. + */ +static bool procedure_is_running(void) +{ + return m_is_running; +} + +/** + * @brief Stop CSMA-CA procedure. + */ +static void procedure_stop(void) +{ + m_is_running = false; +} + +/** + * Notify MAC layer that channel is busy if tx request failed and there are no retries left. + * + * @param[in] result Result of TX request. + */ +static void notify_busy_channel(bool result) +{ + if (!result && (m_nb >= (NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS - 1))) + { + nrf_802154_notify_transmit_failed(mp_psdu, NRF_802154_TX_ERROR_BUSY_CHANNEL); + } +} + +/** + * @brief Perform CCA procedure followed by frame transmission. + * + * If transmission is requested, CSMA-CA module waits for notification from the FSM module. + * If transmission request fails, CSMA-CA module performs procedure for busy channel condition + * @sa channel_busy(). + * + * @param[in] p_context Unused variable passed from the Timer Scheduler module. + */ +static void frame_transmit(void * p_context) +{ + (void)p_context; + + if (!procedure_is_running()) + { + return; + } + + if (!nrf_802154_request_transmit(NRF_802154_TERM_NONE, + REQ_ORIG_CSMA_CA, + mp_psdu, + true, + notify_busy_channel)) + { + (void)channel_busy(); + } +} + +/** + * @brief Delay CCA procedure for random (2^BE - 1) unit backoff periods. + */ +static void random_backoff_start(void) +{ + uint8_t backoff_periods = rand() % (1 << m_be); + + m_timer.callback = frame_transmit; + m_timer.p_context = NULL; + m_timer.t0 = nrf_802154_timer_sched_time_get(); + m_timer.dt = backoff_periods * UNIT_BACKOFF_PERIOD; + + nrf_802154_timer_sched_add(&m_timer, false); +} + +static bool channel_busy(void) +{ + bool result = true; + + if (procedure_is_running()) + { + m_nb++; + + if (m_be < NRF_802154_CSMA_CA_MAX_BE) + { + m_be++; + } + + if (m_nb < NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS) + { + random_backoff_start(); + result = false; + } + else + { + procedure_stop(); + } + } + + return result; +} + +void nrf_802154_csma_ca_start(const uint8_t * p_data) +{ + assert(!procedure_is_running()); + + mp_psdu = p_data; + m_nb = 0; + m_be = NRF_802154_CSMA_CA_MIN_BE; + m_is_running = true; + + random_backoff_start(); +} + +bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig) +{ + // Don't stop CSMA-CA if request by itself or RAAL. + if (req_orig == REQ_ORIG_CSMA_CA || + req_orig == REQ_ORIG_RAAL) + { + return true; + } + + // Stop CSMA-CA if termination level is high enough. + if (term_lvl >= NRF_802154_TERM_802154) + { + nrf_802154_timer_sched_remove(&m_timer); + procedure_stop(); + + return true; + } + + // Return success in case procedure is already stopped. + if (!procedure_is_running()) + { + return true; + } + + return false; +} + +bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error) +{ + (void)error; + + bool result = true; + + if (p_frame == mp_psdu) + { + result = channel_busy(); + } + + return result; +} + +bool nrf_802154_csma_ca_tx_started_hook(const uint8_t * p_frame) +{ + if (p_frame == mp_psdu) + { + assert(!nrf_802154_timer_sched_is_running(&m_timer)); + procedure_stop(); + } + + return true; +} + diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h new file mode 100644 index 000000000..373d02e10 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_CSMA_CA_H__ +#define NRF_802154_CSMA_CA_H__ + +#include +#include + +#include "nrf_802154_const.h" +#include "nrf_802154_types.h" + +/** + * @defgroup nrf_802154_csma_ca 802.15.4 driver CSMA-CA support + * @{ + * @ingroup nrf_802154 + * @brief CSMA-CA procedure. + */ + +/** + * @brief Start CSMA-CA procedure for transmission of given frame. + * + * If CSMA-CA procedure is successful and frame is transmitted @sa nrf_802154_tx_started() + * function is called. If CSMA/CA procedure failed and frame cannot be transmitted due to busy + * channel @sa nrf_802154_transmit_failed() function is called. + * + * @note CSMA-CA does not timeout waiting for ACK automatically. Waiting for ACK shall be timed out + * by the next layer. ACK timeout timer shall start when @sa nrf_802154_tx_started() + * function is called. + * + * @param[in] p_data Pointer to PSDU of frame that should be transmitted. + */ +void nrf_802154_csma_ca_start(const uint8_t * p_data); + +/** + * @brief Abort ongoing CSMA-CA procedure. + * + * @note This function shall not be called during @sa nrf_802154_csma_ca_start execution + * (i.e. from ISR with higher priority). It would result with unrecoverable runtime error. + * + * If CSMA-CA is not running during call, this function does nothing and returns true. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + + * @retval true CSMA-CA procedure is not running anymore. + * @retval false CSMA-CA cannot be stopped due to too low termination level. + */ +bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig); + +/** + * @brief Handler of TX failed event. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that was not transmitted. + * @param[in] error Cause of failed transmission. + * + * @retval true TX failed event should be propagated to the MAC layer. + * @retval false TX failed event should not be propagated to the MAC layer. It is handled + * internally. + */ +bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error); + +/** + * @brief Handler of TX started event. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that is being transmitted. + * + * @retval true TX started event should be propagated to the MAC layer. + * @retval false TX started event should not be propagated to the MAC layer. It is handled + * internally. + */ +bool nrf_802154_csma_ca_tx_started_hook(const uint8_t * p_frame); + +/** + *@} + **/ + +#endif // NRF_802154_CSMA_CA_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c new file mode 100644 index 000000000..c92922a93 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c @@ -0,0 +1,433 @@ +/* Copyright (c) 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements incoming frame filtering according to 3 and 4 levels of filtering. + * + * Filtering details are specified in 802.15.4-2015: 6.7.2. + * 1st and 2nd filtering level is performed by FSM module depending on promiscuous mode, when FCS is + * received. + */ + +#include "nrf_802154_filter.h" + +#include +#include +#include +#include + +#include "nrf_802154_const.h" +#include "nrf_802154_pib.h" + +#define FCF_CHECK_OFFSET (PHR_SIZE + FCF_SIZE) +#define SHORT_ADDR_CHECK_OFFSET (DEST_ADDR_OFFSET + SHORT_ADDRESS_SIZE) +#define EXTENDED_ADDR_CHECK_OFFSET (DEST_ADDR_OFFSET + EXTENDED_ADDRESS_SIZE) + +/** + * @brief Check if given frame version is allowed for given frame type. + * + * @param[in] frame_type Type of incoming frame. + * @param[in] frame_version Version of incoming frame. + * + * @retval true Given frame version is allowed for given frame type. + * @retval false Given frame version is not allowed for given frame type. + */ +static bool frame_type_and_version_filter(uint8_t frame_type, uint8_t frame_version) +{ + bool result; + + switch (frame_type) + { + case FRAME_TYPE_BEACON: + case FRAME_TYPE_DATA: + case FRAME_TYPE_ACK: + case FRAME_TYPE_COMMAND: + result = (frame_version != FRAME_VERSION_3); + break; + + case FRAME_TYPE_MULTIPURPOSE: + result = (frame_version == FRAME_VERSION_0); + break; + + case FRAME_TYPE_FRAGMENT: + case FRAME_TYPE_EXTENDED: + result = true; + break; + + default: + result = false; + } + + return result; +} + +/** + * @brief Check if given frame type may include destination address fields. + * + * @note Actual presence of destination address fields in the frame is indicated by FCF. + * + * @param[in] frame_type Type of incoming frame. + * + * @retval true Given frame type may include addressing fields. + * @retval false Given frame type may not include addressing fields. + */ +static bool dst_addressing_may_be_present(uint8_t frame_type) +{ + bool result; + + switch (frame_type) + { + case FRAME_TYPE_BEACON: + case FRAME_TYPE_DATA: + case FRAME_TYPE_ACK: + case FRAME_TYPE_COMMAND: + case FRAME_TYPE_MULTIPURPOSE: + result = true; + break; + + case FRAME_TYPE_FRAGMENT: + case FRAME_TYPE_EXTENDED: + result = false; + break; + + default: + result = false; + } + + return result; +} + +/** + * @brief Get offset of end of addressing fields for given frame assuming its version is 2006. + * + * If given frame contains errors that prevent getting offset, this function returns false. If there + * are no destination address fields in given frame, this function returns true and does not modify + * @p p_num_bytes. If there is destination address in given frame, this function returns true and + * inserts offset of addressing fields end to @p p_num_bytes. + * + * @param[in] p_psdu Pointer of PSDU of incoming frame. + * @param[out] p_num_bytes Offset of addressing fields end. + * @param[in] frame_type Type of incoming frame. + * + * @retval true No errors in given frame were detected - it may be further processed. + * @retval false Detected an error in given frame - it should be discarded. + */ +static bool dst_addressing_end_offset_get_2006(const uint8_t * p_psdu, + uint8_t * p_num_bytes, + uint8_t frame_type) +{ + bool result; + + switch (p_psdu[DEST_ADDR_TYPE_OFFSET] & DEST_ADDR_TYPE_MASK) + { + case DEST_ADDR_TYPE_SHORT: + *p_num_bytes = SHORT_ADDR_CHECK_OFFSET; + result = true; + break; + + case DEST_ADDR_TYPE_EXTENDED: + *p_num_bytes = EXTENDED_ADDR_CHECK_OFFSET; + result = true; + break; + + case DEST_ADDR_TYPE_NONE: + if (frame_type == FRAME_TYPE_BEACON) + { + switch (p_psdu[SRC_ADDR_TYPE_OFFSET] & SRC_ADDR_TYPE_MASK) + { + case SRC_ADDR_TYPE_SHORT: + *p_num_bytes = SHORT_ADDR_CHECK_OFFSET; + result = true; + break; + + case SRC_ADDR_TYPE_EXTENDED: + *p_num_bytes = EXTENDED_ADDR_CHECK_OFFSET; + result = true; + break; + + default: + result = false; + } + } + else + { + result = true; + } + + break; + + default: + result = false; + } + + return result; +} + +/** + * @brief Get offset of end of addressing fields for given frame assuming its version is 2015. + * + * If given frame contains errors that prevent getting offset, this function returns false. If there + * are no destination address fields in given frame, this function returns true and does not modify + * @p p_num_bytes. If there is destination address in given frame, this function returns true and + * inserts offset of addressing fields end to @p p_num_bytes. + * + * @param[in] p_psdu Pointer of PSDU of incoming frame. + * @param[out] p_num_bytes Offset of addressing fields end. + * @param[in] frame_type Type of incoming frame. + * + * @retval true No errors in given frame were detected - it may be further processed. + * @retval false Detected an error in given frame - it should be discarded. + */ +static bool dst_addressing_end_offset_get_2015(const uint8_t * p_psdu, + uint8_t * p_num_bytes, + uint8_t frame_type) +{ + bool result = false; + + switch (frame_type) + { + case FRAME_TYPE_BEACON: + case FRAME_TYPE_DATA: + case FRAME_TYPE_ACK: + case FRAME_TYPE_COMMAND: + // TODO: Implement dst addressing filtering according to 2015 spec + result = dst_addressing_end_offset_get_2006(p_psdu, p_num_bytes, frame_type); + break; + + case FRAME_TYPE_MULTIPURPOSE: + // TODO: Implement dst addressing filtering according to 2015 spec + result = false; + break; + + case FRAME_TYPE_FRAGMENT: + case FRAME_TYPE_EXTENDED: + // No addressing data + result = true; + break; + } + + return result; +} + +/** + * @brief Get offset of end of addressing fields for given frame. + * + * If given frame contains errors that prevent getting offset, this function returns false. If there + * are no destination address fields in given frame, this function returns true and does not modify + * @p p_num_bytes. If there is destination address in given frame, this function returns true and + * inserts offset of addressing fields end to @p p_num_bytes. + * + * @param[in] p_psdu Pointer of PSDU of incoming frame. + * @param[out] p_num_bytes Offset of addressing fields end. + * @param[in] frame_type Type of incoming frame. + * + * @retval true No errors in given frame were detected - it may be further processed. + * @retval false Detected an error in given frame - it should be discarded. + */ +static bool dst_addressing_end_offset_get(const uint8_t * p_psdu, + uint8_t * p_num_bytes, + uint8_t frame_type, + uint8_t frame_version) +{ + bool result; + + switch (frame_version) + { + case FRAME_VERSION_0: + case FRAME_VERSION_1: + result = dst_addressing_end_offset_get_2006(p_psdu, p_num_bytes, frame_type); + break; + + case FRAME_VERSION_2: + result = dst_addressing_end_offset_get_2015(p_psdu, p_num_bytes, frame_type); + break; + + default: + result = false; + } + + return result; +} + +/** + * Verify if destination PAN Id of incoming frame allows processing by this node. + * + * @param[in] p_psdu Pointer of PSDU of incoming frame. + * + * @retval true PAN Id of incoming frame allows further processing of the frame. + * @retval false PAN Id of incoming frame does not allow further processing. + */ +static bool dst_pan_id_check(const uint8_t * p_psdu) +{ + bool result; + + if ((0 == memcmp(&p_psdu[PAN_ID_OFFSET], nrf_802154_pib_pan_id_get(), PAN_ID_SIZE)) || + (0 == memcmp(&p_psdu[PAN_ID_OFFSET], BROADCAST_ADDRESS, PAN_ID_SIZE))) + { + result = true; + } + else if ((FRAME_TYPE_BEACON == (p_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK)) && + (0 == memcmp(nrf_802154_pib_pan_id_get(), BROADCAST_ADDRESS, PAN_ID_SIZE))) + { + result = true; + } + else + { + result = false; + } + + return result; +} + +/** + * Verify if destination short address of incoming frame allows processing by this node. + * + * @param[in] p_psdu Pointer of PSDU of incoming frame. + * + * @retval true Destination address of incoming frame allows further processing of the frame. + * @retval false Destination address of incoming frame does not allow further processing. + */ +static bool dst_short_addr_check(const uint8_t * p_psdu) +{ + bool result; + + if ((0 == memcmp(&p_psdu[DEST_ADDR_OFFSET], + nrf_802154_pib_short_address_get(), + SHORT_ADDRESS_SIZE)) || + (0 == memcmp(&p_psdu[DEST_ADDR_OFFSET], BROADCAST_ADDRESS, SHORT_ADDRESS_SIZE))) + { + result = true; + } + else if (FRAME_TYPE_BEACON == (p_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK)) + { + result = true; + } + else + { + result = false; + } + + return result; +} + +/** + * Verify if destination extended address of incoming frame allows processing by this node. + * + * @param[in] p_psdu Pointer of PSDU of incoming frame. + * + * @retval true Destination address of incoming frame allows further processing of the frame. + * @retval false Destination address of incoming frame does not allow further processing. + */ +static bool dst_extended_addr_check(const uint8_t *p_psdu) +{ + bool result; + + if (0 == memcmp(&p_psdu[DEST_ADDR_OFFSET], + nrf_802154_pib_extended_address_get(), + EXTENDED_ADDRESS_SIZE)) + { + result = true; + } + else if (FRAME_TYPE_BEACON == (p_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK)) + { + result = true; + } + else + { + result = false; + } + + return result; +} + +nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8_t * p_num_bytes) +{ + nrf_802154_rx_error_t result; + + switch (*p_num_bytes) + { + case FCF_CHECK_OFFSET: + { + if (p_psdu[0] < ACK_LENGTH || p_psdu[0] > MAX_PACKET_SIZE) + { + // Frame length is invalid + result = NRF_802154_RX_ERROR_INVALID_FRAME; + break; + } + + uint8_t frame_type = p_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK; + uint8_t frame_version = p_psdu[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK; + + if (!frame_type_and_version_filter(frame_type, frame_version)) + { + result = NRF_802154_RX_ERROR_INVALID_FRAME; + break; + } + + if (!dst_addressing_may_be_present(frame_type)) + { + result = NRF_802154_RX_ERROR_NONE; + break; + } + + result = dst_addressing_end_offset_get(p_psdu, p_num_bytes, frame_type, frame_version) ? + NRF_802154_RX_ERROR_NONE : NRF_802154_RX_ERROR_INVALID_FRAME; + break; + } + + case SHORT_ADDR_CHECK_OFFSET: + if (!dst_pan_id_check(p_psdu)) + { + result = NRF_802154_RX_ERROR_INVALID_DEST_ADDR; + break; + } + + result = dst_short_addr_check(p_psdu) ? NRF_802154_RX_ERROR_NONE : + NRF_802154_RX_ERROR_INVALID_DEST_ADDR; + break; + + case EXTENDED_ADDR_CHECK_OFFSET: + if (!dst_pan_id_check(p_psdu)) + { + result = NRF_802154_RX_ERROR_INVALID_DEST_ADDR; + break; + } + + result = dst_extended_addr_check(p_psdu) ? NRF_802154_RX_ERROR_NONE : + NRF_802154_RX_ERROR_INVALID_DEST_ADDR; + break; + + default: + assert(false); + } + + return result; +} diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h new file mode 100644 index 000000000..434d3247b --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @brief This file implements incoming frame filter API. + * + */ + +#ifndef NRF_802154_FILTER_H_ +#define NRF_802154_FILTER_H_ + +#include +#include + +#include "nrf_802154_types.h" + +/** + * @defgroup nrf_802154_filter Incoming frame filter API. + * @{ + * @ingroup nrf_802154 + * @brief Procedures used to discard incoming frames that contain unexpected data in PHR or MHR. + */ + + +/** + * @brief Verify if given part of the frame is valid. + * + * This function is called a few times for each received frame. First call is after FCF is received + * (PSDU length is 1 - @p p_num_bytes value is 1). Subsequent calls are performed when number of + * bytes requested by previous call is available. Iteration ends when function does not request + * any more bytes to check. + * If verified part of the function is correct this function returns true and sets @p p_num_bytes to + * number of bytes that should be available in PSDU during next iteration. If frame is correct and + * there is nothing more to check, function returns true and does not modify @p p_num_bytes value. + * If verified frame is incorrect this function returns false and @p p_num_bytes value is undefined. + * + * @param[in] p_psdu Pointer to PSDU of incoming frame. + * @param[inout] p_num_bytes Number of bytes available in @p p_psdu buffer. This value is set to + * requested number of bytes for next iteration or this value is + * unchanged if no more iterations shall be performed during filtering of + * given frame. + * + * @retval NRF_802154_RX_ERROR_NONE Verified part of the incoming frame is valid. + * @retval NRF_802154_RX_ERROR_INVALID_FRAME Verified part of the incoming frame is invalid. + * @retval NRF_802154_RX_ERROR_INVALID_DEST_ADDR Incoming frame has destination address that + * mismatches address of this node. + */ +nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8_t * p_num_bytes); + +#endif /* NRF_802154_FILTER_H_ */ + diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c new file mode 100644 index 000000000..57c6f4823 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c @@ -0,0 +1,686 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements the nrf 802.15.4 radio driver. + * + */ + +#include "nrf_802154.h" + +#include +#include +#include +#include +#include + +#include "nrf_802154_ack_pending_bit.h" +#include "nrf_802154_config.h" +#include "nrf_802154_const.h" +#include "nrf_802154_core.h" +#include "nrf_802154_critical_section.h" +#include "nrf_802154_debug.h" +#include "nrf_802154_notification.h" +#include "nrf_802154_pib.h" +#include "nrf_802154_priority_drop.h" +#include "nrf_802154_request.h" +#include "nrf_802154_revision.h" +#include "nrf_802154_rx_buffer.h" +#include "hal/nrf_radio.h" +#include "platform/clock/nrf_802154_clock.h" +#include "platform/timer/nrf_802154_timer.h" +#include "raal/nrf_raal_api.h" +#include "timer_scheduler/nrf_802154_timer_sched.h" + +#include "mac_features/nrf_802154_csma_ca.h" +#include "mac_features/nrf_802154_ack_timeout.h" + +#if ENABLE_FEM +#include "fem/nrf_fem_control_api.h" +#endif + +#define RAW_LENGTH_OFFSET 0 +#define RAW_PAYLOAD_OFFSET 1 + +#if !NRF_802154_USE_RAW_API +/** Static transmit buffer used by @sa nrf_802154_transmit() family of functions. + * + * If none of functions using this buffer is called and link time optimization is enabled, this + * buffer should be removed by linker. + */ +static uint8_t m_tx_buffer[RAW_PAYLOAD_OFFSET + MAX_PACKET_SIZE]; + +/** + * @brief Fill transmit buffer with given data. + * + * @param[in] p_data Pointer to array containing payload of a data to transmit. The array + * should exclude PHR or FCS fields of 802.15.4 frame. + * @param[in] length Length of given frame. This value shall exclude PHR and FCS fields from + * the given frame (exact size of buffer pointed by @p p_data). + */ +static void tx_buffer_fill(const uint8_t * p_data, uint8_t length) +{ + assert(length <= MAX_PACKET_SIZE - FCS_SIZE); + + m_tx_buffer[RAW_LENGTH_OFFSET] = length + FCS_SIZE; + memcpy(&m_tx_buffer[RAW_PAYLOAD_OFFSET], p_data, length); +} +#endif // !NRF_802154_USE_RAW_API + + +void nrf_802154_channel_set(uint8_t channel) +{ + bool changed = nrf_802154_pib_channel_get() != channel; + + nrf_802154_pib_channel_set(channel); + + if (changed) + { + nrf_802154_request_channel_update(); + } +} + +uint8_t nrf_802154_channel_get(void) +{ + return nrf_802154_pib_channel_get(); +} + +void nrf_802154_tx_power_set(int8_t power) +{ + nrf_802154_pib_tx_power_set(power); +} + +int8_t nrf_802154_tx_power_get(void) +{ + return nrf_802154_pib_tx_power_get(); +} + +void nrf_802154_pan_id_set(const uint8_t * p_pan_id) +{ + nrf_802154_pib_pan_id_set(p_pan_id); +} + +void nrf_802154_extended_address_set(const uint8_t * p_extended_address) +{ + nrf_802154_pib_extended_address_set(p_extended_address); +} + +void nrf_802154_short_address_set(const uint8_t * p_short_address) +{ + nrf_802154_pib_short_address_set(p_short_address); +} + +int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level) +{ + return ED_MIN_DBM + (energy_level / ED_RESULT_FACTOR); +} + +uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length) +{ + uint32_t frame_symbols = PHY_SHR_DURATION; + frame_symbols += (PHR_SIZE + psdu_length) * PHY_SYMBOLS_PER_OCTET; + + return end_timestamp - (frame_symbols * PHY_US_PER_SYMBOL); +} + +void nrf_802154_init(void) +{ + nrf_802154_ack_pending_bit_init(); + nrf_802154_core_init(); + nrf_802154_clock_init(); + nrf_802154_critical_section_init(); + nrf_802154_debug_init(); + nrf_802154_notification_init(); + nrf_802154_pib_init(); + nrf_802154_priority_drop_init(); + nrf_802154_request_init(); + nrf_802154_revision_init(); + nrf_802154_rx_buffer_init(); + nrf_802154_timer_init(); + nrf_raal_init(); +} + +void nrf_802154_deinit(void) +{ + nrf_802154_timer_deinit(); + nrf_802154_clock_deinit(); + nrf_802154_core_deinit(); +} + +#if !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +void nrf_802154_radio_irq_handler(void) +{ + nrf_802154_core_irq_handler(); +} +#endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING + +#if ENABLE_FEM +void nrf_802154_fem_control_cfg_set(const nrf_802154_fem_control_cfg_t * p_cfg) +{ + nrf_fem_control_cfg_set(p_cfg); +} + +void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg) +{ + nrf_fem_control_cfg_get(p_cfg); +} +#endif // ENABLE_FEM + +nrf_802154_state_t nrf_802154_state_get(void) +{ + switch (nrf_802154_core_state_get()) + { + case RADIO_STATE_SLEEP: + case RADIO_STATE_FALLING_ASLEEP: + return NRF_802154_STATE_SLEEP; + + case RADIO_STATE_RX: + case RADIO_STATE_TX_ACK: + return NRF_802154_STATE_RECEIVE; + + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + case RADIO_STATE_RX_ACK: + return NRF_802154_STATE_TRANSMIT; + + case RADIO_STATE_ED: + return NRF_802154_STATE_ENERGY_DETECTION; + + case RADIO_STATE_CCA: + return NRF_802154_STATE_CCA; + + case RADIO_STATE_CONTINUOUS_CARRIER: + return NRF_802154_STATE_CONTINUOUS_CARRIER; + } + + return NRF_802154_STATE_INVALID; +} + +bool nrf_802154_sleep(void) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_SLEEP); + + result = nrf_802154_request_sleep(NRF_802154_TERM_802154); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_SLEEP); + return result; +} + +bool nrf_802154_receive(void) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RECEIVE); + + result = nrf_802154_request_receive(NRF_802154_TERM_802154, REQ_ORIG_HIGHER_LAYER, NULL); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RECEIVE); + return result; +} + +#if NRF_802154_USE_RAW_API +bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT); + + result = nrf_802154_request_transmit(NRF_802154_TERM_NONE, + REQ_ORIG_HIGHER_LAYER, + p_data, + cca, + NULL); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_TRANSMIT); + return result; +} + +#else // NRF_802154_USE_RAW_API + +bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT); + + tx_buffer_fill(p_data, length); + result = nrf_802154_request_transmit(NRF_802154_TERM_NONE, + REQ_ORIG_HIGHER_LAYER, + m_tx_buffer, + cca, + NULL); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_TRANSMIT); + return result; +} + +#endif // NRF_802154_USE_RAW_API + +bool nrf_802154_energy_detection(uint32_t time_us) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_ENERGY_DETECTION); + + result = nrf_802154_request_energy_detection(NRF_802154_TERM_NONE, time_us); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_ENERGY_DETECTION); + return result; +} + +bool nrf_802154_cca(void) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CCA); + + result = nrf_802154_request_cca(NRF_802154_TERM_NONE); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_CCA); + return result; +} + +bool nrf_802154_continuous_carrier(void) +{ + bool result; + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CONTINUOUS_CARRIER); + + result = nrf_802154_request_continuous_carrier(NRF_802154_TERM_NONE); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_CONTINUOUS_CARRIER); + return result; +} + +#if NRF_802154_USE_RAW_API + +void nrf_802154_buffer_free_raw(uint8_t * p_data) +{ + bool result; + rx_buffer_t * p_buffer = (rx_buffer_t *)p_data; + + assert(p_buffer->free == false); + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); + + result = nrf_802154_request_buffer_free(p_data); + assert(result); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); +} + +#else // NRF_802154_USE_RAW_API + +void nrf_802154_buffer_free(uint8_t * p_data) +{ + bool result; + rx_buffer_t * p_buffer = (rx_buffer_t *)(p_data - RAW_PAYLOAD_OFFSET); + + assert(p_buffer->free == false); + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); + + result = nrf_802154_request_buffer_free(p_data - RAW_PAYLOAD_OFFSET); + assert(result); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); +} + +#endif // NRF_802154_USE_RAW_API + +int8_t nrf_802154_rssi_last_get(void) +{ + uint8_t minus_dbm = nrf_radio_rssi_sample_get(); + return - (int8_t)minus_dbm; +} + +int8_t nrf_802154_rssi_corrected_get(int8_t rssi, int8_t temp) +{ + if (temp <= -30) + { + return rssi + 3; + } + + if (temp <= -10) + { + return rssi + 2; + } + + if (temp <= 10) + { + return rssi + 1; + } + + if (temp <= 30) + { + return rssi; + } + + if (temp <= 50) + { + return rssi - 1; + } + + if (temp <= 70) + { + return rssi - 2; + } + + return rssi - 3; +} + +bool nrf_802154_promiscuous_get(void) +{ + return nrf_802154_pib_promiscuous_get(); +} + +void nrf_802154_promiscuous_set(bool enabled) +{ + nrf_802154_pib_promiscuous_set(enabled); +} + +void nrf_802154_auto_ack_set(bool enabled) +{ + nrf_802154_pib_auto_ack_set(enabled); +} + +bool nrf_802154_auto_ack_get(void) +{ + return nrf_802154_pib_auto_ack_get(); +} + +void nrf_802154_auto_pending_bit_set(bool enabled) +{ + nrf_802154_ack_pending_bit_set(enabled); +} + +bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended) +{ + return nrf_802154_ack_pending_bit_for_addr_set(p_addr, extended); +} + +bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended) +{ + return nrf_802154_ack_pending_bit_for_addr_clear(p_addr, extended); +} + +void nrf_802154_pending_bit_for_addr_reset(bool extended) +{ + nrf_802154_ack_pending_bit_for_addr_reset(extended); +} + +void nrf_802154_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg) +{ + nrf_802154_pib_cca_cfg_set(p_cca_cfg); + + nrf_802154_request_cca_cfg_update(); +} + +void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg) +{ + nrf_802154_pib_cca_cfg_get(p_cca_cfg); +} + +#if NRF_802154_CSMA_CA_ENABLED +#if NRF_802154_USE_RAW_API + +void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data) +{ + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CSMACA); + + nrf_802154_csma_ca_start(p_data); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_CSMACA); +} + +#else // NRF_802154_USE_RAW_API + +void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length) +{ + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CSMACA); + + tx_buffer_fill(p_data, length); + + nrf_802154_csma_ca_start(m_tx_buffer); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_CSMACA); +} + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_CSMA_CA_ENABLED + +#if NRF_802154_ACK_TIMEOUT_ENABLED + +void nrf_802154_ack_timeout_set(uint32_t time) +{ + nrf_802154_ack_timeout_time_set(time); +} + +#endif // NRF_802154_ACK_TIMEOUT_ENABLED + +__WEAK void nrf_802154_tx_ack_started(void) +{ + // Intentionally empty +} + +#if NRF_802154_USE_RAW_API +__WEAK void nrf_802154_received_raw(uint8_t * p_data, int8_t power, uint8_t lqi) +{ +#if NRF_802154_FRAME_TIMESTAMP_ENABLED + uint32_t timestamp = nrf_802154_timer_sched_time_get(); + + nrf_802154_received_timestamp_raw(p_data, power, lqi, timestamp); +#else // NRF_802154_FRAME_TIMESTAMP_ENABLED + nrf_802154_buffer_free_raw(p_data); +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED +} + +#else // NRF_802154_USE_RAW_API +__WEAK void nrf_802154_received(uint8_t * p_data, uint8_t length, int8_t power, uint8_t lqi) +{ +#if NRF_802154_FRAME_TIMESTAMP_ENABLED + uint32_t timestamp = nrf_802154_timer_sched_time_get(); + + nrf_802154_received_timestamp(p_data, length, power, lqi, timestamp); +#else // NRF_802154_FRAME_TIMESTAMP_ENABLED + (void)length; + (void)power; + (void)lqi; + + nrf_802154_buffer_free(p_data); +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED +} +#endif // !NRF_802154_USE_RAW_API + +#if NRF_802154_FRAME_TIMESTAMP_ENABLED +#if NRF_802154_USE_RAW_API + +__WEAK void nrf_802154_received_timestamp_raw(uint8_t * p_data, + int8_t power, + uint8_t lqi, + uint32_t time) +{ + (void)power; + (void)lqi; + (void)time; + + nrf_802154_buffer_free_raw(p_data); +} + +#else // NRF_802154_USE_RAW_API + +__WEAK void nrf_802154_received_timestamp(uint8_t * p_data, + uint8_t length, + int8_t power, + uint8_t lqi, + uint32_t time) +{ + (void)length; + (void)power; + (void)lqi; + (void)time; + + nrf_802154_buffer_free(p_data); +} + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED + +__WEAK void nrf_802154_receive_failed(nrf_802154_rx_error_t error) +{ + (void)error; +} + +__WEAK void nrf_802154_tx_started(const uint8_t * p_frame) +{ + (void)p_frame; +} + +#if NRF_802154_USE_RAW_API +__WEAK void nrf_802154_transmitted_raw(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + uint8_t lqi) +{ +#if NRF_802154_FRAME_TIMESTAMP_ENABLED + + uint32_t timestamp = (p_ack == NULL) ? 0 : nrf_802154_timer_sched_time_get(); + + nrf_802154_transmitted_timestamp_raw(p_frame, p_ack, power, lqi, timestamp); + +#else // NRF_802154_FRAME_TIMESTAMP_ENABLED + + (void)p_frame; + (void)power; + (void)lqi; + + if (p_ack != NULL) + { + nrf_802154_buffer_free_raw(p_ack); + } + +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED +} + +#else // NRF_802154_USE_RAW_API +__WEAK void nrf_802154_transmitted(const uint8_t * p_frame, + uint8_t * p_ack, + uint8_t length, + int8_t power, + uint8_t lqi) +{ +#if NRF_802154_FRAME_TIMESTAMP_ENABLED + + uint32_t timestamp = (p_ack == NULL) ? 0 : nrf_802154_timer_sched_time_get(); + + nrf_802154_transmitted_timestamp(p_frame, p_ack, length, power, lqi, timestamp); + +#else // NRF_802154_FRAME_TIMESTAMP_ENABLED + + (void)p_frame; + (void)length; + (void)power; + (void)lqi; + + if (p_ack != NULL) + { + nrf_802154_buffer_free(p_ack); + } + +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED +} +#endif // NRF_802154_USE_RAW_API + + +#if NRF_802154_FRAME_TIMESTAMP_ENABLED +#if NRF_802154_USE_RAW_API + +__WEAK void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + uint8_t lqi, + uint32_t time) +{ + (void)p_frame; + (void)power; + (void)lqi; + (void)time; + + if (p_ack != NULL) + { + nrf_802154_buffer_free_raw(p_ack); + } +} + +#else // NRF_802154_USE_RAW_API + +__WEAK void nrf_802154_transmitted_timestamp(const uint8_t * p_frame, + uint8_t * p_ack, + uint8_t length, + int8_t power, + uint8_t lqi, + uint32_t time) +{ + (void)p_frame; + (void)length; + (void)power; + (void)lqi; + (void)time; + + if (p_ack != NULL) + { + nrf_802154_buffer_free(p_ack); + } +} + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED + +__WEAK void nrf_802154_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error) +{ + (void)p_frame; + (void)error; +} + +__WEAK void nrf_802154_energy_detected(uint8_t result) +{ + (void)result; +} + +__WEAK void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error) +{ + (void)error; +} + +__WEAK void nrf_802154_cca_done(bool channel_free) +{ + (void)channel_free; +} + +__WEAK void nrf_802154_cca_failed(nrf_802154_cca_error_t error) +{ + (void)error; +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h new file mode 100644 index 000000000..1642c2caf --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h @@ -0,0 +1,951 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @brief This module contains generic 802.15.4 radio driver for nRF SoC devices. + * + */ + +#ifndef NRF_802154_H_ +#define NRF_802154_H_ + +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_types.h" + +#if ENABLE_FEM +#include "fem/nrf_fem_control_api.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize 802.15.4 driver. + * + * @note This function shall be called once, before any other function from this module. + * + * Initialize radio peripheral to Sleep state. + */ +void nrf_802154_init(void); + +/** + * @brief Deinitialize 802.15.4 driver. + * + * Deinitialize radio peripheral and reset it to the default state. + */ +void nrf_802154_deinit(void); + +#if !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +/** + * @brief Handle interrupt request from the RADIO peripheral. + * + * @note When NRF_802154_INTERNAL_RADIO_IRQ_HANDLING is enabled the driver internally handles the + * RADIO IRQ and this function shall not be called. + * + * This function is intended to be used in Operating System environment when the OS handles IRQ + * and indirectly passes it to the driver or with RAAL implementation that indirectly passes radio + * IRQ handler to the driver (i.e. SoftDevice). + */ +void nrf_802154_radio_irq_handler(void); +#endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING + +/** + * @brief Set channel on which the radio shall operate right now. + * + * @param[in] channel Channel number (11-26). + */ +void nrf_802154_channel_set(uint8_t channel); + +/** + * @brief Get channel on which the radio operates right now. + * + * @returns Channel number (11-26). + */ +uint8_t nrf_802154_channel_get(void); + +/** + * @brief Set transmit power. + * + * @note The driver recalculates requested value to the nearest value accepted by the hardware. + * The calculation result is rounded up. + * + * @param[in] power Transmit power [dBm]. + */ +void nrf_802154_tx_power_set(int8_t power); + +/** + * @brief Get currently set transmit power. + * + * @return Currently used transmit power [dBm]. + */ +int8_t nrf_802154_tx_power_get(void); + +/*************************************************************************************************** + * @section Front-end module management. + **************************************************************************************************/ + +#if ENABLE_FEM + +/** Structure containing run-time configuration of FEM module. */ +typedef nrf_fem_control_cfg_t nrf_802154_fem_control_cfg_t; + +/** Macro with default configuration of FEM module. */ +#define NRF_802154_FEM_DEFAULT_SETTINGS \ + ((nrf_802154_fem_control_cfg_t) { \ + .pa_cfg = { \ + .enable = 1, \ + .active_high = 1, \ + .gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \ + }, \ + .lna_cfg = { \ + .enable = 1, \ + .active_high = 1, \ + .gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \ + }, \ + .pa_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL, \ + .lna_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL, \ + .ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \ + .ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \ + }) + +/** + * @brief Set PA & LNA GPIO toggle configuration. + * + * @note This function shall not be called when radio is in use. + * + * @param[in] p_cfg A pointer to the PA & LNA GPIO toggle configuration. + * + */ +void nrf_802154_fem_control_cfg_set(const nrf_802154_fem_control_cfg_t * p_cfg); + +/** + * @brief Get PA & LNA GPIO toggle configuration. + * + * @param[out] p_cfg A pointer to the structure for the PA & LNA GPIO toggle configuration. + * + */ +void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg); + +#endif // ENABLE_FEM + + +/*************************************************************************************************** + * @section Setting addresses and Pan Id of this device. + **************************************************************************************************/ + +/** + * @brief Set PAN Id used by this device. + * + * @param[in] p_pan_id Pointer to PAN Id (2 bytes, little-endian). + * + * This function makes copy of the PAN Id. + */ +void nrf_802154_pan_id_set(const uint8_t *p_pan_id); + +/** + * @brief Set Extended Address of this device. + * + * @param[in] p_extended_address Pointer to extended address (8 bytes, little-endian). + * + * This function makes copy of the address. + */ +void nrf_802154_extended_address_set(const uint8_t *p_extended_address); + +/** + * @brief Set Short Address of this device. + * + * @param[in] p_short_address Pointer to short address (2 bytes, little-endian). + * + * This function makes copy of the address. + */ +void nrf_802154_short_address_set(const uint8_t *p_short_address); + + +/*************************************************************************************************** + * @section Functions to calculate data given by the driver. + **************************************************************************************************/ + +/** + * @brief Calculate dBm from energy level received during energy detection procedure. + * + * @param[in] energy_level Energy level passed by @sa nrf_802154_energy_detected + * + * @return Result of energy detection procedure in dBm. + */ +int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level); + +/** + * @brief Calculate timestamp of beginning of first symbol of preamble in a received frame. + * + * @param[in] end_timestamp Timestamp of end of last symbol in the frame (in us). + * @param[in] psdu_length Number of bytes in the frame PSDU. + * + * @return Timestamp of first preamble symbol of given frame (in us). + */ +uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length); + + +/*************************************************************************************************** + * @section Functions to request FSM transitions and check current state. + **************************************************************************************************/ + +/** + * @brief Get current state of the radio. + */ +nrf_802154_state_t nrf_802154_state_get(void); + +/** + * @brief Change radio state to Sleep. + * + * Sleep state is the lowest power state. In this state radio cannot transmit or receive frames. + * It is the only state in which the driver releases high frequency clock and does not request + * timeslots from a radio arbiter. + * + * @note High frequency clock may be enabled even in radio Sleep state if other module requests it. + * + * @return true If the radio changes it's state to low power mode. + * @return false If the driver could not schedule changing state. + */ +bool nrf_802154_sleep(void); + +/** + * @brief Change radio state to Receive. + * + * In Receive state radio receives frames and may automatically send ACK frames when appropriate. + * Received frame is reported to higher layer by @sa nrf_radio802154_received() call. + * + * @return true If the radio enters Receive state. + * @return false If the driver could not enter Receive state. + */ +bool nrf_802154_receive(void); + +#if NRF_802154_USE_RAW_API +/** + * @brief Change radio state to Transmit. + * + * @note If the CPU was halted or interrupted during performing this function + * @sa nrf_802154_transmitted() or @sa nrf_802154_transmit_failed() may be + * called before nrf_802154_transmit_raw() returns result. + * @note This function is implemented in zero-copy fashion. It passes given buffer pointer to + * the RADIO peripheral. + * + * In Transmit state radio transmits given frame. If requested it waits for ACK frame. + * Depending on @sa NRF_802154_ACK_TIMEOUT_ENABLED configuration option, Radio driver automatically + * stops waiting for an ACK frame or waits infinitely for an ACK frame. If it is configured to wait + * indefinitely, MAC layer is responsible to call @sa nrf_radio802154_receive() or + * @sa nrf_radio802154_sleep() after ACK timeout. + * Transmission result is reported to higher layer by @sa nrf_radio802154_transmitted() or + * @sa nrf_radio802154_transmit_failed() calls. + * + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC Header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <---------------------------- PHR -----------------------------------> | + * + * @param[in] p_data Pointer to array containing data to transmit. First byte should contain + * frame length (including PHR and FCS). Following bytes should contain data. + * CRC is computed automatically by radio hardware and because of that FCS + * field can contain any bytes. + * @param[in] cca If the driver should perform CCA procedure before transmission. + * + * @return true If the transmission procedure was scheduled. + * @return false If the driver could not schedule the transmission procedure. + */ +bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Change radio state to Transmit. + * + * @note If the CPU was halted or interrupted during performing this function + * @sa nrf_802154_transmitted() or @sa nrf_802154_transmit_failed() may be + * called before nrf_802154_transmit() returns result. + * @note This function makes copy of given buffer. There is an internal buffer maintained by this + * function. It is used to make a frame copy. To prevent unnecessary memory consumption and + * to perform zero-copy transmission @sa nrf_802154_transmit_raw() function should + * be used instead of this. + * + * In Transmit state radio transmits given frame. If requested it waits for ACK frame. + * Depending on @sa NRF_802154_ACK_TIMEOUT_ENABLED configuration option, Radio driver automatically + * stops waiting for an ACK frame or waits infinitely for an ACK frame. If it is configured to wait + * indefinitely, MAC layer is responsible to call @sa nrf_radio802154_receive() or + * @sa nrf_radio802154_sleep() after ACK timeout. + * Transmission result is reported to higher layer by @sa nrf_radio802154_transmitted() or + * @sa nrf_radio802154_transmit_failed() calls. + * + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC Header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <------------------ length -----------------------------> | + * + * @param[in] p_data Pointer to array containing payload of a data to transmit. The array + * should exclude PHR or FCS fields of 802.15.4 frame. + * @param[in] length Length of given frame. This value shall exclude PHR and FCS fields from + * the given frame (exact size of buffer pointed by @p p_data). + * @param[in] cca If the driver should perform CCA procedure before transmission. + * + * @return true If the transmission procedure was scheduled. + * @return false If the driver could not schedule the transmission procedure. + */ +bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca); + +#endif // NRF_802154_USE_RAW_API + +/** + * @brief Change radio state to Energy Detection. + * + * In Energy Detection state radio detects maximum energy for given time. Result of the detection + * is reported to the higher layer by @sa nrf_802154_energy_detected() call. + * + * @note @sa nrf_802154_energy_detected() may be called before nrf_802154_energy_detection() + * returns result. + * @note Performing Energy Detection procedure make take longer than time requested in @p time_us. + * Procedure is performed only during timeslots granted by a radio arbiter. It may be + * interrupted by other protocols using radio hardware. If procedure is interrupted, it is + * automatically continued and the sum of time periods during which the procedure is carried + * out is not less than requested @p time_us. + * + * @param[in] time_us Duration of energy detection procedure. Given value is rounded up to + * multiplication of 8s (128 us). + * + * @return true If the energy detection procedure was scheduled. + * @return false If the driver could not schedule the energy detection procedure. + */ +bool nrf_802154_energy_detection(uint32_t time_us); + +/** + * @brief Change radio state to CCA. + * + * @note @sa nrf_802154_cca_done() may be called before nrf_802154_cca() returns result. + * + * In CCA state radio verifies if channel is clear. Result of verification is reported to the higher + * layer by @sa nrf_802154_cca_done() call. + * + * @return true If the CCA procedure was scheduled. + * @return false If the driver could not schedule the CCA procedure. + */ +bool nrf_802154_cca(void); + +/** + * @brief Change radio state to Continuous Carrier. + * + * @note When radio is emitting continuous carrier it blocks all transmissions on selected channel. + * This function should be called only during radio tests. It should not be used during + * normal device operation. + * @note This function works correctly only with a single-phy arbiter. It should not be used with + * any other arbiter. + * + * @return true If the continuous carrier procedure was scheduled. + * @return false If the driver could not schedule the continuous carrier procedure. + */ +bool nrf_802154_continuous_carrier(void); + + +/*************************************************************************************************** + * @section Calls to higher layer. + **************************************************************************************************/ + +/** + * @brief Notify that transmitting ACK frame has started. + * + * @note This function should be very short to prevent dropping frames by the driver. + */ +extern void nrf_802154_tx_ack_started(void); + +#if NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was received. + * + * @note Buffer pointed by the p_data pointer is not modified by the radio driver (and can't + * be used to receive a frame) until @sa nrf_802154_buffer_free_raw() function is called. + * @note Buffer pointed by the p_data pointer may be modified by the function handler (and other + * modules) until @sa nrf_802154_buffer_free_raw() function is called. + * + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC Header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <---------------------------- PHR -----------------------------------> | + * + * @param[in] p_data Pointer to the buffer containing received data (PHR + PSDU). First byte in + * the buffer is length of the frame (PHR) and following bytes is the frame + * itself (PSDU). Length byte (PHR) includes FCS. FCS is already verified by + * the hardware and may be modified by the hardware. + * @param[in] power RSSI of received frame. + * @param[in] lqi LQI of received frame. + */ +extern void nrf_802154_received_raw(uint8_t * p_data, int8_t power, uint8_t lqi); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was received. + * + * @note Buffer pointed by the p_data pointer is not modified by the radio driver (and can't + * be used to receive a frame) until nrf_802154_buffer_free() function is called. + * @note Buffer pointed by the p_data pointer may be modified by the function handler (and other + * modules) until @sa nrf_802154_buffer_free() function is called. + * + * p_data + * v + * +-----+-----------------------------------------------------------+------------+ + * | PHR | MAC Header and payload | FCS | + * +-----+-----------------------------------------------------------+------------+ + * | | + * | <------------------ length -----------------------------> | + * + * @param[in] p_data Pointer to the buffer containing payload of received frame (PSDU without FCS). + * @param[in] length Length of received payload. + * @param[in] power RSSI of received frame. + * @param[in] lqi LQI of received frame. + */ +extern void nrf_802154_received(uint8_t * p_data, uint8_t length, int8_t power, uint8_t lqi); + +#endif // !NRF_802154_USE_RAW_API + +#if NRF_802154_FRAME_TIMESTAMP_ENABLED +#if NRF_802154_USE_RAW_API +/** + * @brief Notify that frame was received at given time + * + * This functions works like @sa nrf_802154_received_raw and adds timestamp to parameter + * list. + * + * @note @p timestamp may be inacurate due to software latency (IRQ handling). + * @note @p timestamp granularity depends on granularity of the timer driver in platform/timer + * directory. + * @note Including timestamp to received frame uses resources like CPU time and memory. If timestamp + * is not required use @sa nrf_802154_received_raw() instead. + * + * @param[in] p_data Pointer to the buffer containing received data (PHR + PSDU). First byte in + * the buffer is length of the frame (PHR) and following bytes is the frame + * itself (PSDU). Length byte (PHR) includes FCS. FCS is already verified by + * the hardware and may be modified by the hardware. + * @param[in] power RSSI of received frame. + * @param[in] lqi LQI of received frame. + * @param[in] time Timestamp taken when last symbol of the frame was received (in us). + */ +extern void nrf_802154_received_timestamp_raw(uint8_t * p_data, + int8_t power, + uint8_t lqi, + uint32_t time); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was received at given time + * + * This functions works like @sa nrf_802154_received and adds timestamp to parameter list. + * + * @note @p timestamp may be inacurate due to software latency (IRQ handling). + * @note @p timestamp granularity depends on granularity of the timer driver in platform/timer + * directory. + * @note Including timestamp to received frame uses resources like CPU time and memory. If timestamp + * is not required use @sa nrf_802154_received instead(). + * + * @param[in] p_data Pointer to the buffer containing payload of received frame (PSDU without FCS). + * @param[in] length Length of received payload. + * @param[in] power RSSI of received frame. + * @param[in] lqi LQI of received frame. + * @param[in] time Timestamp taken when last symbol of the frame was received (in us). + */ +extern void nrf_802154_received_timestamp(uint8_t * p_data, + uint8_t length, + int8_t power, + uint8_t lqi, + uint32_t time); + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED + +/** + * @brief Notify that reception of a frame failed. + * + * @param[in] error An error code that indicates reason of the failure. + */ +extern void nrf_802154_receive_failed(nrf_802154_rx_error_t error); + +/** + * @brief Notify that transmitting frame has started. + * + * @note It is possible that transmit procedure is interrupted and + * @sa nrf_802154_transmitted won't be called. + * @note This function should be very short to prevent dropping frames by the driver. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame being transmitted. + */ +extern void nrf_802154_tx_started(const uint8_t * p_frame); + +#if NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was transmitted. + * + * @note If ACK was requested for transmitted frame this function is called after proper ACK is + * received. If ACK was not requested this function is called just after transmission is + * ended. + * @note Buffer pointed by the @p p_ack pointer is not modified by the radio driver (and can't + * be used to receive a frame) until @sa nrf_802154_buffer_free_raw() function is + * called. + * @note Buffer pointed by the @p p_ack pointer may be modified by the function handler (and other + * modules) until @sa nrf_802154_buffer_free_raw() function is called. + * + * @param[in] p_frame Pointer to buffer containing PHR and PSDU of transmitted frame. + * @param[in] p_ack Pointer to received ACK buffer. Fist byte in the buffer is length of the + * frame (PHR) and following bytes are the ACK frame itself (PSDU). Length byte + * (PHR) includes FCS. FCS is already verified by the hardware and may be + * modified by the hardware. + * If ACK was not requested @p p_ack is set to NULL. + * @param[in] power RSSI of received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of received frame or 0 if ACK was not requested. + */ +extern void nrf_802154_transmitted_raw(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + uint8_t lqi); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was transmitted. + * + * @note If ACK was requested for transmitted frame this function is called after proper ACK is + * received. If ACK was not requested this function is called just after transmission is + * ended. + * @note Buffer pointed by the @p p_ack pointer is not modified by the radio driver (and can't + * be used to receive a frame) until @sa nrf_802154_buffer_free() function is + * called. + * @note Buffer pointed by the @p p_ack pointer may be modified by the function handler (and other + * modules) until @sa nrf_802154_buffer_free() function is called. + * @note The next higher layer should handle @sa nrf_802154_transmitted() or + * @sa nrf_802154_transmitted_raw() function. It should not handle both. + * + * @param[in] p_frame Pointer to buffer containing PSDU of transmitted frame. + * @param[in] p_ack Pointer to buffer containing received ACK payload (PHR excluding FCS). + * If ACK was not requested @p p_ack is set to NULL. + * @param[in] length Length of received ACK payload or 0 if ACK was not requested. + * @param[in] power RSSI of received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of received frame or 0 if ACK was not requested. + */ +extern void nrf_802154_transmitted(const uint8_t * p_frame, + uint8_t * p_ack, + uint8_t length, + int8_t power, + uint8_t lqi); + +#endif // !NRF_802154_USE_RAW_API + +#if NRF_802154_FRAME_TIMESTAMP_ENABLED +#if NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was transmitted. + * + * This functions works like @sa nrf_802154_transmitted_raw and adds timestamp to parameter + * list. + * + * @note @p timestamp may be inacurate due to software latency (IRQ handling). + * @note @p timestamp granularity depends on granularity of the timer driver in platform/timer + * directory. + * @note Including timestamp to received frame uses resources like CPU time and memory. If timestamp + * is not required use @sa nrf_802154_received instead. + * + * @param[in] p_frame Pointer to buffer containing PSDU of transmitted frame. + * @param[in] p_ack Pointer to received ACK buffer. Fist byte in the buffer is length of the + * frame (PHR) and following bytes are the ACK frame itself (PSDU). Length byte + * (PHR) includes FCS. FCS is already verified by the hardware and may be + * modified by the hardware. + * If ACK was not requested @p p_ack is set to NULL. + * @param[in] power RSSI of received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of received frame or 0 if ACK was not requested. + * @param[in] time Timestamp taken when received last symbol of ACK or 0 if ACK was not + * requested. + */ +extern void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + uint8_t lqi, + uint32_t time); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notify that frame was transmitted. + * + * This functions works like @sa nrf_802154_transmitted and adds timestamp to parameter + * list. + * + * @note @p timestamp may be inacurate due to software latency (IRQ handling). + * @note @p timestamp granularity depends on granularity of the timer driver in platform/timer + * directory. + * @note Including timestamp to received frame uses resources like CPU time and memory. If timestamp + * is not required use @sa nrf_802154_received instead. + * + * @param[in] p_frame Pointer to buffer containing PSDU of transmitted frame. + * @param[in] p_ack Pointer to buffer containing received ACK payload (PHR excluding FCS). + * If ACK was not requested @p p_ack is set to NULL. + * @param[in] length Length of received ACK payload. + * @param[in] power RSSI of received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of received frame or 0 if ACK was not requested. + * @param[in] time Timestamp taken when received last symbol of ACK or 0 if ACK was not + * requested. + */ +extern void nrf_802154_transmitted_timestamp(const uint8_t * p_frame, + uint8_t * p_ack, + uint8_t length, + int8_t power, + uint8_t lqi, + uint32_t time); + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED + +/** + * @brief Notify that frame was not transmitted due to busy channel. + * + * This function is called if transmission procedure fails. + * + * @param[in] p_frame Pointer to buffer containing PSDU of frame that was not transmitted. + * @param[in] error Reason of the failure. + */ +extern void nrf_802154_transmit_failed(const uint8_t * p_frame, + nrf_802154_tx_error_t error); + +/** + * @brief Notify that Energy Detection procedure finished. + * + * @note This function passes EnergyLevel defined in 802.15.4-2006 specification: + * 0x00 - 0xff proportional to detected energy level (dBm above receiver sensitivity). To + * calculate result in dBm use @sa nrf_802154_dbm_from_energy_level_calculate(). + * + * @param[in] result Maximum energy detected during Energy Detection procedure. + */ +extern void nrf_802154_energy_detected(uint8_t result); + +/** + * @brief Notify that Energy Detection procedure failed. + * + * @param[in] error Reason of the failure. + */ +extern void nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error); + +/** + * @brief Notify that CCA procedure has finished. + * + * @param[in] channel_free Indication if channel is free. + */ +extern void nrf_802154_cca_done(bool channel_free); + +/** + * @brief Notify that CCA procedure failed. + * + * @param[in] error Reason of the failure. + */ +extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error); + + +/*************************************************************************************************** + * @section Driver memory management + **************************************************************************************************/ + +#if NRF_802154_USE_RAW_API + +/** + * @brief Notify driver that buffer containing received frame is not used anymore. + * + * @note The buffer pointed by the @p p_data pointer may be modified by this function. + * + * @param[in] p_data A pointer to the buffer containing received data that is no more needed by + * the higher layer. + */ +void nrf_802154_buffer_free_raw(uint8_t * p_data); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Notify driver that buffer containing received frame is not used anymore. + * + * @note The buffer pointed by the @p p_data pointer may be modified by this function. + * + * @param[in] p_data A pointer to the buffer containing received data that is no more needed by + * the higher layer. + */ +void nrf_802154_buffer_free(uint8_t * p_data); + +#endif // NRF_802154_USE_RAW_API + + +/*************************************************************************************************** + * @section RSSI measurement function. + **************************************************************************************************/ + +/** + * @brief Begin RSSI measurement. + * + * @note This function should be called in Receive state. + * + * Begin RSSI measurement. The result will be available in 8 uS. The result can be read by + * @sa nrf_radio802154_rssi_last_get() function. + */ +void nrf_802154_rssi_measure(void); + +/** + * @brief Get result of last RSSI measurement. + * + * @returns RSSI measurement result [dBm]. + */ +int8_t nrf_802154_rssi_last_get(void); + +/** + * @brief Adjust given RSSI measurement using a temperature correction factor. + * + * @param[in] rssi Measured RSSI value [dBm]. + * @param[in] temp Temperature value when RSSI sample took place [C]. + * + * @returns RSSI [dBm] corrected by a temperature factor (Errata 153). + */ +int8_t nrf_802154_rssi_corrected_get(int8_t rssi, int8_t temp); + + +/*************************************************************************************************** + * @section Promiscuous mode. + **************************************************************************************************/ + +/** + * @brief Enable or disable promiscuous radio mode. + * + * @note Promiscuous mode is disabled by default. + * + * In promiscuous mode driver notifies higher layer that it received any frame (regardless + * frame type or destination address). + * In normal mode (not promiscuous) higher layer is not notified about ACK frames and frames with + * unknown type. Also frames with destination address not matching this device address are ignored. + * + * @param[in] enabled If promiscuous mode should be enabled. + */ +void nrf_802154_promiscuous_set(bool enabled); + +/** + * @brief Check if radio is in promiscuous mode. + * + * @retval True Radio is in promiscuous mode. + * @retval False Radio is not in promiscuous mode. + */ +bool nrf_802154_promiscuous_get(void); + + +/*************************************************************************************************** + * @section Auto ACK management. + **************************************************************************************************/ + +/** + * @brief Enable or disable auto ACK procedure. + * + * @note Auto ACK procedure is enabled by default. + * + * If auto ACK procedure is enabled the driver prepares and sends ACK frames automatically + * aTurnaroundTime (192 us) after proper frame is received. The driver sets sequence number in + * the ACK frame and pending bit according to auto pending bit feature settings. When auto ACK + * procedure is enabled the driver notifies the next higher layer about received frame after ACK + * frame is transmitted. + * If auto ACK procedure is disabled the driver does not transmit ACK frames. It notifies the next + * higher layer about received frame when a frame is received. In this mode the next higher layer + * is responsible for sending ACK frame. ACK frames should be sent using @sa nrf_802154_transmit() + * function. + * + * @param[in] enabled If auto ACK procedure should be enabled. + */ +void nrf_802154_auto_ack_set(bool enabled); + +/** + * @brief Check if auto ACK procedure is enabled. + * + * @retval True Auto ACK procedure is enabled. + * @retval False Auto ACK procedure is disabled. + */ +bool nrf_802154_auto_ack_get(void); + +/** + * @brief Enable or disable setting pending bit in automatically transmitted ACK frames. + * + * @note Setting pending bit in automatically transmitted ACK frames is enabled by default. + * + * Radio driver automatically sends ACK frames in response frames destined to this node with Ack + * Request bit set. Pending bit in ACK frame can be set or cleared regarding data in indirect queue + * destined to ACK destination. + * + * If setting pending bit in ACK frames is disabled, pending bit in every ACK frame is set. + * If setting pending bit in ACK frames is enabled, radio driver checks if there is data + * in indirect queue destined to ACK destination. If there is no such data, pending bit is cleared. + * + * @note It is possible that due to ISR latency, radio driver cannot verify if there is data in + * indirect queue before ACK is sent. In this case pending bit is set. + * + * @param[in] enabled If setting pending bit in ACK frames is enabled. + */ +void nrf_802154_auto_pending_bit_set(bool enabled); + +/** + * @brief Add address of peer node for which there is pending data in the buffer. + * + * @note This function makes a copy of given address. + * + * @param[in] p_addr Array of bytes containing address of the node (little-endian). + * @param[in] extended If given address is Extended MAC Address or Short MAC Address. + * + * @retval True Address successfully added to the list. + * @retval False There is not enough memory to store this address in the list. + */ +bool nrf_802154_pending_bit_for_addr_set(const uint8_t *p_addr, bool extended); + +/** + * @brief Remove address of peer node for which there is no more pending data in the buffer. + * + * @param[in] p_addr Array of bytes containing address of the node (little-endian). + * @param[in] extended If given address is Extended MAC Address or Short MAC Address. + * + * @retval True Address successfully removed from the list. + * @retval False There is no such address in the list. + */ +bool nrf_802154_pending_bit_for_addr_clear(const uint8_t *p_addr, bool extended); + +/** + * @brief Remove all addresses of given type from pending bit list. + * + * @param[in] extended If function should remove all Exnteded MAC Adresses of all Short Addresses. + */ +void nrf_802154_pending_bit_for_addr_reset(bool extended); + +/*************************************************************************************************** + * @section CCA configuration management. + **************************************************************************************************/ + +/** + * @brief Configure radio CCA mode and threshold. + * + * @param[in] p_cca_cfg A pointer to the CCA configuration structure. Only fields relevant to + * selected mode are updated. + */ +void nrf_802154_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg); + +/** + * @brief Get current radio CCA configuration + * + * @param[out] p_cca_cfg A pointer to the structure for current CCA configuration. + */ +void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); + +/*************************************************************************************************** + * @section CSMA-CA procedure. + **************************************************************************************************/ +#if NRF_802154_CSMA_CA_ENABLED +#if NRF_802154_USE_RAW_API + +/** + * @brief Perform CSMA-CA procedure and transmit frame in case of success. + * + * End of CSMA-CA procedure is notified by @sa nrf_802154_transmitted_raw() or + * @sa nrf_802154_transmit_failed() function. + * + * @note The driver may be configured to automatically time out waiting for ACK frame depending on + * @sa NRF_802154_ACK_TIMEOUT_ENABLED configuration option. If automatic ACK timeout is + * disabled, CSMA-CA procedure does not time out waiting for ACK frame in case frame with ACK + * request bit set was transmitted. MAC layer should manage timer to time out waiting for ACK + * frame. This timer may be started by @sa nrf_802154_tx_started() function. When the timer + * expires MAC layer should call @sa nrf_802154_receive() or @sa nrf_802154_sleep() to stop + * waiting for ACK frame. + * @note Before CSMA-CA procedure is used, application should initialize random seed with srand(). + * + * @param[in] p_data Pointer to frame to transmit. @sa nrf_802154_transmit_raw() + */ +void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data); + +#else // NRF_802154_USE_RAW_API + +/** + * @brief Perform CSMA-CA procedure and transmit frame in case of success. + * + * End of CSMA-CA procedure is notified by @sa nrf_802154_transmitted() or + * @sa nrf_802154_transmit_failed() function. + * + * @note The driver may be configured to automatically time out waiting for ACK frame depending on + * @sa NRF_802154_ACK_TIMEOUT_ENABLED configuration option. If automatic ACK timeout is + * disabled, CSMA-CA procedure does not time out waiting for ACK frame in case frame with ACK + * request bit set was transmitted. MAC layer should manage timer to time out waiting for ACK + * frame. This timer may be started by @sa nrf_802154_tx_started() function. When the timer + * expires MAC layer should call @sa nrf_802154_receive() or @sa nrf_802154_sleep() to stop + * waiting for ACK frame. + * @note Before CSMA-CA procedure is used, application should initialize random seed with srand(). + * + * @param[in] p_data Pointer to frame to transmit. @sa nrf_802154_transmit() + * @param[in] length Length of given frame. @sa nrf_802154_transmit() + */ +void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length); + +#endif // NRF_802154_USE_RAW_API +#endif // NRF_802154_CSMA_CA_ENABLED + +/*************************************************************************************************** + * @section ACK timeout procedure. + **************************************************************************************************/ +#if NRF_802154_ACK_TIMEOUT_ENABLED + +/** + * @brief Set timeout time for ACK timeout feature. + * + * Timeout is notified by @sa nrf_802154_transmit_failed() function. + * + * @param[in] time Timeout time in us. Timeout is started at the beginning of frame transmission + * (after transmission of PHR). Default value is defined in nrf_802154_config.h + * @sa NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT . + */ +void nrf_802154_ack_timeout_set(uint32_t time); + +#endif // NRF_802154_ACK_TIMEOUT_ENABLED + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_802154_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.c new file mode 100644 index 000000000..44d6cadaf --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.c @@ -0,0 +1,413 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements procedures to set pending bit in nRF 802.15.4 radio driver. + * + */ + +#include "nrf_802154_ack_pending_bit.h" + +#include +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_const.h" + +#include "hal/nrf_radio.h" + +/// Maximum number of Short Addresses of nodes for which there is pending data in buffer. +#define NUM_PENDING_SHORT_ADDRESSES NRF_802154_PENDING_SHORT_ADDRESSES +/// Maximum number of Extended Addresses of nodes for which there is pending data in buffer. +#define NUM_PENDING_EXTENDED_ADDRESSES NRF_802154_PENDING_EXTENDED_ADDRESSES +/// Value used to mark Short Address as unused. +#define UNUSED_PENDING_SHORT_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff}) +/// Value used to mark Extended Address as unused. +#define UNUSED_PENDING_EXTENDED_ADDRESS ((uint8_t [EXTENDED_ADDRESS_SIZE]) {0}) + +/// If pending bit in ACK frame should be set to valid or default value. +static bool m_setting_pending_bit_enabled; +/// Array of Short Addresses of nodes for which there is pending data in the buffer. +static uint8_t m_pending_short[NUM_PENDING_SHORT_ADDRESSES][SHORT_ADDRESS_SIZE]; +/// Array of Extended Addresses of nodes for which there is pending data in the buffer. +static uint8_t m_pending_extended[NUM_PENDING_EXTENDED_ADDRESSES][EXTENDED_ADDRESS_SIZE]; +/// Current number of Short Addresses of nodes for which there is pending data in the buffer. +static uint8_t m_num_of_pending_short; +/// Current number of Extended Addresses of nodes for which there is pending data in the buffer. +static uint8_t m_num_of_pending_extended; + +/** + * @brief Compare two extended addresses. + * + * @param[in] p_first_addr Pointer to a first address that should be compared. + * @param[in] p_second_addr Pointer to a second address that should be compared. + * + * @retval -1 First address is less than the second address. + * @retval 0 First address is equal to the second address. + * @retval 1 First address is greater than the second address. + */ +static int8_t extended_addr_compare(const uint8_t * p_first_addr, const uint8_t * p_second_addr) +{ + uint64_t first_addr; + uint64_t second_addr; + + // Cast address pointer to uint64_t variables in 2 steps to prevent unaligned access errors. + first_addr = *(uint32_t *)p_first_addr; + first_addr = (first_addr << 32) | (*(uint32_t *)(p_first_addr + sizeof(uint32_t))); + second_addr = *(uint32_t *)p_second_addr; + second_addr = (second_addr << 32) | (*(uint32_t *)(p_second_addr + sizeof(uint32_t))); + + if (first_addr < second_addr) + { + return -1; + } + else if (first_addr > second_addr) + { + return 1; + } + else + { + return 0; + } +} + +/** + * @brief Compare two short addresses. + * + * @param[in] p_first_addr Pointer to a first address that should be compared. + * @param[in] p_second_addr Pointer to a second address that should be compared. + * + * @retval -1 First address is less than the second address. + * @retval 0 First address is equal to the second address. + * @retval 1 First address is greater than the second address. + */ +static int8_t short_addr_compare(const uint8_t * p_first_addr, const uint8_t * p_second_addr) +{ + uint16_t first_addr = *(uint16_t *)(p_first_addr); + uint16_t second_addr = *(uint16_t *)(p_second_addr); + + if (first_addr < second_addr) + { + return -1; + } + else if (first_addr > second_addr) + { + return 1; + } + else + { + return 0; + } +} + +/** + * @brief Compare two addresses. + * + * @param[in] p_first_addr Pointer to a first address that should be compared. + * @param[in] p_second_addr Pointer to a second address that should be compared. + * @param[in] extended Indication if @p p_first_addr and @p p_second_addr are extended or short addresses. + * + * @retval -1 First address is less than the second address. + * @retval 0 First address is equal to the second address. + * @retval 1 First address is greater than the second address. + */ +static int8_t addr_compare(const uint8_t * p_first_addr, const uint8_t * p_second_addr, bool extended) +{ + if (extended) + { + return extended_addr_compare(p_first_addr, p_second_addr); + } + else + { + return short_addr_compare(p_first_addr, p_second_addr); + } +} + +/** + * @brief Perform a binary search for an address in a list of addresses. + * + * @param[in] p_addr Pointer to an address that is searched for. + * @param[in] p_addr_array Pointer to a list of addresses to be searched. + * @param[out] p_location If the address @p p_addr appears in the list, this is its index in the address list. + * Otherwise, it is the index which @p p_addr would have if it was placed in the list + * (ascending order assumed). + * @param[in] extended Indication if @p p_addr is an extended or a short addresses. + * + * @retval true Address @p p_addr is in the list. + * @retval false Address @p p_addr is not in the list. + */ +static bool addr_binary_search(const uint8_t * p_addr, + const uint8_t * p_addr_array, + uint8_t * p_location, + bool extended) +{ + uint8_t addr_array_len = extended ? m_num_of_pending_extended : m_num_of_pending_short; + uint8_t entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE; + int8_t low = 0; + int8_t midpoint = 0; + int8_t high = addr_array_len; + + while (high >= low) + { + midpoint = low + (high - low) / 2; + + if (midpoint >= addr_array_len) + { + break; + } + + switch (addr_compare(p_addr, p_addr_array + entry_size * midpoint, extended)) + { + case -1: + high = midpoint - 1; + break; + + case 0: + *p_location = midpoint; + return true; + + case 1: + low = midpoint + 1; + break; + + default: + break; + } + } + + /* If in the last iteration of the loop the last case was utilized, it means that the midpoint + * found by the algorithm is less than the address to be added. The midpoint should be therefore + * shifted to the next position. As a simplified example, a { 1, 3, 4 } array can be considered. + * Suppose that a number equal to 2 is about to be added to the array. At the beginning of the + * last iteration, midpoint is equal to 1 and low and high are equal to 0. Midpoint is then set + * to 0 and with last case being utilized, low is set to 1. However, midpoint equal to 0 is + * incorrect, as in the last iteration first element of the array proves to be less than the + * element to be added to the array. With the below code, midpoint is then shifted to 1. */ + if (low == midpoint + 1) + { + midpoint++; + } + + *p_location = midpoint; + return false; +} + +/** + * @brief Find an address in a list of addresses. + * + * @param[in] p_addr Pointer to an address that is searched for. + * @param[out] p_location If the address @p p_addr appears in the list, this is its index in the address list. + * Otherwise, it is the index which @p p_addr would have if it was placed in the list + * (ascending order assumed). + * @param[in] extended Indication if @p p_addr is an extended or a short addresses. + * + * @retval true Address @p p_addr is in the list. + * @retval false Address @p p_addr is not in the list. + */ +static bool addr_index_find(const uint8_t * p_addr, + uint8_t * p_location, + bool extended) +{ + if (extended) + { + return addr_binary_search(p_addr, (uint8_t *)m_pending_extended, p_location, extended); + } + else + { + return addr_binary_search(p_addr, (uint8_t *)m_pending_short, p_location, extended); + } +} + +/** + * @brief Add an address to the address list in ascending order. + * + * @param[in] p_addr Pointer to the address to be added. + * @param[in] location Index of the location where @p p_addr should be added. + * @param[in] extended Indication if @p p_addr is an extended or a short addresses. + * + * @retval true Address @p p_addr has been added to the list successfully. + * @retval false Address @p p_addr could not be added to the list. + */ +static bool addr_add(const uint8_t * p_addr, uint8_t location, bool extended) +{ + uint8_t * p_addr_array = extended ? (uint8_t *)m_pending_extended : + (uint8_t *)m_pending_short; + uint8_t max_addr_array_len = extended ? NUM_PENDING_EXTENDED_ADDRESSES : + NUM_PENDING_SHORT_ADDRESSES; + uint8_t * p_addr_array_len = extended ? &m_num_of_pending_extended : &m_num_of_pending_short; + uint8_t entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE; + + if (*p_addr_array_len == max_addr_array_len) + { + return false; + } + + memmove(p_addr_array + entry_size * (location + 1), + p_addr_array + entry_size * (location), + (*p_addr_array_len - location) * entry_size); + + memcpy(p_addr_array + entry_size * location, p_addr, entry_size); + + (*p_addr_array_len)++; + + return true; +} + +/** + * @brief Remove an address from the address list keeping it in ascending order. + * + * @param[in] location Index of the element to be removed from the list. + * @param[in] extended Indication if address to remove is an extended or a short address. + * + * @retval true Address @p p_addr has been removed from the list successfully. + * @retval false Address @p p_addr could not removed from the list. + */ +static bool addr_remove(uint8_t location, bool extended) +{ + uint8_t * p_addr_array = extended ? (uint8_t *)m_pending_extended : + (uint8_t *)m_pending_short; + uint8_t * p_addr_array_len = extended ? &m_num_of_pending_extended : &m_num_of_pending_short; + uint8_t entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE; + + if (*p_addr_array_len == 0) + { + return false; + } + + memmove(p_addr_array + entry_size * location, + p_addr_array + entry_size * (location + 1), + (*p_addr_array_len - location - 1) * entry_size); + + (*p_addr_array_len)--; + + return true; +} + +void nrf_802154_ack_pending_bit_init(void) +{ + m_setting_pending_bit_enabled = true; + m_num_of_pending_extended = 0; + m_num_of_pending_short = 0; +} + +void nrf_802154_ack_pending_bit_set(bool enabled) +{ + m_setting_pending_bit_enabled = enabled; +} + +bool nrf_802154_ack_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended) +{ + uint8_t location = 0; + + if (addr_index_find(p_addr, &location, extended)) + { + return true; + } + else + { + return addr_add(p_addr, location, extended); + } +} + +bool nrf_802154_ack_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended) +{ + uint8_t location = 0; + + if (addr_index_find(p_addr, &location, extended)) + { + return addr_remove(location, extended); + } + else + { + return false; + } +} + +void nrf_802154_ack_pending_bit_for_addr_reset(bool extended) +{ + if (extended) + { + m_num_of_pending_extended = 0; + } + else + { + m_num_of_pending_short = 0; + } +} + +bool nrf_802154_ack_pending_bit_should_be_set(const uint8_t * p_psdu) +{ + const uint8_t * p_src_addr; + uint8_t location; + bool extended; + + // If automatic setting of pending bit in ACK frames is disabled the pending bit is always set. + if (!m_setting_pending_bit_enabled) + { + return true; + } + + switch (p_psdu[DEST_ADDR_TYPE_OFFSET] & DEST_ADDR_TYPE_MASK) + { + case DEST_ADDR_TYPE_SHORT: + p_src_addr = &p_psdu[SRC_ADDR_OFFSET_SHORT_DST]; + break; + + case DEST_ADDR_TYPE_EXTENDED: + p_src_addr = &p_psdu[SRC_ADDR_OFFSET_EXTENDED_DST]; + break; + + default: + return true; + } + + if (0 == (p_psdu[PAN_ID_COMPR_OFFSET] & PAN_ID_COMPR_MASK)) + { + p_src_addr += PAN_ID_SIZE; + } + + switch (p_psdu[SRC_ADDR_TYPE_OFFSET] & SRC_ADDR_TYPE_MASK) + { + case SRC_ADDR_TYPE_SHORT: + extended = false; + break; + + case SRC_ADDR_TYPE_EXTENDED: + extended = true; + break; + + default: + return true; + } + + return addr_index_find(p_src_addr, &location, extended); +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.h similarity index 85% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.h index 38e531d00..459bf558f 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_ack_pending_bit.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,8 +33,8 @@ * */ -#ifndef NRF_DRV_RADIO802154_ACK_PENDING_BIT_H_ -#define NRF_DRV_RADIO802154_ACK_PENDING_BIT_H_ +#ifndef NRF_802154_ACK_PENDING_BIT_H_ +#define NRF_802154_ACK_PENDING_BIT_H_ #include #include @@ -46,14 +46,14 @@ extern "C" { /** * @brief Initialize this module. */ -void nrf_drv_radio802154_ack_pending_bit_init(void); +void nrf_802154_ack_pending_bit_init(void); /** * @brief Enable or disable procedure of setting pending bit in ACK frame. * * @param[in] enabled True if procedure should be enabled, false otherwise. */ -void nrf_drv_radio802154_ack_pending_bit_set(bool enabled); +void nrf_802154_ack_pending_bit_set(bool enabled); /** * @brief Add address to ACK pending bit list. @@ -68,7 +68,7 @@ void nrf_drv_radio802154_ack_pending_bit_set(bool enabled); * @retval true Address successfully added to the list. * @retval false Address was not added to the list (list is full). */ -bool nrf_drv_radio802154_ack_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended); +bool nrf_802154_ack_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended); /** * @brief Remove address from ACK pending bit list. @@ -83,7 +83,7 @@ bool nrf_drv_radio802154_ack_pending_bit_for_addr_set(const uint8_t * p_addr, bo * @retval true Address successfully removed from the list. * @retval false Address was not removed from the list (address is missing in the list). */ -bool nrf_drv_radio802154_ack_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended); +bool nrf_802154_ack_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended); /** * @brief Remove all addresses of given length from ACK pending bit list. @@ -91,7 +91,7 @@ bool nrf_drv_radio802154_ack_pending_bit_for_addr_clear(const uint8_t * p_addr, * @param[in] extended Indication if all extended or all short addresses should be removed from * the list. */ -void nrf_drv_radio802154_ack_pending_bit_for_addr_reset(bool extended); +void nrf_802154_ack_pending_bit_for_addr_reset(bool extended); /** * @brief Check if pending bit should be set in ACK sent in response to given frame. @@ -101,11 +101,11 @@ void nrf_drv_radio802154_ack_pending_bit_for_addr_reset(bool extended); * @retval true Pending bit should be set. * @retval false Pending bit should be cleared. */ -bool nrf_drv_radio802154_ack_pending_bit_should_be_set(const uint8_t * p_psdu); +bool nrf_802154_ack_pending_bit_should_be_set(const uint8_t * p_psdu); #ifdef __cplusplus } #endif -#endif /* NRF_DRV_RADIO802154_ACK_PENDING_BIT_H_ */ +#endif /* NRF_802154_ACK_PENDING_BIT_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_config.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_config.h new file mode 100644 index 000000000..b35fd7b53 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_config.h @@ -0,0 +1,462 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_CONFIG_H__ +#define NRF_802154_CONFIG_H__ + +#ifdef NRF_802154_PROJECT_CONFIG +#include NRF_802154_PROJECT_CONFIG +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_802154_config 802.15.4 driver configuration + * @{ + * @ingroup nrf_802154 + * @brief Configuration of 802.15.4 radio driver for nRF SoC. + */ + +/*************************************************************************************************** + * @section Radio Driver Configuration. + **************************************************************************************************/ + +/** + * @def NRF_802154_CCA_MODE + * + * CCA Mode used by the driver. + * + */ +#ifndef NRF_802154_CCA_MODE_DEFAULT +#define NRF_802154_CCA_MODE_DEFAULT NRF_RADIO_CCA_MODE_ED +#endif + +/** + * @def NRF_802154_CCA_ED_THRESHOLD + * + * Energy Detection Threshold used in CCA procedure. + * + */ +#ifndef NRF_802154_CCA_ED_THRESHOLD_DEFAULT +#define NRF_802154_CCA_ED_THRESHOLD_DEFAULT 0x14 +#endif + +/** + * @def NRF_802154_CCA_CORR_THRESHOLD + * + * Correlator Threshold used in CCA procedure. + * + */ +#ifndef NRF_802154_CCA_CORR_THRESHOLD_DEFAULT +#define NRF_802154_CCA_CORR_THRESHOLD_DEFAULT 0x14 +#endif + +/** + * @def NRF_802154_CCA_CORR_LIMIT + * + * Correlator limit used in CCA procedure. + * + */ +#ifndef NRF_802154_CCA_CORR_LIMIT_DEFAULT +#define NRF_802154_CCA_CORR_LIMIT_DEFAULT 0x02 +#endif + +/** + * @def NRF_802154_INTERNAL_RADIO_IRQ_HANDLING + * + * If the driver should internally handle the RADIO IRQ. + * In case the driver is used in an OS the RADIO IRQ may be handled by the OS and passed to + * the driver @sa nrf_802154_radio_irq_handler(). In this case internal handling should be disabled. + */ + +#ifndef NRF_802154_INTERNAL_RADIO_IRQ_HANDLING + +#if RAAL_SOFTDEVICE +#define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 0 +#else // RAAL_SOFTDEVICE +#define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 1 +#endif // RAAL_SOFTDEVICE + +#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING + +/** + * @def NRF_802154_IRQ_PRIORITY + * + * Interrupt priority for RADIO peripheral. + * It is recommended to keep IRQ priority high (low number) to prevent losing frames due to + * preemption. + * + */ +#ifndef NRF_802154_IRQ_PRIORITY +#define NRF_802154_IRQ_PRIORITY 0 +#endif + +/** + * @def NRF_802154_TIMER_INSTANCE + * + * TIMER instance used by the driver for Ack IFS and by FEM module. + * + */ +#ifndef NRF_802154_TIMER_INSTANCE +#define NRF_802154_TIMER_INSTANCE NRF_TIMER1 +#endif + +/** + * @def NRF_802154_COUNTER_TIMER_INSTANCE + * + * Timer instance used by the driver for detecting when PSDU is being received. + * + * @note This configuration is only used when NRF_RADIO_EVENT_BCMATCH event handling is disabled + * (@sa NRF_802154_DISABLE_BCC_MATCHING). + */ +#ifndef NRF_802154_COUNTER_TIMER_INSTANCE +#define NRF_802154_COUNTER_TIMER_INSTANCE NRF_TIMER2 +#endif + +/** + * @def NRF_802154_SWI_EGU_INSTANCE + * + * SWI EGU instance used by the driver to synchronize PPIs and for requests and notifications if + * SWI is in use. + * + * @note This option is used by core module regardless driver configuration. + * + */ +#ifndef NRF_802154_SWI_EGU_INSTANCE +#define NRF_802154_SWI_EGU_INSTANCE NRF_EGU3 +#endif + +/** + * @def NRF_802154_SWI_IRQ_HANDLER + * + * SWI EGU IRQ handler used by the driver for requests and notifications if SWI is in use. + * + * @note This option is used when the driver uses SWI to process requests and notifications. + * + */ +#ifndef NRF_802154_SWI_IRQ_HANDLER +#define NRF_802154_SWI_IRQ_HANDLER SWI3_EGU3_IRQHandler +#endif + +/** + * @def NRF_802154_SWI_IRQN + * + * SWI EGU IRQ number used by the driver for requests and notifications if SWI is in use. + * + * @note This option is used when the driver uses SWI to process requests and notifications. + * + */ +#ifndef NRF_802154_SWI_IRQN +#define NRF_802154_SWI_IRQN SWI3_EGU3_IRQn +#endif + +/** + * @def NRF_802154_SWI_PRIORITY + * + * Priority of software interrupt used for requests and notifications. + * + */ +#ifndef NRF_802154_SWI_PRIORITY +#define NRF_802154_SWI_PRIORITY 5 +#endif + +/** + * @def NRF_802154_USE_RAW_API + * + * When this flag is set RAW API is available for the MAC layer. It is recommended to use RAW API, + * because it provides more optimized functions. + * + * @note If RAW API is not available for the MAC layer, only less optimized functions performing + * copy are available. + * + */ +#ifndef NRF_802154_USE_RAW_API +#define NRF_802154_USE_RAW_API 1 +#endif + +/** + * @def NRF_802154_PENDING_SHORT_ADDRESSES + * + * Number of slots containing short addresses of nodes for which pending data is stored. + * + */ +#ifndef NRF_802154_PENDING_SHORT_ADDRESSES +#define NRF_802154_PENDING_SHORT_ADDRESSES 10 +#endif + +/** + * @def NRF_802154_PENDING_EXTENDED_ADDRESSES + * + * Number of slots containing extended addresses of nodes for which pending data is stored. + * + */ +#ifndef NRF_802154_PENDING_EXTENDED_ADDRESSES +#define NRF_802154_PENDING_EXTENDED_ADDRESSES 10 +#endif + +/** + * @def NRF_802154_RX_BUFFERS + * + * Number of buffers in receive queue. + * + */ +#ifndef NRF_802154_RX_BUFFERS +#define NRF_802154_RX_BUFFERS 16 +#endif + +/** + * @def NRF_802154_EXCLUDE_BCC_MATCHING + * + * Setting this flag disables NRF_RADIO_EVENT_BCMATCH handling, and therefore address filtering + * during frame reception. With this flag set to 1, address filtering is done after receiving + * a frame, during NRF_RADIO_EVENT_END handling. + * + */ +#ifndef NRF_802154_DISABLE_BCC_MATCHING +#define NRF_802154_DISABLE_BCC_MATCHING 0 +#endif + +/** + * @def NRF_802154_NOTIFY_CRCERROR + * + * With this flag set to 1 CRC errors would be notified to upper layers. This requires interrupt + * handler to be used. + * + */ +#ifndef NRF_802154_NOTIFY_CRCERROR +#define NRF_802154_NOTIFY_CRCERROR 1 +#endif + +/** + * @def NRF_802154_FRAME_TIMESTAMP_ENABLED + * + * If timestamps should be added to received frames. + * Enabling this feature enables @sa nrf_802154_received_timsestamp_raw, + * @sa nrf_802154_received_timestamp, @sa nrf_802154_transmitted_timestamp_raw and + * @sa nrf_802154_transmitted_timestamp functions that add timestamps to received frames. + * + */ +#ifndef NRF_802154_FRAME_TIMESTAMP_ENABLED +#define NRF_802154_FRAME_TIMESTAMP_ENABLED 1 +#endif + +/*************************************************************************************************** + * @section Clock Driver Configuration. + **************************************************************************************************/ + +/** + * @def NRF_802154_CLOCK_IRQ_PRIORITY + * + * Priority of clock interrupt used in standalone clock driver implementation. + * + * @note This configuration is only applicable for Clock Abstraction Layer implementation + * in nrf_802154_clock_nodrv.c. + * + */ +#ifndef NRF_802154_CLOCK_IRQ_PRIORITY +#define NRF_802154_CLOCK_IRQ_PRIORITY 10 +#endif + +/** + * @def NRF_802154_CLOCK_IRQ_PRIORITY + * + * Low frequency clock source used in standalone clock driver implementation. + * + * @note This configuration is only applicable for Clock Abstraction Layer implementation + * in nrf_802154_clock_nodrv.c. + * + */ +#ifndef NRF_802154_CLOCK_LFCLK_SOURCE +#define NRF_802154_CLOCK_LFCLK_SOURCE NRF_CLOCK_LFCLK_Xtal +#endif + +/*************************************************************************************************** + * @section RTC Driver Configuration. + **************************************************************************************************/ + +/** + * @def NRF_802154_RTC_IRQ_PRIORITY + * + * Priority of RTC interrupt used in standalone timer driver implementation. + * + * @note This configuration is only applicable for Timer Abstraction Layer implementation + * in nrf_802154_timer_nodrv.c. + * + */ +#ifndef NRF_802154_RTC_IRQ_PRIORITY +#define NRF_802154_RTC_IRQ_PRIORITY 6 +#endif + +/** + * @def NRF_802154_RTC_INSTANCE + * + * RTC instance used in standalone timer driver implementation. + * + * @note This configuration is only applicable for Timer Abstraction Layer implementation + * in nrf_802154_timer_nodrv.c. + * + */ +#ifndef NRF_802154_RTC_INSTANCE +#define NRF_802154_RTC_INSTANCE NRF_RTC2 +#endif + +/** + * @def NRF_802154_RTC_IRQ_HANDLER + * + * RTC interrupt handler name used in standalone timer driver implementation. + * + * @note This configuration is only applicable for Timer Abstraction Layer implementation + * in nrf_802154_timer_nodrv.c. + * + */ +#ifndef NRF_802154_RTC_IRQ_HANDLER +#define NRF_802154_RTC_IRQ_HANDLER RTC2_IRQHandler +#endif + + +/** + * @def NRF_802154_RTC_IRQN + * + * RTC Interrupt number used in standalone timer driver implementation. + * + * @note This configuration is only applicable for Timer Abstraction Layer implementation + * in nrf_802154_timer_nodrv.c. + * + */ +#ifndef NRF_802154_RTC_IRQN +#define NRF_802154_RTC_IRQN RTC2_IRQn +#endif + + +/*************************************************************************************************** + * @section CSMA/CA procedure configuration. + **************************************************************************************************/ + +/** + * @def NRF_802154_CSMA_CA_ENABLED + * + * If CSMA-CA procedure should be enabled by the driver. Disabling CSMA-CA procedure improves + * driver performance. + * + */ +#ifndef NRF_802154_CSMA_CA_ENABLED +#define NRF_802154_CSMA_CA_ENABLED 1 +#endif + +/** + * @def NRF_802154_CSMA_CA_MIN_BE + * + * The minimum value of the backoff exponent (BE) in the CSMA-CA algorithm. + * (IEEE 802.15.4-2015: 6.2.5.1) + * + */ +#ifndef NRF_802154_CSMA_CA_MIN_BE +#define NRF_802154_CSMA_CA_MIN_BE 3 +#endif + +/** + * @def NRF_802154_CSMA_CA_MAX_BE + * + * The maximum value of the backoff exponent, BE, in the CSMA-CA algorithm. + * (IEEE 802.15.4-2015: 6.2.5.1) + * + */ +#ifndef NRF_802154_CSMA_CA_MAX_BE +#define NRF_802154_CSMA_CA_MAX_BE 5 +#endif + +/** + * @def NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS + * + * The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel + * access failure. + * + */ +#ifndef NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS +#define NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS 4 +#endif + +/*************************************************************************************************** + * @section ACK timeout feature configuration. + **************************************************************************************************/ + +/** + * @def NRF_802154_ACK_TIMEOUT_ENABLED + * + * If ACK timeout feature should be enabled in the driver. + * + */ +#ifndef NRF_802154_ACK_TIMEOUT_ENABLED +#define NRF_802154_ACK_TIMEOUT_ENABLED 1 +#endif + +/** + * @def NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT + * + * Default timeout time in us for ACK timeout feature. + * + */ +#ifndef NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT +#define NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT 7000 +#endif + +/*************************************************************************************************** + * @section Transmission start notification feature configuration. + **************************************************************************************************/ + +/** + * @def NRF_802154_TX_STARTED_NOTIFY_ENABLED + * + * If notification of started transmission should be enabled in the driver. + * + * @note This feature is enabled by default if Ack Timeout feature or CSMA-CA feature is enabled. + * These features depend on notification of transmission start. + */ +#ifndef NRF_802154_TX_STARTED_NOTIFY_ENABLED +#if NRF_802154_ACK_TIMEOUT_ENABLED || NRF_802154_CSMA_CA_ENABLED +#define NRF_802154_TX_STARTED_NOTIFY_ENABLED 1 +#else +#define NRF_802154_TX_STARTED_NOTIFY_ENABLED 0 +#endif +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_802154_CONFIG_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_const.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_const.h similarity index 59% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_const.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_const.h index e51426aaa..bd6d28d86 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_const.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_const.h @@ -33,44 +33,95 @@ * */ -#ifndef NRF_DRV_RADIO802154_CONST_H_ -#define NRF_DRV_RADIO802154_CONST_H_ +#ifndef NRF_802154_CONST_H_ +#define NRF_802154_CONST_H_ -#define ACK_HEADER_WITH_PENDING 0x12 ///< First byte of ACK frame containing pending bit -#define ACK_HEADER_WITHOUT_PENDING 0x02 ///< First byte of ACK frame without pending bit +#include +#include "nrf_802154_config.h" + +#define ACK_HEADER_WITH_PENDING 0x12 ///< First byte of ACK frame containing pending bit +#define ACK_HEADER_WITHOUT_PENDING 0x02 ///< First byte of ACK frame without pending bit -#define ACK_LENGTH 5 ///< Length of ACK frame -#define ACK_REQUEST_BIT (1 << 5) ///< Ack request bit #define ACK_REQUEST_OFFSET 1 ///< Byte containing Ack request bit (+1 for frame length byte) -#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing extended destination address type -#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing destination address type +#define ACK_REQUEST_BIT (1 << 5) ///< Ack request bit + #define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing destination address type (+1 for frame length byte) +#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing destination address type +#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing extended destination address type +#define DEST_ADDR_TYPE_NONE 0x00 ///< Bits containing not present destination address type #define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing short destination address type -#define DEST_ADDR_OFFSET 5 ///< Offset of destination address in Data frame +#define DEST_ADDR_OFFSET 6 ///< Offset of destination address in Data frame (+1 for frame length byte) + #define DSN_OFFSET 3 ///< Byte containing DSN value (+1 for frame length byte) -#define FRAME_PENDING_BIT (1 << 4) ///< Pending bit + #define FRAME_PENDING_OFFSET 1 ///< Byte containing pending bit (+1 for frame length byte) +#define FRAME_PENDING_BIT (1 << 4) ///< Pending bit + +#define FRAME_TYPE_OFFSET 1 ///< Byte containing frame type bits (+1 for frame length byte) +#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing frame type #define FRAME_TYPE_ACK 0x02 ///< Bits containing ACK frame type #define FRAME_TYPE_BEACON 0x00 ///< Bits containing Beacon frame type #define FRAME_TYPE_COMMAND 0x03 ///< Bits containing Command frame type #define FRAME_TYPE_DATA 0x01 ///< Bits containing Data frame type -#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing frame type -#define FRAME_TYPE_OFFSET 1 ///< Byte containing frame type bits (+1 for frame length byte) +#define FRAME_TYPE_EXTENDED 0x07 ///< Bits containing Extended frame type +#define FRAME_TYPE_FRAGMENT 0x06 ///< Bits containing Fragment or Frak frame type +#define FRAME_TYPE_MULTIPURPOSE 0x05 ///< Bits containing Multipurpose frame type + +#define FRAME_VERSION_OFFSET 2 ///< Byte containing frame version bits (+1 for frame length byte) +#define FRAME_VERSION_MASK 0x30 ///< Mask of bits containing frame version +#define FRAME_VERSION_0 0x00 ///< Bits containing frame version 0b00 +#define FRAME_VERSION_1 0x10 ///< Bits containing frame version 0b01 +#define FRAME_VERSION_2 0x20 ///< Bits containing frame version 0b10 +#define FRAME_VERSION_3 0x30 ///< Bits containing frame version 0b11 + #define PAN_ID_COMPR_OFFSET 1 ///< Byte containing Pan Id compression bit (+1 for frame length byte) #define PAN_ID_COMPR_MASK 0x40 ///< Pan Id compression bit -#define PAN_ID_OFFSET 3 ///< Offset of Pan Id in Data frame + +#define PAN_ID_OFFSET 4 ///< Offset of Pan Id in Data frame (+1 for frame length byte) + #define SRC_ADDR_TYPE_EXTENDED 0xc0 ///< Bits containing extended source address type +#define SRC_ADDR_TYPE_NONE 0x00 ///< Bits containing not present source address type #define SRC_ADDR_TYPE_MASK 0xc0 ///< Mask of bits containing source address type #define SRC_ADDR_TYPE_OFFSET 2 ///< Byte containing source address type (+1 for frame length byte) #define SRC_ADDR_TYPE_SHORT 0x80 ///< Bits containing short source address type + #define SRC_ADDR_OFFSET_SHORT_DST 8 ///< Offset of source address in Data frame if destination address is short #define SRC_ADDR_OFFSET_EXTENDED_DST 14 ///< Offset of source address in Data frame if destination address is extended +#define PHR_SIZE 1 ///< Size of PHR field +#define FCF_SIZE 2 ///< Size of FCF field #define PAN_ID_SIZE 2 ///< Size of Pan Id #define SHORT_ADDRESS_SIZE 2 ///< Size of Short Mac Address #define EXTENDED_ADDRESS_SIZE 8 ///< Size of Extended Mac Address #define FCS_SIZE 2 ///< Size of FCS field +#define ACK_LENGTH 5 ///< Length of ACK frame #define MAX_PACKET_SIZE 127 ///< Maximal size of radio packet +#define TURNAROUND_TIME 192UL ///< aTurnaroundTime [us] +#define CCA_TIME 128UL ///< aCcaTime [us] +#define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< aUnitBackoffPeriod [us] + +#define PHY_US_PER_SYMBOL 16 ///< Duration of single symbol in microseconds [us] +#define PHY_SYMBOLS_PER_OCTET 2 ///< Number of symbols in single byte (octet) +#define PHY_SHR_DURATION 10 ///< Number of symbols in Synchronization Header (SHR) + +#define ED_MIN_DBM (-94) ///< dBm value corresponding to value 0 in EDSAMPLE register +#define ED_RESULT_FACTOR 4 ///< Factor needed to calculate ED result based on data from RADIO peripheral +#define ED_RESULT_MAX 0xff ///< Maximal ED result + +#define BROADCAST_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff}) ///< Broadcast Short Address + +typedef enum +{ + REQ_ORIG_HIGHER_LAYER, + REQ_ORIG_CORE, + REQ_ORIG_RAAL, +#if NRF_802154_CSMA_CA_ENABLED + REQ_ORIG_CSMA_CA, +#endif // NRF_802154_CSMA_CA_ENABLED +#if NRF_802154_ACK_TIMEOUT_ENABLED + REQ_ORIG_ACK_TIMEOUT, +#endif // NRF_802154_ACK_TIMEOUT_ENABLED +} req_originator_t; #endif // NRD_DRV_RADIO802154_CONST_H_ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c new file mode 100644 index 000000000..92d9465d3 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c @@ -0,0 +1,2791 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements Finite State Machine of nRF 802.15.4 radio driver. + * + */ + +#include "nrf_802154_core.h" + +#include +#include +#include +#include + +#include "nrf_802154.h" +#include "nrf_802154_ack_pending_bit.h" +#include "nrf_802154_config.h" +#include "nrf_802154_const.h" +#include "nrf_802154_critical_section.h" +#include "nrf_802154_debug.h" +#include "nrf_802154_notification.h" +#include "nrf_802154_pib.h" +#include "nrf_802154_priority_drop.h" +#include "nrf_802154_procedures_duration.h" +#include "nrf_802154_revision.h" +#include "nrf_802154_rx_buffer.h" +#include "nrf_802154_types.h" +#include "fem/nrf_fem_control_api.h" +#include "hal/nrf_egu.h" +#include "hal/nrf_ppi.h" +#include "hal/nrf_radio.h" +#include "hal/nrf_timer.h" +#include "mac_features/nrf_802154_filter.h" + +#include "nrf_802154_core_hooks.h" +#include "raal/nrf_raal_api.h" + + +#define EGU_EVENT NRF_EGU_EVENT_TRIGGERED15 +#define EGU_TASK NRF_EGU_TASK_TRIGGER15 +#define PPI_CH0 NRF_PPI_CHANNEL6 +#define PPI_CH1 NRF_PPI_CHANNEL7 +#define PPI_CH2 NRF_PPI_CHANNEL8 +#define PPI_CH3 NRF_PPI_CHANNEL9 +#define PPI_CH4 NRF_PPI_CHANNEL10 +#define PPI_CH5 NRF_PPI_CHANNEL11 +#define PPI_CH6 NRF_PPI_CHANNEL12 +#define PPI_CHGRP0 NRF_PPI_CHANNEL_GROUP0 ///< PPI group used to disable self-disabling PPIs +#define PPI_CHGRP0_DIS_TASK NRF_PPI_TASK_CHG0_DIS + +#define PPI_DISABLED_EGU PPI_CH0 ///< PPI that connects RADIO DISABLED event with EGU task +#define PPI_EGU_RAMP_UP PPI_CH1 ///< PPI that connects EGU event with RADIO TXEN or RXEN task +#define PPI_EGU_TIMER_START PPI_CH2 ///< PPI that connects EGU event with TIMER START task +#define PPI_CRCERROR_CLEAR PPI_CH3 ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task +#define PPI_CCAIDLE_FEM PPI_CH3 ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM +#define PPI_TIMER_TX_ACK PPI_CH3 ///< PPI that connects TIMER COMPARE event with RADIO TXEN task +#define PPI_CRCOK_DIS_PPI PPI_CH4 ///< PPI that connects RADIO CRCOK event with task that disables PPI group + +#if NRF_802154_DISABLE_BCC_MATCHING +#define PPI_ADDRESS_COUNTER_COUNT PPI_CH5 ///< PPI that connects RADIO ADDRESS event with TIMER COUNT task +#define PPI_CRCERROR_COUNTER_CLEAR PPI_CH6 ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task +#endif // NRF_802154_DISABLE_BCC_MATCHING + +/// Workaround for missing PHYEND event in older chip revision. +static inline uint32_t short_phyend_disable_mask_get(void) +{ + if (nrf_802154_revision_has_phyend_event()) + { + return NRF_RADIO_SHORT_PHYEND_DISABLE_MASK; + } + + return NRF_RADIO_SHORT_END_DISABLE_MASK; +} + +#if NRF_802154_DISABLE_BCC_MATCHING +#define SHORT_ADDRESS_BCSTART 0UL +#else // NRF_802154_DISABLE_BCC_MATCHING +#define SHORT_ADDRESS_BCSTART NRF_RADIO_SHORT_ADDRESS_BCSTART_MASK +#endif // NRF_802154_DISABLE_BCC_MATCHING + +/// Value set to SHORTS register when no shorts should be enabled. +#define SHORTS_IDLE 0 + +/// Value set to SHORTS register for RX operation. +#define SHORTS_RX (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \ + NRF_RADIO_SHORT_END_DISABLE_MASK | \ + SHORT_ADDRESS_BCSTART) + +#define SHORTS_RX_FREE_BUFFER (NRF_RADIO_SHORT_RXREADY_START_MASK) + +#define SHORTS_TX_ACK (NRF_RADIO_SHORT_TXREADY_START_MASK | \ + short_phyend_disable_mask_get()) + +#define SHORTS_CCA_TX (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \ + NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK | \ + NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK | \ + NRF_RADIO_SHORT_TXREADY_START_MASK | \ + short_phyend_disable_mask_get()) + +#define SHORTS_TX (NRF_RADIO_SHORT_TXREADY_START_MASK | \ + short_phyend_disable_mask_get()) + +#define SHORTS_RX_ACK (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \ + NRF_RADIO_SHORT_END_DISABLE_MASK) + +#define SHORTS_ED (NRF_RADIO_SHORT_READY_EDSTART_MASK) + +#define SHORTS_CCA (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \ + NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK) + +/// Delay before first check of received frame: 24 bits is PHY header and MAC Frame Control field. +#define BCC_INIT (3 * 8) + +/// Duration of single iteration of Energy Detection procedure +#define ED_ITER_DURATION 128U +/// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations] +#define ED_ITERS_OVERHEAD 2U + +#define CRC_LENGTH 2 ///< Length of CRC in 802.15.4 frames [bytes] +#define CRC_POLYNOMIAL 0x011021 ///< Polynomial used for CRC calculation in 802.15.4 frames + +#define MHMU_MASK 0xff000700 ///< Mask of known bytes in ACK packet +#define MHMU_PATTERN 0x00000200 ///< Values of known bytes in ACK packet +#define MHMU_PATTERN_DSN_OFFSET 24 ///< Offset of DSN in MHMU_PATTER [bits] + +#define ACK_IFS TURNAROUND_TIME ///< Ack Inter Frame Spacing [us] - delay between last symbol of received frame and first symbol of transmitted Ack +#define TXRU_TIME 40 ///< Transmitter ramp up time [us] +#define EVENT_LAT 23 ///< END event latency [us] + +#define LQI_VALUE_FACTOR 4 ///< Factor needed to calculate LQI value based on data from RADIO peripheral +#define LQI_MAX 0xff ///< Maximal LQI value + + +/** Get LQI of given received packet. If CRC is calculated by hardware LQI is included instead of CRC + * in the frame. Length is stored in byte with index 0; CRC is 2 last bytes. + */ +#define RX_FRAME_LQI(psdu) ((psdu)[(psdu)[0] - 1]) + +#if NRF_802154_RX_BUFFERS > 1 +/// Pointer to currently used receive buffer. +static rx_buffer_t * mp_current_rx_buffer; +#else +/// If there is only one buffer use const pointer to the receive buffer. +static rx_buffer_t * const mp_current_rx_buffer = &nrf_802154_rx_buffers[0]; +#endif + +static uint8_t m_ack_psdu[ACK_LENGTH + 1]; ///< Ack frame buffer. +static const uint8_t * mp_tx_data; ///< Pointer to data to transmit. +static uint32_t m_ed_time_left; ///< Remaining time of current energy detection procedure [us]. +static uint8_t m_ed_result; ///< Result of current energy detection procedure. + +static volatile radio_state_t m_state = RADIO_STATE_SLEEP; ///< State of the radio driver + +typedef struct +{ + bool frame_filtered :1; ///< If frame being received passed filtering operation. + bool rx_timeslot_requested :1; ///< If timeslot for the frame being received is already requested. +#if !NRF_802154_DISABLE_BCC_MATCHING + bool psdu_being_received :1; ///< If PSDU is currently being received. +#endif // !NRF_802154_DISABLE_BCC_MATCHING +} nrf_radio802154_flags_t; +static nrf_radio802154_flags_t m_flags; ///< Flags used to store current driver state. + + +/*************************************************************************************************** + * @section Common core operations + **************************************************************************************************/ + +/** Set driver state. + * + * @param[in] state Driver state to set. + */ +static void state_set(radio_state_t state) +{ + m_state = state; + + nrf_802154_log(EVENT_SET_STATE, (uint32_t)state); +} + +/** Clear flags describing frame being received. */ +static void rx_flags_clear(void) +{ + m_flags.frame_filtered = false; + m_flags.rx_timeslot_requested = false; +#if !NRF_802154_DISABLE_BCC_MATCHING + m_flags.psdu_being_received = false; +#endif // !NRF_802154_DISABLE_BCC_MATCHING +} + +/** Get result of last RSSI measurement. + * + * @returns Result of last RSSI measurement [dBm]. + */ +static int8_t rssi_last_measurement_get(void) +{ + return -((int8_t)nrf_radio_rssi_sample_get()); +} + +/** Get LQI of a received frame. + * + * @param[in] p_data Pointer to buffer containing PHR and PSDU of received frame + * + * @returns LQI of given frame. + */ +static uint8_t lqi_get(const uint8_t * p_data) +{ + uint32_t lqi = RX_FRAME_LQI(p_data); + + lqi *= LQI_VALUE_FACTOR; + + if (lqi > LQI_MAX) + { + lqi = LQI_MAX; + } + + return (uint8_t)lqi; +} + +/** Notify MAC layer that a frame was received. */ +static void received_frame_notify(uint8_t * p_psdu) +{ + nrf_802154_critical_section_nesting_allow(); + + nrf_802154_notify_received(p_psdu, // data + rssi_last_measurement_get(), // rssi + lqi_get(p_psdu)); // lqi + + nrf_802154_critical_section_nesting_deny(); +} + +/** Notify MAC layer that receive procedure failed. */ +static void receive_failed_notify(nrf_802154_rx_error_t error) +{ + nrf_802154_critical_section_nesting_allow(); + + nrf_802154_notify_receive_failed(error); + + nrf_802154_critical_section_nesting_deny(); +} + +/** Notify MAC layer that transmission of requested frame has started. */ +static void transmit_started_notify(void) +{ + if (nrf_802154_core_hooks_tx_started(mp_tx_data)) + { + nrf_802154_tx_started(mp_tx_data); + } + +} + +/** Notify MAC layer that a frame was transmitted. */ +static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, int8_t lqi) +{ + nrf_802154_critical_section_nesting_allow(); + + nrf_802154_core_hooks_transmitted(mp_tx_data); + nrf_802154_notify_transmitted(mp_tx_data, p_ack, power, lqi); + + nrf_802154_critical_section_nesting_deny(); +} + +/** Notify MAC layer that transmission procedure failed. */ +static void transmit_failed_notify(const uint8_t * p_data, nrf_802154_tx_error_t error) +{ + nrf_802154_critical_section_nesting_allow(); + + if (nrf_802154_core_hooks_tx_failed(p_data, error)) + { + nrf_802154_notify_transmit_failed(p_data, error); + } + + nrf_802154_critical_section_nesting_deny(); +} + +/** Notify MAC layer that energy detection procedure ended. */ +static void energy_detected_notify(uint8_t result) +{ + nrf_802154_critical_section_nesting_allow(); + + nrf_802154_notify_energy_detected(result); + + nrf_802154_critical_section_nesting_deny(); +} + +/** Notify MAC layer that CCA procedure ended. */ +static void cca_notify(bool result) +{ + nrf_802154_critical_section_nesting_allow(); + + nrf_802154_notify_cca(result); + + nrf_802154_critical_section_nesting_deny(); +} + +/** Update CCA configuration in RADIO registers. */ +static void cca_configuration_update(void) +{ + nrf_802154_cca_cfg_t cca_cfg; + + nrf_802154_pib_cca_cfg_get(&cca_cfg); + nrf_radio_cca_mode_set(cca_cfg.mode); + nrf_radio_cca_ed_threshold_set(cca_cfg.ed_threshold); + nrf_radio_cca_corr_threshold_set(cca_cfg.corr_threshold); + nrf_radio_cca_corr_counter_set(cca_cfg.corr_limit); +} + +/** Check if PSDU is currently being received. + * + * @returns True if radio is receiving PSDU, false otherwise. + */ +static bool psdu_is_being_received(void) +{ +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, nrf_timer_capture_task_get(NRF_TIMER_CC_CHANNEL0)); + uint32_t counter = nrf_timer_cc_read(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0); + + assert(counter <= 1); + + return counter > 0; +#else // NRF_802154_DISABLE_BCC_MATCHING + return m_flags.psdu_being_received; +#endif // NRF_802154_DISABLE_BCC_MATCHING +} + +/*************************************************************************************************** + * @section RX buffer management + **************************************************************************************************/ + +/** Set currently used rx buffer to given address. + * + * @param[in] p_rx_buffer Pointer to receive buffer that should be used now. + */ +static void rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer) +{ +#if NRF_802154_RX_BUFFERS > 1 + mp_current_rx_buffer = p_rx_buffer; +#else + (void) p_rx_buffer; +#endif +} + +/** Check if currently there is available rx buffer. + * + * @retval true There is available rx buffer. + * @retval false Currently there is no available rx buffer. + */ +static bool rx_buffer_is_available(void) +{ + return (mp_current_rx_buffer != NULL) && (mp_current_rx_buffer->free); +} + +/** Get pointer to available rx buffer. + * + * @returns Pointer to available rx buffer or NULL if rx buffer is not available. + */ +static uint8_t * rx_buffer_get(void) +{ + return rx_buffer_is_available() ? mp_current_rx_buffer->psdu : NULL; +} + +/*************************************************************************************************** + * @section Radio parameters calculators + **************************************************************************************************/ + +/** Set radio channel + * + * @param[in] channel Channel number to set (11-26). + */ +static void channel_set(uint8_t channel) +{ + assert(channel >= 11 && channel <= 26); + + nrf_radio_frequency_set(5 + (5 * (channel - 11))); +} + +/*************************************************************************************************** + * @section ACK transmission management + **************************************************************************************************/ + +/// Set valid sequence number in ACK frame. +static void ack_prepare(void) +{ + // Copy sequence number from received frame to ACK frame. + m_ack_psdu[DSN_OFFSET] = mp_current_rx_buffer->psdu[DSN_OFFSET]; +} + +/// Set pending bit in ACK frame. +static void ack_pending_bit_set(void) +{ + m_ack_psdu[FRAME_PENDING_OFFSET] = ACK_HEADER_WITH_PENDING; + + if (!nrf_802154_ack_pending_bit_should_be_set(mp_current_rx_buffer->psdu)) + { + m_ack_psdu[FRAME_PENDING_OFFSET] = ACK_HEADER_WITHOUT_PENDING; + } +} + +/** Check if ACK is requested in given frame. + * + * @param[in] p_frame Pointer to a frame to check. + * + * @retval true ACK is requested in given frame. + * @retval false ACK is not requested in given frame. + */ +static bool ack_is_requested(const uint8_t * p_frame) +{ + return (p_frame[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT) ? true : false; +} + +/*************************************************************************************************** + * @section ACK receiving management + **************************************************************************************************/ + +/** Enable hardware ACK matching accelerator. */ +static void ack_matching_enable(void) +{ + nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH); + nrf_radio_mhmu_search_pattern_set(MHMU_PATTERN | + ((uint32_t) mp_tx_data[DSN_OFFSET] << + MHMU_PATTERN_DSN_OFFSET)); +} + +/** Disable hardware ACK matching accelerator. */ +static void ack_matching_disable(void) +{ + nrf_radio_mhmu_search_pattern_set(0); + nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH); +} + +/** Check if hardware ACK matching accelerator matched ACK pattern in received frame. + * + * @retval true ACK matching accelerator matched ACK pattern. + * @retval false ACK matching accelerator did not match ACK pattern. + */ +static bool ack_is_matched(void) +{ + return (nrf_radio_event_get(NRF_RADIO_EVENT_MHRMATCH)) && + (nrf_radio_crc_status_get() == NRF_RADIO_CRC_STATUS_OK); +} + +/*************************************************************************************************** + * @section RADIO peripheral management + **************************************************************************************************/ + +/** Initialize radio peripheral. */ +static void nrf_radio_init(void) +{ + nrf_radio_mode_set(NRF_RADIO_MODE_IEEE802154_250KBIT); + nrf_radio_config_length_field_length_set(8); + nrf_radio_config_preamble_length_set(NRF_RADIO_PREAMBLE_LENGTH_32BIT_ZERO); + nrf_radio_config_crc_included_set(true); + nrf_radio_config_max_length_set(MAX_PACKET_SIZE); + nrf_radio_ramp_up_mode_set(NRF_RADIO_RAMP_UP_MODE_FAST); + + // Configure CRC + nrf_radio_crc_length_set(CRC_LENGTH); + nrf_radio_crc_includes_address_set(NRF_RADIO_CRC_INCLUDES_ADDR_IEEE802154); + nrf_radio_crc_polynominal_set(CRC_POLYNOMIAL); + + // Configure CCA + cca_configuration_update(); + + // Configure MAC Header Match Unit + nrf_radio_mhmu_search_pattern_set(0); + nrf_radio_mhmu_pattern_mask_set(MHMU_MASK); + + // Set channel + channel_set(nrf_802154_pib_channel_get()); +} + +/** Reset radio peripheral. */ +static void nrf_radio_reset(void) +{ + nrf_radio_power_set(false); + nrf_radio_power_set(true); + + nrf_802154_log(EVENT_RADIO_RESET, 0); +} + +/** Initialize interrupts for radio peripheral. */ +static void irq_init(void) +{ + NVIC_SetPriority(RADIO_IRQn, NRF_802154_IRQ_PRIORITY); + NVIC_ClearPendingIRQ(RADIO_IRQn); + NVIC_EnableIRQ(RADIO_IRQn); +} + +/** Deinitialize interrupts for radio peripheral. */ +static void irq_deinit(void) +{ + NVIC_DisableIRQ(RADIO_IRQn); + NVIC_ClearPendingIRQ(RADIO_IRQn); + NVIC_SetPriority(RADIO_IRQn, 0); + + __DSB(); + __ISB(); +} + + +/*************************************************************************************************** + * @section TIMER peripheral management + **************************************************************************************************/ + +/** Initialize TIMER peripheral used by the driver. */ +static void nrf_timer_init(void) +{ + nrf_timer_mode_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_MODE_TIMER); + nrf_timer_bit_width_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_BIT_WIDTH_16); + nrf_timer_frequency_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_FREQ_1MHz); + +#if NRF_802154_DISABLE_BCC_MATCHING + // Setup timer for detecting PSDU reception. + nrf_timer_mode_set(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_MODE_COUNTER); + nrf_timer_bit_width_set(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_BIT_WIDTH_8); +#endif +} + +/*************************************************************************************************** + * @section Energy detection management + **************************************************************************************************/ + +/** Get ED result value. + * + * @returns ED result based on data collected during Energy Detection procedure. + */ +static uint8_t ed_result_get(void) +{ + uint32_t result = m_ed_result; + + result *= ED_RESULT_FACTOR; + + if (result > ED_RESULT_MAX) + { + result = ED_RESULT_MAX; + } + + return (uint8_t)result; +} + +/** Setup next iteration of energy detection procedure. + * + * Energy detection procedure is performed in iterations to make sure it is performed for requested + * time regardless radio arbitration. + * + * @param[in] Remaining time of energy detection procedure [us]. + * + * @retval true Next iteration of energy detection procedure will be performed now. + * @retval false Next iteration of energy detection procedure will not be performed now due to + * ending timeslot. + */ +static bool ed_iter_setup(uint32_t time_us) +{ + uint32_t us_left_in_timeslot = nrf_raal_timeslot_us_left_get(); + uint32_t next_ed_iters = us_left_in_timeslot / ED_ITER_DURATION; + + if (next_ed_iters > ED_ITERS_OVERHEAD) + { + next_ed_iters -= ED_ITERS_OVERHEAD; + + if ((time_us / ED_ITER_DURATION) < next_ed_iters) + { + m_ed_time_left = 0; + next_ed_iters = time_us / ED_ITER_DURATION; + } + else + { + m_ed_time_left = time_us - (next_ed_iters * ED_ITER_DURATION); + next_ed_iters--; // Time of ED procedure is (next_ed_iters + 1) * 128us + } + + nrf_radio_ed_loop_count_set(next_ed_iters); + + return true; + } + else + { + if (nrf_raal_timeslot_is_granted()) + { + irq_deinit(); + nrf_radio_reset(); + } + + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN); + nrf_fem_control_pin_clear(); + + m_ed_time_left = time_us; + + return false; + } +} + + +/*************************************************************************************************** + * @section FSM transition request sub-procedures + **************************************************************************************************/ + +/** Wait time needed to propagate event through PPI to EGU. + * + * During detection if trigger of DISABLED event caused start of hardware procedure, detecting + * function needs to wait until event is propagated from RADIO through PPI to EGU. This delay is + * required to make sure EGU event is set if hardware was prepared before DISABLED event was + * triggered. + */ +static inline void ppi_and_egu_delay_wait(void) +{ + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); +} + +/** Detect if PPI starting EGU for current operation worked. + * + * @retval true PPI worked. + * @retval false PPI did not work. DISABLED task should be triggered. + */ +static bool ppi_egu_worked(void) +{ + // Detect if PPIs were set before DISABLED event was notified. If not trigger DISABLE + if (nrf_radio_state_get() != NRF_RADIO_STATE_DISABLED) + { + // If RADIO state is not DISABLED, it means that RADIO is still ramping down or already + // started ramping up. + return true; + } + + // Wait for PPIs + ppi_and_egu_delay_wait(); + + if (nrf_egu_event_check(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT)) + { + // If EGU event is set, procedure is running. + return true; + } + else + { + return false; + } +} + +/** Set PPIs to connect DISABLED->EGU->RAMP_UP + * + * @param[in] ramp_up_task Task triggered to start ramp up procedure. + * @param[in] self_disabling If PPI should disable itself. + */ +static void ppis_for_egu_and_ramp_up_set(nrf_radio_task_t ramp_up_task, bool self_disabling) +{ + if (self_disabling) + { + nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_radio_task_address_get(ramp_up_task), + (uint32_t)nrf_ppi_task_address_get( + PPI_CHGRP0_DIS_TASK)); + } + else + { + nrf_ppi_channel_endpoint_setup(PPI_EGU_RAMP_UP, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_radio_task_address_get(ramp_up_task)); + } + + nrf_ppi_channel_endpoint_setup(PPI_DISABLED_EGU, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED), + (uint32_t)nrf_egu_task_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_TASK)); + + if (self_disabling) + { + nrf_ppi_channel_include_in_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + } + + nrf_ppi_channel_enable(PPI_EGU_RAMP_UP); + nrf_ppi_channel_enable(PPI_DISABLED_EGU); +} + +/** Configure FEM to set LNA at appropriate time. */ +static void fem_for_lna_set(nrf_timer_cc_channel_t cc_channel, + nrf_timer_short_mask_t short_mask) +{ + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, cc_channel); + nrf_fem_control_timer_set(NRF_FEM_CONTROL_LNA_PIN, cc_channel, short_mask); + nrf_fem_control_ppi_task_setup(NRF_FEM_CONTROL_LNA_PIN, + PPI_EGU_TIMER_START, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_START)); +} + +/** Reset FEM configuration for LNA. + * + * @param[in] timer_short_mask Mask of shorts that should be disabled on FEM timer. + */ +static void fem_for_lna_reset(nrf_timer_short_mask_t timer_short_mask) +{ + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN); + nrf_fem_control_timer_reset(NRF_FEM_CONTROL_LNA_PIN, timer_short_mask); + nrf_ppi_channel_disable(PPI_EGU_TIMER_START); +} + +/** Configure FEM to set PA at appropriate time. */ +static void fem_for_pa_set(void) +{ + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_CC_CHANNEL2); + nrf_fem_control_timer_set(NRF_FEM_CONTROL_PA_PIN, + NRF_TIMER_CC_CHANNEL2, + NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + nrf_fem_control_ppi_fork_setup(NRF_FEM_CONTROL_PA_PIN, + PPI_EGU_RAMP_UP, + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_START)); +} + +/** Reset FEM configuration for PA. */ +static void fem_for_pa_reset(void) +{ + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_PA_PIN); + nrf_fem_control_timer_reset(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + nrf_fem_control_ppi_fork_clear(NRF_FEM_CONTROL_PA_PIN, PPI_EGU_RAMP_UP); +} + +/** Configure FEM for TX procedure. */ +static void fem_for_tx_set(bool cca) +{ + if (cca) + { + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, NRF_TIMER_CC_CHANNEL0); + nrf_fem_control_timer_set(NRF_FEM_CONTROL_LNA_PIN, + NRF_TIMER_CC_CHANNEL0, + NRF_TIMER_SHORT_COMPARE0_STOP_MASK); + nrf_fem_control_ppi_pin_task_setup(PPI_CCAIDLE_FEM, + (uint32_t)nrf_radio_event_address_get( + NRF_RADIO_EVENT_CCAIDLE), + false, + true); + } + else + { + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_CC_CHANNEL1); + nrf_fem_control_timer_set(NRF_FEM_CONTROL_PA_PIN, + NRF_TIMER_CC_CHANNEL1, + NRF_TIMER_SHORT_COMPARE1_STOP_MASK); + } + + nrf_fem_control_ppi_task_setup(NRF_FEM_CONTROL_ANY_PIN, + PPI_EGU_TIMER_START, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_START)); +} + +/** Reset FEM for TX procedure. */ +static void fem_for_tx_reset(bool disable_ppi_egu_timer_start) +{ + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_ANY_PIN); + nrf_fem_control_timer_reset(NRF_FEM_CONTROL_ANY_PIN, NRF_TIMER_SHORT_COMPARE0_STOP_MASK | NRF_TIMER_SHORT_COMPARE1_STOP_MASK); + nrf_fem_control_ppi_fork_clear(NRF_FEM_CONTROL_ANY_PIN, PPI_CCAIDLE_FEM); + nrf_ppi_channel_disable(PPI_CCAIDLE_FEM); + + if (disable_ppi_egu_timer_start) + { + nrf_ppi_channel_disable(PPI_EGU_TIMER_START); + } +} + +/** Restart RX procedure after frame was received (and no ACK transmitted). */ +static void rx_restart(bool set_shorts) +{ + // Disable PPIs on DISABLED event to control TIMER. + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + + if (set_shorts) + { + nrf_radio_shorts_set(SHORTS_RX); + } + + // Restart TIMER. + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + // Enable self-disabled PPI or PPI disabled by CRCOK + nrf_ppi_channel_enable(PPI_EGU_RAMP_UP); + + rx_flags_clear(); +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); + nrf_radio_bcc_set(BCC_INIT); +#endif // !NRF_802154_DISABLE_BCC_MATCHING + + // Enable PPIs on DISABLED event and clear event to detect if PPI worked + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + nrf_ppi_channel_enable(PPI_DISABLED_EGU); + + if (!ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate Falling Asleep procedure. */ +static void falling_asleep_terminate(void) +{ + if (nrf_raal_timeslot_is_granted()) + { + nrf_radio_int_disable(NRF_RADIO_INT_DISABLED_MASK); + } +} + +/** Terminate RX procedure. */ +static void rx_terminate(void) +{ + uint32_t ints_to_disable = 0; + + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + nrf_ppi_channel_disable(PPI_EGU_TIMER_START); +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_disable(PPI_CRCERROR_CLEAR); + nrf_ppi_channel_disable(PPI_CRCOK_DIS_PPI); + nrf_ppi_channel_disable(PPI_ADDRESS_COUNTER_COUNT); + nrf_ppi_channel_disable(PPI_CRCERROR_COUNTER_CLEAR); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN); + + nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_fork_endpoint_setup(PPI_EGU_TIMER_START, 0); +#else // NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK | NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + nrf_timer_shorts_disable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + if (nrf_raal_timeslot_is_granted()) + { +#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + ints_to_disable |= NRF_RADIO_INT_CRCERROR_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR +#if !NRF_802154_DISABLE_BCC_MATCHING + ints_to_disable |= NRF_RADIO_INT_BCMATCH_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING + ints_to_disable |= NRF_RADIO_INT_CRCOK_MASK; + nrf_radio_int_disable(ints_to_disable); + nrf_radio_shorts_set(SHORTS_IDLE); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate TX ACK procedure. */ +static void tx_ack_terminate(void) +{ + uint32_t ints_to_disable = 0; + + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + nrf_ppi_channel_disable(PPI_EGU_TIMER_START); +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_disable(PPI_CRCERROR_CLEAR); + nrf_ppi_channel_disable(PPI_CRCOK_DIS_PPI); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_PA_PIN); + + nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); +#endif // !NRF_802154_DISABLE_BCC_MATCHING + + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK | NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + nrf_timer_shorts_disable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + if (nrf_raal_timeslot_is_granted()) + { + ints_to_disable = nrf_802154_revision_has_phyend_event() ? + NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK; +#if NRF_802154_TX_STARTED_NOTIFY_ENABLED + ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK; +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + + nrf_radio_int_disable(ints_to_disable); + nrf_radio_shorts_set(SHORTS_IDLE); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate TX procedure. */ +static void tx_terminate(void) +{ + uint32_t ints_to_disable; + + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + + fem_for_tx_reset(true); + + nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); + + if (nrf_raal_timeslot_is_granted()) + { + ints_to_disable = nrf_802154_revision_has_phyend_event() ? + NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK; + ints_to_disable |= NRF_RADIO_INT_CCABUSY_MASK; +#if NRF_802154_TX_STARTED_NOTIFY_ENABLED + ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK; +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + + nrf_radio_int_disable(ints_to_disable); + nrf_radio_shorts_set(SHORTS_IDLE); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate RX ACK procedure. */ +static void rx_ack_terminate(void) +{ + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + + fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + + nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); + + if (nrf_raal_timeslot_is_granted()) + { + nrf_radio_int_disable(NRF_RADIO_INT_END_MASK); + nrf_radio_shorts_set(SHORTS_IDLE); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + + ack_matching_disable(); + } +} + +/** Terminate ED procedure. */ +static void ed_terminate(void) +{ + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + + fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE0_STOP_MASK); + + nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); + + if (nrf_raal_timeslot_is_granted()) + { + nrf_radio_int_disable(NRF_RADIO_INT_EDEND_MASK); + nrf_radio_shorts_set(SHORTS_IDLE); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate CCA procedure. */ +static void cca_terminate(void) +{ + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + + fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE0_STOP_MASK); + + nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); + + if (nrf_raal_timeslot_is_granted()) + { + nrf_radio_int_disable(NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK); + nrf_radio_shorts_set(SHORTS_IDLE); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate Continuous Carrier procedure. */ +static void continuous_carrier_terminate(void) +{ + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + nrf_ppi_channel_disable(PPI_EGU_RAMP_UP); + + fem_for_pa_reset(); + + if (nrf_raal_timeslot_is_granted()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Terminate ongoing operation. + * + * This function is called when MAC layer requests transition to another operation. + * + * After calling this function RADIO should enter DISABLED state and RAAL should be in continuous + * mode. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates termination request. + * @param[in] notify_abort If Termination of current operation shall be notified. + * + * @retval true Terminated ongoing operation. + * @retval false Ongoing operation was not terminated. + */ +static bool current_operation_terminate(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + bool notify_abort) +{ + bool result = nrf_802154_core_hooks_terminate(term_lvl, req_orig); + + if (result) + { + switch (m_state) + { + case RADIO_STATE_SLEEP: + if (req_orig != REQ_ORIG_RAAL) + { + // Enter continuous mode unless terminating current operation is requested by + // RAAL during timeslot end procedure. + nrf_raal_continuous_mode_enter(); + } + + break; + + case RADIO_STATE_FALLING_ASLEEP: + falling_asleep_terminate(); + break; + + case RADIO_STATE_RX: + if (psdu_is_being_received()) + { + if (term_lvl >= NRF_802154_TERM_802154) + { + rx_terminate(); + + if (notify_abort) + { + nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_ABORTED); + } + } + else + { + result = false; + } + } + else + { + rx_terminate(); + } + + break; + + case RADIO_STATE_TX_ACK: + if (term_lvl >= NRF_802154_TERM_802154) + { + tx_ack_terminate(); + } + else + { + result = false; + } + + break; + + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + if (term_lvl >= NRF_802154_TERM_802154) + { + tx_terminate(); + + if (notify_abort) + { + nrf_802154_notify_transmit_failed(mp_tx_data, NRF_802154_TX_ERROR_ABORTED); + } + } + else + { + result = false; + } + + break; + + case RADIO_STATE_RX_ACK: + if (term_lvl >= NRF_802154_TERM_802154) + { + rx_ack_terminate(); + + if (notify_abort) + { + nrf_802154_notify_transmit_failed(mp_tx_data, NRF_802154_TX_ERROR_ABORTED); + } + } + else + { + result = false; + } + + break; + + case RADIO_STATE_ED: + if (term_lvl >= NRF_802154_TERM_802154) + { + ed_terminate(); + + if (notify_abort) + { + nrf_802154_notify_energy_detection_failed(NRF_802154_ED_ERROR_ABORTED); + } + } + else + { + result = false; + } + + break; + + case RADIO_STATE_CCA: + if (term_lvl >= NRF_802154_TERM_802154) + { + cca_terminate(); + + if (notify_abort) + { + nrf_802154_notify_cca_failed(NRF_802154_CCA_ERROR_ABORTED); + } + } + else + { + result = false; + } + break; + + case RADIO_STATE_CONTINUOUS_CARRIER: + continuous_carrier_terminate(); + break; + + default: + assert(false); + } + } + + return result; +} + +/** Enter Sleep state. */ +static void sleep_init(void) +{ + nrf_802154_priority_drop_timeslot_exit(); +} + +/** Initialize Falling Asleep operation. */ +static void falling_asleep_init(void) +{ + if (!nrf_raal_timeslot_is_granted()) + { + state_set(RADIO_STATE_SLEEP); + sleep_init(); + return; + } + + nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); + nrf_radio_int_enable(NRF_RADIO_INT_DISABLED_MASK); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED) + { + // Radio is already disabled. Enter sleep state directly. + falling_asleep_terminate(); + state_set(RADIO_STATE_SLEEP); + sleep_init(); + } +} + +/** Initialize RX operation. */ +static void rx_init(bool disabled_was_triggered) +{ + bool free_buffer; + int32_t ints_to_enable = 0; + uint32_t lna_target_time; + uint32_t pa_target_time; + + if (!nrf_raal_timeslot_is_granted()) + { + return; + } + + // Clear filtering flag + rx_flags_clear(); + + nrf_radio_tx_power_set(nrf_802154_pib_tx_power_get()); + + // Find available RX buffer + free_buffer = rx_buffer_is_available(); + + if (free_buffer) + { + nrf_radio_packet_ptr_set(rx_buffer_get()); + } + + // Set shorts + nrf_radio_shorts_set(free_buffer ? (SHORTS_RX | SHORTS_RX_FREE_BUFFER) : (SHORTS_RX)); + + // Set BCC +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_bcc_set(BCC_INIT); +#endif // !NRF_802154_DISABLE_BCC_MATCHING + + // Enable IRQs +#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + nrf_radio_event_clear(NRF_RADIO_EVENT_CRCERROR); + ints_to_enable |= NRF_RADIO_INT_CRCERROR_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING ||NRF_802154_NOTIFY_CRCERROR +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); + ints_to_enable |= NRF_RADIO_INT_BCMATCH_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_event_clear(NRF_RADIO_EVENT_CRCOK); + ints_to_enable |= NRF_RADIO_INT_CRCOK_MASK; + nrf_radio_int_enable(ints_to_enable); + + // Set FEM + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, NRF_TIMER_CC_CHANNEL0); + lna_target_time = nrf_fem_control_delay_get(NRF_FEM_CONTROL_LNA_PIN); + pa_target_time = nrf_fem_control_delay_get(NRF_FEM_CONTROL_PA_PIN); + + // Set TIMER to transmit ACK + nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE, + NRF_TIMER_SHORT_COMPARE0_STOP_MASK | + NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0, lna_target_time); + nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE, + NRF_TIMER_CC_CHANNEL1, + lna_target_time + ACK_IFS - TXRU_TIME - EVENT_LAT); + nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE, + NRF_TIMER_CC_CHANNEL2, + lna_target_time + ACK_IFS - TXRU_TIME - EVENT_LAT + pa_target_time); + +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_timer_shorts_enable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK); + nrf_timer_cc_write(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL1, 1); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + // Clr event EGU + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + + // Set PPIs +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_endpoint_setup(PPI_EGU_RAMP_UP, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_radio_task_address_get(NRF_RADIO_TASK_RXEN)); + nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_TIMER_START, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_START), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_COUNTER_TIMER_INSTANCE, + NRF_TIMER_TASK_START)); + nrf_ppi_channel_endpoint_setup(PPI_CRCERROR_CLEAR, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCERROR), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_CLEAR)); + nrf_ppi_channel_endpoint_setup(PPI_CRCOK_DIS_PPI, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK), + (uint32_t)nrf_ppi_task_address_get(PPI_CHGRP0_DIS_TASK)); +#else // NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_radio_task_address_get( + NRF_RADIO_TASK_RXEN), + (uint32_t)nrf_ppi_task_address_get( + PPI_CHGRP0_DIS_TASK)); + nrf_ppi_channel_endpoint_setup(PPI_EGU_TIMER_START, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_START)); +#endif // NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_include_in_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); + + nrf_ppi_channel_endpoint_setup(PPI_DISABLED_EGU, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED), + (uint32_t)nrf_egu_task_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_TASK)); +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_endpoint_setup(PPI_ADDRESS_COUNTER_COUNT, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_ADDRESS), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_COUNTER_TIMER_INSTANCE, + NRF_TIMER_TASK_COUNT)); + nrf_ppi_channel_endpoint_setup(PPI_CRCERROR_COUNTER_CLEAR, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCERROR), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_COUNTER_TIMER_INSTANCE, + NRF_TIMER_TASK_CLEAR)); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + nrf_ppi_channel_enable(PPI_EGU_RAMP_UP); + nrf_ppi_channel_enable(PPI_EGU_TIMER_START); +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_enable(PPI_CRCERROR_CLEAR); + nrf_ppi_channel_enable(PPI_CRCOK_DIS_PPI); + nrf_ppi_channel_enable(PPI_ADDRESS_COUNTER_COUNT); + nrf_ppi_channel_enable(PPI_CRCERROR_COUNTER_CLEAR); +#endif // NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_enable(PPI_DISABLED_EGU); + + // Start procedure if necessary + if (!disabled_was_triggered || !ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } + + // Find RX buffer if none available + if (!free_buffer) + { + rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find()); + + if (rx_buffer_is_available()) + { + nrf_radio_packet_ptr_set(rx_buffer_get()); + nrf_radio_shorts_set(SHORTS_RX | SHORTS_RX_FREE_BUFFER); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + } + } +} + +/** Initialize TX operation. */ +static bool tx_init(const uint8_t * p_data, bool cca, bool disabled_was_triggered) +{ + uint32_t ints_to_enable = 0; + + if (!nrf_raal_timeslot_request( + nrf_802154_tx_duration_get(p_data[0], cca, ack_is_requested(p_data)))) + { + return false; + } + + nrf_radio_tx_power_set(nrf_802154_pib_tx_power_get()); + nrf_radio_packet_ptr_set(p_data); + + // Set shorts + nrf_radio_shorts_set(cca ? SHORTS_CCA_TX : SHORTS_TX); + + // Enable IRQs + if (nrf_802154_revision_has_phyend_event()) + { + nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); + ints_to_enable |= NRF_RADIO_INT_PHYEND_MASK; + } + else + { + nrf_radio_event_clear(NRF_RADIO_EVENT_END); + ints_to_enable |= NRF_RADIO_INT_END_MASK; + } + + if (cca) + { + nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY); + ints_to_enable |= NRF_RADIO_INT_CCABUSY_MASK; + } + +#if NRF_802154_TX_STARTED_NOTIFY_ENABLED + nrf_radio_event_clear(NRF_RADIO_EVENT_ADDRESS); + ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK; +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + + nrf_radio_int_enable(ints_to_enable); + + // Set FEM + fem_for_tx_set(cca); + + // Clr event EGU + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + + // Set PPIs + ppis_for_egu_and_ramp_up_set(cca ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN, true); + + if (!disabled_was_triggered || !ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } + + return true; +} + +/** Initialize ED operation */ +static void ed_init(bool disabled_was_triggered) +{ + if (!ed_iter_setup(m_ed_time_left)) + { + // Just wait for next timeslot if there is not enough time in this one. + return; + } + + // Set shorts + nrf_radio_shorts_set(SHORTS_ED); + + // Enable IRQs + nrf_radio_event_clear(NRF_RADIO_EVENT_EDEND); + nrf_radio_int_enable(NRF_RADIO_INT_EDEND_MASK); + + // Set FEM + fem_for_lna_set(NRF_TIMER_CC_CHANNEL0, NRF_TIMER_SHORT_COMPARE0_STOP_MASK); + + // Clr event EGU + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + + // Set PPIs + ppis_for_egu_and_ramp_up_set(NRF_RADIO_TASK_RXEN, true); + + if (!disabled_was_triggered || !ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Initialize CCA operation. */ +static void cca_init(bool disabled_was_triggered) +{ + if (!nrf_raal_timeslot_request(nrf_802154_cca_duration_get())) + { + return; + } + + // Set shorts + nrf_radio_shorts_set(SHORTS_CCA); + + // Enable IRQs + nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY); + nrf_radio_event_clear(NRF_RADIO_EVENT_CCAIDLE); + nrf_radio_int_enable(NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK); + + // Set FEM + fem_for_lna_set(NRF_TIMER_CC_CHANNEL0, NRF_TIMER_SHORT_COMPARE0_STOP_MASK); + + // Clr event EGU + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + + // Set PPIs + ppis_for_egu_and_ramp_up_set(NRF_RADIO_TASK_RXEN, true); + + if (!disabled_was_triggered || !ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + +/** Initialize Continuous Carrier operation. */ +static void continuous_carrier_init(bool disabled_was_triggered) +{ + if (!nrf_raal_timeslot_is_granted()) + { + return; + } + + // Set FEM + fem_for_pa_set(); + + // Clr event EGU + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + + // Set PPIs + ppis_for_egu_and_ramp_up_set(NRF_RADIO_TASK_TXEN, false); + + if (!disabled_was_triggered || !ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } +} + + +/*************************************************************************************************** + * @section RAAL notification handlers + **************************************************************************************************/ + +void nrf_raal_timeslot_started(void) +{ + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TIMESLOT_STARTED); + + // Prevent interrupting of this handler by requests from higher priority code. + nrf_802154_critical_section_forcefully_enter(); + + nrf_radio_reset(); + nrf_radio_init(); + irq_init(); + + assert(nrf_radio_shorts_get() == SHORTS_IDLE); + + switch (m_state) + { + case RADIO_STATE_RX: + rx_init(false); + break; + + case RADIO_STATE_CCA_TX: + (void)tx_init(mp_tx_data, true, false); + break; + + case RADIO_STATE_TX: + (void)tx_init(mp_tx_data, false, false); + break; + + case RADIO_STATE_ED: + ed_init(false); + break; + + case RADIO_STATE_CCA: + cca_init(false); + break; + + case RADIO_STATE_CONTINUOUS_CARRIER: + continuous_carrier_init(false); + break; + + case RADIO_STATE_SLEEP: + // This case may happen when sleep is requested by the next higher layer right before + // timeslot starts and the driver uses SWI for requests and notifications. In this case + // RAAL may report timeslot start event when exiting sleep request critical section. + // The driver is already in SLEEP state but did not request timeslot end yet - it will + // be requested in the next SWI handler. + break; + + default: + assert(false); + } + + nrf_802154_critical_section_exit(); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_TIMESLOT_STARTED); +} + +void nrf_raal_timeslot_ended(void) +{ + bool result; + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TIMESLOT_ENDED); + + // Prevent interrupting of this handler by requests from higher priority code. + nrf_802154_critical_section_forcefully_enter(); + + irq_deinit(); + nrf_radio_reset(); + nrf_fem_control_pin_clear(); + + result = current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_RAAL, false); + assert(result); + + switch (m_state) + { + case RADIO_STATE_SLEEP: + // Intentionally empty. + break; + + case RADIO_STATE_FALLING_ASLEEP: + state_set(RADIO_STATE_SLEEP); + sleep_init(); + break; + + case RADIO_STATE_RX: + if (psdu_is_being_received()) + { + receive_failed_notify(NRF_802154_RX_ERROR_TIMESLOT_ENDED); + } + + break; + + case RADIO_STATE_TX_ACK: + state_set(RADIO_STATE_RX); + receive_failed_notify(NRF_802154_RX_ERROR_TIMESLOT_ENDED); + break; + + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + case RADIO_STATE_RX_ACK: + state_set(RADIO_STATE_RX); + transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_TIMESLOT_ENDED); + break; + + case RADIO_STATE_ED: + case RADIO_STATE_CCA: + case RADIO_STATE_CONTINUOUS_CARRIER: + // Intentionally empty. + break; + + default: + assert(false); + } + + nrf_802154_critical_section_exit(); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_TIMESLOT_ENDED); +} + + +/*************************************************************************************************** + * @section RADIO interrupt handler + **************************************************************************************************/ + +static void irq_address_state_tx_frame(void) +{ + transmit_started_notify(); +} + +static void irq_address_state_tx_ack(void) +{ + nrf_802154_tx_ack_started(); +} + +#if !NRF_802154_DISABLE_BCC_MATCHING +/// This event is generated during frame reception to request RAAL timeslot and to filter frame +static void irq_bcmatch_state_rx(void) +{ + uint8_t prev_num_psdu_bytes; + uint8_t num_psdu_bytes; + nrf_802154_rx_error_t filter_result; + + num_psdu_bytes = nrf_radio_bcc_get() / 8; + prev_num_psdu_bytes = num_psdu_bytes; + + // If CRCERROR event is set, it means that events are handled out of order due to software + // latency. Just skip this handler in this case - frame will be dropped. + if (nrf_radio_event_get(NRF_RADIO_EVENT_CRCERROR)) + { + return; + } + + if (!m_flags.rx_timeslot_requested) + { + assert(num_psdu_bytes >= PHR_SIZE + FCF_SIZE); + + if (nrf_raal_timeslot_request(nrf_802154_rx_duration_get( + mp_current_rx_buffer->psdu[0], + ack_is_requested(mp_current_rx_buffer->psdu)))) + { + m_flags.rx_timeslot_requested = true; + } + else + { + irq_deinit(); + nrf_radio_reset(); + + nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_TIMESLOT_ENDED); + + return; + } + } + + if (!m_flags.frame_filtered) + { + m_flags.psdu_being_received = true; + filter_result = nrf_802154_filter_frame_part(mp_current_rx_buffer->psdu, &num_psdu_bytes); + + if (filter_result == NRF_802154_RX_ERROR_NONE) + { + if (num_psdu_bytes != prev_num_psdu_bytes) + { + nrf_radio_bcc_set(num_psdu_bytes * 8); + } + else + { + m_flags.frame_filtered = true; + } + } + else if (!nrf_802154_pib_promiscuous_get()) + { + rx_terminate(); + rx_init(true); + + if ((mp_current_rx_buffer->psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != + FRAME_TYPE_ACK) + { + receive_failed_notify(filter_result); + } + } + else + { + // Promiscuous mode, allow incorrect frames. Nothing to do here. + } + } +} +#endif //!NRF_802154_DISABLE_BCC_MATCHING + +#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR +static void irq_crcerror_state_rx(void) +{ +#if !NRF_802154_DISABLE_BCC_MATCHING + rx_restart(false); +#endif //!NRF_802154_DISABLE_BCC_MATCHING +#if NRF_802154_NOTIFY_CRCERROR + receive_failed_notify(NRF_802154_RX_ERROR_INVALID_FCS); +#endif //NRF_802154_NOTIFY_CRCERROR +} +#endif //!NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + +static void irq_crcok_state_rx(void) +{ + uint8_t * p_received_psdu = mp_current_rx_buffer->psdu; + uint32_t ints_to_disable = 0; + uint32_t ints_to_enable = 0; +#if NRF_802154_DISABLE_BCC_MATCHING + uint8_t num_psdu_bytes = PHR_SIZE + FCF_SIZE; + uint8_t prev_num_psdu_bytes = 0; + nrf_802154_rx_error_t filter_result; + + // Frame filtering + while (num_psdu_bytes != prev_num_psdu_bytes) + { + prev_num_psdu_bytes = num_psdu_bytes; + + // Keep checking consecutive parts of the frame header. + filter_result = nrf_802154_filter_frame_part(mp_current_rx_buffer->psdu, &num_psdu_bytes); + + if (filter_result == NRF_802154_RX_ERROR_NONE) + { + if (num_psdu_bytes == prev_num_psdu_bytes) + { + m_flags.frame_filtered = true; + } + } + else + { + break; + } + } + + // Timeslot request + if (m_flags.frame_filtered && + ack_is_requested(p_received_psdu) && + !nrf_raal_timeslot_request(nrf_802154_rx_duration_get(0, true))) + { + // Frame is destined to this node but there is no timeslot to transmit ACK + irq_deinit(); + nrf_radio_reset(); + + rx_flags_clear(); + + // Filter out received ACK frame if promiscuous mode is disabled. + if (((p_received_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) || + nrf_802154_pib_promiscuous_get()) + { + mp_current_rx_buffer->free = false; + received_frame_notify(p_received_psdu); + } + + return; + } +#endif // NRF_802154_DISABLE_BCC_MATCHING + + if (m_flags.frame_filtered || nrf_802154_pib_promiscuous_get()) + { + if (m_flags.frame_filtered && + ack_is_requested(mp_current_rx_buffer->psdu) && + nrf_802154_pib_auto_ack_get()) + { + bool wait_for_phyend; + + // Prepare ACK + ack_prepare(); + nrf_radio_packet_ptr_set(m_ack_psdu); + + // Set shorts + nrf_radio_shorts_set(SHORTS_TX_ACK); + + // Clear TXREADY event to detect if PPI worked + nrf_radio_event_clear(NRF_RADIO_EVENT_TXREADY); + +#if NRF_802154_DISABLE_BCC_MATCHING + // Disable PPIs for PSDU detection + nrf_ppi_fork_endpoint_setup(PPI_EGU_TIMER_START, 0); + nrf_ppi_channel_disable(PPI_ADDRESS_COUNTER_COUNT); + nrf_ppi_channel_disable(PPI_CRCERROR_COUNTER_CLEAR); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + // Set PPIs + nrf_ppi_channel_endpoint_setup(PPI_TIMER_TX_ACK, + (uint32_t)nrf_timer_event_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_EVENT_COMPARE1), + (uint32_t)nrf_radio_task_address_get( + NRF_RADIO_TASK_TXEN)); + +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_enable(PPI_TIMER_TX_ACK); +#endif // !NRF_802154_DISABLE_BCC_MATCHING + + // Set FEM PPIs + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN); + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_CC_CHANNEL2); + + // Detect if PPI worked (timer is counting or TIMER event is marked) + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CAPTURE3); + if (nrf_timer_cc_read(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL3) < + nrf_timer_cc_read(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL1)) + { + wait_for_phyend = true; + } + else + { + ppi_and_egu_delay_wait(); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_TX_RU) + { + wait_for_phyend = true; + } + else if (nrf_radio_event_get(NRF_RADIO_EVENT_TXREADY)) + { + wait_for_phyend = true; + } + else + { + wait_for_phyend = false; + } + } + + if (wait_for_phyend) + { + ack_pending_bit_set(); + state_set(RADIO_STATE_TX_ACK); + + // Set event handlers +#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + ints_to_disable |= NRF_RADIO_INT_CRCERROR_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR +#if !NRF_802154_DISABLE_BCC_MATCHING + ints_to_disable |= NRF_RADIO_INT_BCMATCH_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING + ints_to_disable |= NRF_RADIO_INT_CRCOK_MASK; + nrf_radio_int_disable(ints_to_disable); + + if (nrf_802154_revision_has_phyend_event()) + { + nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); + ints_to_enable = NRF_RADIO_INT_PHYEND_MASK; + } + else + { + nrf_radio_event_clear(NRF_RADIO_EVENT_END); + ints_to_enable = NRF_RADIO_INT_END_MASK; + } + +#if NRF_802154_TX_STARTED_NOTIFY_ENABLED + nrf_radio_event_clear(NRF_RADIO_EVENT_ADDRESS); + ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK; +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + + nrf_radio_int_enable(ints_to_enable); + } + else + { + mp_current_rx_buffer->free = false; + +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_disable(PPI_TIMER_TX_ACK); +#endif // !NRF_802154_DISABLE_BCC_MATCHING + + // RX uses the same peripherals as TX_ACK until RADIO ints are updated. + rx_terminate(); + rx_init(true); + + received_frame_notify(p_received_psdu); + } + } + else + { + rx_restart(true); + + // Filter out received ACK frame if promiscuous mode is disabled. + if (((p_received_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) || + nrf_802154_pib_promiscuous_get()) + { + // Find new RX buffer + mp_current_rx_buffer->free = false; + rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find()); + + if (rx_buffer_is_available()) + { + nrf_radio_packet_ptr_set(rx_buffer_get()); + nrf_radio_shorts_set(SHORTS_RX | SHORTS_RX_FREE_BUFFER); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + } + + received_frame_notify(p_received_psdu); + } + else + { + nrf_radio_shorts_set(SHORTS_RX | SHORTS_RX_FREE_BUFFER); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + } + } + } + else + { + // CRC is OK, but filtering operation did not end - it is invalid frame with valid CRC + // or problem due to software latency (i.e. handled BCMATCH, CRCERROR, CRCOK from two + // consecutively received frames). + rx_terminate(); + rx_init(true); + +#if NRF_802154_DISABLE_BCC_MATCHING + if ((p_received_psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) + { + receive_failed_notify(filter_result); + } +#else // NRF_802154_DISABLE_BCC_MATCHING + receive_failed_notify(NRF_802154_RX_ERROR_RUNTIME); +#endif // NRF_802154_DISABLE_BCC_MATCHING + } +} + +static void irq_phyend_state_tx_ack(void) +{ + uint8_t * p_received_psdu = mp_current_rx_buffer->psdu; + uint32_t ints_to_enable = 0; + uint32_t ints_to_disable = 0; + + // Disable PPIs on DISABLED event to control TIMER. + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + + // Set FEM PPIs + nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_PA_PIN); + nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, NRF_TIMER_CC_CHANNEL0); + + nrf_radio_shorts_set(SHORTS_RX); + + // Set BCC for next reception +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_bcc_set(BCC_INIT); +#endif // !NRF_802154_DISABLE_BCC_MATCHING + + ints_to_disable = nrf_802154_revision_has_phyend_event() ? + NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK; + +#if NRF_802154_TX_STARTED_NOTIFY_ENABLED + ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK; +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + + nrf_radio_int_disable(ints_to_disable); + +#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + nrf_radio_event_clear(NRF_RADIO_EVENT_CRCERROR); + ints_to_enable |= NRF_RADIO_INT_CRCERROR_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING ||NRF_802154_NOTIFY_CRCERROR +#if !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); + ints_to_enable |= NRF_RADIO_INT_BCMATCH_MASK; +#endif // !NRF_802154_DISABLE_BCC_MATCHING + nrf_radio_event_clear(NRF_RADIO_EVENT_CRCOK); + ints_to_enable |= NRF_RADIO_INT_CRCOK_MASK; + nrf_radio_int_enable(ints_to_enable); + + // Restart TIMER. + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + + // Reset PPI for RX mode +#if PPI_TIMER_TX_ACK != PPI_CRCERROR_CLEAR +#error Invalid PPI configuration +#endif + nrf_ppi_channel_endpoint_setup(PPI_CRCERROR_CLEAR, + (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCERROR), + (uint32_t)nrf_timer_task_address_get( + NRF_802154_TIMER_INSTANCE, + NRF_TIMER_TASK_CLEAR)); + + nrf_ppi_fork_endpoint_setup(PPI_EGU_TIMER_START, + (uint32_t)nrf_timer_task_address_get( + NRF_802154_COUNTER_TIMER_INSTANCE, + NRF_TIMER_TASK_START)); +#else // NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_disable(PPI_TIMER_TX_ACK); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + // Enable PPI disabled by CRCOK + nrf_ppi_channel_enable(PPI_EGU_RAMP_UP); +#if NRF_802154_DISABLE_BCC_MATCHING + nrf_ppi_channel_enable(PPI_ADDRESS_COUNTER_COUNT); + nrf_ppi_channel_enable(PPI_CRCERROR_COUNTER_CLEAR); +#endif // NRF_802154_DISABLE_BCC_MATCHING + + // Enable PPIs on DISABLED event and clear event to detect if PPI worked + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + nrf_ppi_channel_enable(PPI_DISABLED_EGU); + + if (!ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } + + // Find new RX buffer + mp_current_rx_buffer->free = false; + rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find()); + + if (rx_buffer_is_available()) + { + nrf_radio_packet_ptr_set(rx_buffer_get()); + nrf_radio_shorts_set(SHORTS_RX | SHORTS_RX_FREE_BUFFER); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + } + + state_set(RADIO_STATE_RX); + + rx_flags_clear(); + + received_frame_notify(p_received_psdu); +} + +static void irq_phyend_state_tx_frame(void) +{ + uint32_t ints_to_disable = 0; + + if (ack_is_requested(mp_tx_data)) + { + bool rx_buffer_free = rx_buffer_is_available(); + uint32_t shorts = rx_buffer_free ? + (SHORTS_RX_ACK | SHORTS_RX_FREE_BUFFER) : SHORTS_RX_ACK; + + // Disable EGU PPI to prevent unsynchronized PPIs + nrf_ppi_channel_disable(PPI_DISABLED_EGU); + + nrf_radio_shorts_set(shorts); + + if (rx_buffer_free) + { + nrf_radio_packet_ptr_set(rx_buffer_get()); + } + + ints_to_disable = NRF_RADIO_INT_CCABUSY_MASK; +#if NRF_802154_TX_STARTED_NOTIFY_ENABLED + ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK; +#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED + nrf_radio_int_disable(ints_to_disable); + + if (nrf_802154_revision_has_phyend_event()) + { + nrf_radio_int_disable(NRF_RADIO_INT_PHYEND_MASK); + nrf_radio_event_clear(NRF_RADIO_EVENT_END); + nrf_radio_int_enable(NRF_RADIO_INT_END_MASK); + } + + // Clear FEM configuration set at the beginning of the transmission + fem_for_tx_reset(false); + // Set PPIs necessary in rx_ack state + fem_for_lna_set(NRF_TIMER_CC_CHANNEL2, NRF_TIMER_SHORT_COMPARE2_STOP_MASK); + + nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP, + (uint32_t)nrf_egu_event_address_get( + NRF_802154_SWI_EGU_INSTANCE, + EGU_EVENT), + (uint32_t)nrf_radio_task_address_get( + NRF_RADIO_TASK_RXEN), + (uint32_t)nrf_ppi_task_address_get( + PPI_CHGRP0_DIS_TASK)); + + nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT); + + // Enable PPI disabled by DISABLED event + nrf_ppi_channel_enable(PPI_EGU_RAMP_UP); + + // Enable EGU PPI to start all PPIs synchronously + nrf_ppi_channel_enable(PPI_DISABLED_EGU); + + state_set(RADIO_STATE_RX_ACK); + + if (!ppi_egu_worked()) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } + + if (!rx_buffer_free) + { + rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find()); + + if (rx_buffer_is_available()) + { + nrf_radio_packet_ptr_set(rx_buffer_get()); + nrf_radio_shorts_set(SHORTS_RX_ACK | SHORTS_RX_FREE_BUFFER); + + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + } + } + + ack_matching_enable(); + } + else + { + tx_terminate(); + state_set(RADIO_STATE_RX); + rx_init(true); + + transmitted_frame_notify(NULL, 0, 0); + } +} + +static void irq_end_state_rx_ack(void) +{ + bool ack_match = ack_is_matched(); + rx_buffer_t * p_ack_buffer = NULL; + + if (ack_match) + { + p_ack_buffer = mp_current_rx_buffer; + mp_current_rx_buffer->free = false; + } + + rx_ack_terminate(); + state_set(RADIO_STATE_RX); + rx_init(true); + + if (ack_match) + { + transmitted_frame_notify(p_ack_buffer->psdu, // psdu + rssi_last_measurement_get(), // rssi + lqi_get(p_ack_buffer->psdu)); // lqi; + } + else + { + transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_INVALID_ACK); + } +} + +static void irq_disabled_state_falling_asleep(void) +{ + falling_asleep_terminate(); + state_set(RADIO_STATE_SLEEP); + sleep_init(); +} + +/// This event is generated when CCA reports idle channel during stand-alone procedure. +static void irq_ccaidle_state_cca(void) +{ + cca_terminate(); + state_set(RADIO_STATE_RX); + rx_init(true); + + cca_notify(true); +} + +static void irq_ccabusy_state_tx_frame(void) +{ + tx_terminate(); + state_set(RADIO_STATE_RX); + rx_init(true); + + transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_BUSY_CHANNEL); +} + +static void irq_ccabusy_state_cca(void) +{ + cca_terminate(); + state_set(RADIO_STATE_RX); + rx_init(true); + + cca_notify(false); +} + +/// This event is generated when energy detection procedure ends. +static void irq_edend_state_ed(void) +{ + uint32_t result = nrf_radio_ed_sample_get(); + m_ed_result = result > m_ed_result ? result : m_ed_result; + + if (m_ed_time_left) + { + if (ed_iter_setup(m_ed_time_left)) + { + nrf_radio_task_trigger(NRF_RADIO_TASK_EDSTART); + } + else + { + fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE0_STOP_MASK); + } + } + else + { + // In case channel change was requested during energy detection procedure. + channel_set(nrf_802154_pib_channel_get()); + + ed_terminate(); + state_set(RADIO_STATE_RX); + rx_init(true); + + energy_detected_notify(ed_result_get()); + } +} + +/// Handler of radio interrupts. +static void irq_handler(void) +{ + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_IRQ_HANDLER); + + // Prevent interrupting of this handler by requests from higher priority code. + nrf_802154_critical_section_forcefully_enter(); + + if (nrf_radio_int_get(NRF_RADIO_INT_ADDRESS_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_ADDRESS)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_FRAMESTART); + nrf_radio_event_clear(NRF_RADIO_EVENT_ADDRESS); + + switch (m_state) + { + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + irq_address_state_tx_frame(); + break; + + case RADIO_STATE_TX_ACK: + irq_address_state_tx_ack(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_FRAMESTART); + } + +#if !NRF_802154_DISABLE_BCC_MATCHING + // Check MAC frame header. + if (nrf_radio_int_get(NRF_RADIO_INT_BCMATCH_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_BCMATCH)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_BCMATCH); + nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); + + switch (m_state) + { + case RADIO_STATE_RX: + irq_bcmatch_state_rx(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_BCMATCH); + } + +#endif // !NRF_802154_DISABLE_BCC_MATCHING + +#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + if (nrf_radio_int_get(NRF_RADIO_INT_CRCERROR_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_CRCERROR)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_CRCERROR); + nrf_radio_event_clear(NRF_RADIO_EVENT_CRCERROR); + + switch (m_state) + { + case RADIO_STATE_RX: + irq_crcerror_state_rx(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CRCERROR); + } +#endif // !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR + + if (nrf_radio_int_get(NRF_RADIO_INT_CRCOK_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_CRCOK)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_CRCOK); + nrf_radio_event_clear(NRF_RADIO_EVENT_CRCOK); + + switch (m_state) + { + case RADIO_STATE_RX: + irq_crcok_state_rx(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CRCOK); + } + + if (nrf_802154_revision_has_phyend_event() && + nrf_radio_int_get(NRF_RADIO_INT_PHYEND_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_PHYEND)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_PHYEND); + nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); + + switch (m_state) + { + case RADIO_STATE_TX_ACK: + irq_phyend_state_tx_ack(); + break; + + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + irq_phyend_state_tx_frame(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_PHYEND); + } + + if (nrf_radio_int_get(NRF_RADIO_INT_END_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_END)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_END); + nrf_radio_event_clear(NRF_RADIO_EVENT_END); + + switch (m_state) + { + case RADIO_STATE_TX_ACK: + if (!nrf_802154_revision_has_phyend_event()) + { + irq_phyend_state_tx_ack(); + } + + break; + + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + if (!nrf_802154_revision_has_phyend_event()) + { + irq_phyend_state_tx_frame(); + } + + break; + + case RADIO_STATE_RX_ACK: // Ended receiving of ACK. + irq_end_state_rx_ack(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_END); + } + + if (nrf_radio_int_get(NRF_RADIO_INT_DISABLED_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_DISABLED)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_DISABLED); + nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); + + switch (m_state) + { + case RADIO_STATE_FALLING_ASLEEP: + irq_disabled_state_falling_asleep(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_DISABLED); + } + + if (nrf_radio_int_get(NRF_RADIO_INT_CCAIDLE_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_CCAIDLE)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_CCAIDLE); + nrf_radio_event_clear(NRF_RADIO_EVENT_CCAIDLE); + + switch (m_state) + { + case RADIO_STATE_CCA: + irq_ccaidle_state_cca(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CCAIDLE); + } + + if (nrf_radio_int_get(NRF_RADIO_INT_CCABUSY_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_CCABUSY)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_CCABUSY); + nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY); + + switch (m_state) + { + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + irq_ccabusy_state_tx_frame(); + break; + + case RADIO_STATE_CCA: + irq_ccabusy_state_cca(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CCABUSY); + } + + if (nrf_radio_int_get(NRF_RADIO_INT_EDEND_MASK) && + nrf_radio_event_get(NRF_RADIO_EVENT_EDEND)) + { + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_EDEND); + nrf_radio_event_clear(NRF_RADIO_EVENT_EDEND); + + switch (m_state) + { + case RADIO_STATE_ED: + irq_edend_state_ed(); + break; + + default: + assert(false); + } + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_EDEND); + } + + nrf_802154_critical_section_exit(); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_IRQ_HANDLER); +} + + +/*************************************************************************************************** + * @section API functions + **************************************************************************************************/ + +void nrf_802154_core_init(void) +{ + const uint8_t ack_psdu[] = {0x05, ACK_HEADER_WITH_PENDING, 0x00, 0x00, 0x00, 0x00}; + memcpy(m_ack_psdu, ack_psdu, sizeof(ack_psdu)); + + nrf_timer_init(); +} + +void nrf_802154_core_deinit(void) +{ + current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_HIGHER_LAYER, true); + + if (nrf_raal_timeslot_is_granted()) + { + nrf_radio_reset(); + } + + nrf_fem_control_pin_clear(); + nrf_fem_control_deactivate(); + + irq_deinit(); +} + +radio_state_t nrf_802154_core_state_get(void) +{ + return m_state; +} + +bool nrf_802154_core_sleep(nrf_802154_term_t term_lvl) +{ + bool result = true; + + if ((m_state != RADIO_STATE_SLEEP) && (m_state != RADIO_STATE_FALLING_ASLEEP)) + { + result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true); + + if (result) + { + state_set(RADIO_STATE_FALLING_ASLEEP); + falling_asleep_init(); + } + } + + return result; +} + +bool nrf_802154_core_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function) +{ + bool result = true; + + if ((m_state != RADIO_STATE_RX) && (m_state != RADIO_STATE_TX_ACK)) + { + result = current_operation_terminate(term_lvl, req_orig, notify_function == NULL); + + if (result) + { + state_set(RADIO_STATE_RX); + rx_init(true); + } + + if (notify_function != NULL) + { + notify_function(result); + } + } + + return result; +} + +bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function) +{ + bool result = current_operation_terminate(term_lvl, req_orig, notify_function == NULL); + + if (result) + { + // Set state to RX in case sleep terminate succeeded, but transmit_begin fails. + state_set(RADIO_STATE_RX); + + mp_tx_data = p_data; + result = tx_init(p_data, cca, true); + } + + if (result) + { + state_set(cca ? RADIO_STATE_CCA_TX : RADIO_STATE_TX); + } + + if (notify_function != NULL) + { + notify_function(result); + } + + return result; +} + +bool nrf_802154_core_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us) +{ + bool result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true); + + if (result) + { + state_set(RADIO_STATE_ED); + m_ed_time_left = time_us; + m_ed_result = 0; + ed_init(true); + } + + return result; +} + +bool nrf_802154_core_cca(nrf_802154_term_t term_lvl) +{ + bool result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true); + + if (result) + { + state_set(RADIO_STATE_CCA); + cca_init(true); + } + + return result; +} + +bool nrf_802154_core_continuous_carrier(nrf_802154_term_t term_lvl) +{ + bool result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true); + + if (result) + { + state_set(RADIO_STATE_CONTINUOUS_CARRIER); + continuous_carrier_init(true); + } + + return result; +} + +bool nrf_802154_core_notify_buffer_free(uint8_t * p_data) +{ + rx_buffer_t * p_buffer = (rx_buffer_t *)p_data; + + p_buffer->free = true; + + if (!nrf_raal_timeslot_is_granted()) + { + return true; + } + + switch (m_state) + { + case RADIO_STATE_RX: + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + assert(nrf_radio_shorts_get() == SHORTS_RX); + + rx_buffer_in_use_set(p_buffer); + + nrf_radio_packet_ptr_set(rx_buffer_get()); + nrf_radio_shorts_set(SHORTS_RX | SHORTS_RX_FREE_BUFFER); + + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + + break; + + case RADIO_STATE_RX_ACK: + if (nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE) + { + assert(nrf_radio_shorts_get() == SHORTS_RX_ACK); + + rx_buffer_in_use_set(p_buffer); + + nrf_radio_packet_ptr_set(rx_buffer_get()); + nrf_radio_shorts_set(SHORTS_RX_ACK | SHORTS_RX_FREE_BUFFER); + + nrf_radio_task_trigger(NRF_RADIO_TASK_START); + } + + break; + + default: + // Don't perform any action in any other state (receiver should not be started). + break; + } + + return true; +} + +bool nrf_802154_core_channel_update(void) +{ + switch (m_state) + { + case RADIO_STATE_RX: + { + bool result; + + if (nrf_raal_timeslot_is_granted()) + { + channel_set(nrf_802154_pib_channel_get()); + } + + result = current_operation_terminate(NRF_802154_TERM_NONE, REQ_ORIG_CORE, true); + + if (result) + { + rx_init(true); + } + + break; + } + + case RADIO_STATE_CONTINUOUS_CARRIER: + if (nrf_raal_timeslot_is_granted()) + { + channel_set(nrf_802154_pib_channel_get()); + nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); + } + + break; + + case RADIO_STATE_TX_ACK: + case RADIO_STATE_CCA_TX: + case RADIO_STATE_TX: + case RADIO_STATE_RX_ACK: + case RADIO_STATE_CCA: + if (nrf_raal_timeslot_is_granted()) + { + channel_set(nrf_802154_pib_channel_get()); + } + + break; + + case RADIO_STATE_SLEEP: + case RADIO_STATE_FALLING_ASLEEP: + case RADIO_STATE_ED: + // Don't perform any action in these states (channel will be updated on state change). + break; + } + + return true; +} + +bool nrf_802154_core_cca_cfg_update(void) +{ + if (nrf_raal_timeslot_is_granted()) + { + cca_configuration_update(); + } + + return true; +} + +#if NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +void RADIO_IRQHandler(void) +#else // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +void nrf_802154_core_irq_handler(void) +#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +{ + irq_handler(); +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.h similarity index 53% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.h index 7cabb5633..66be46176 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,18 +29,20 @@ */ /** - * @brief This module contains Finite State Machine of nRF 802.15.4 radio driver. + * @brief This module contains core of the nRF IEEE 802.15.4 radio driver. * */ -#ifndef NRF_DRV_RADIO802154_FSM_H_ -#define NRF_DRV_RADIO802154_FSM_H_ +#ifndef NRF_802154_CORE_H_ +#define NRF_802154_CORE_H_ #include #include -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_rx_buffer.h" +#include "nrf_802154_config.h" +#include "nrf_802154_notification.h" +#include "nrf_802154_rx_buffer.h" +#include "nrf_802154_types.h" #ifdef __cplusplus extern "C" { @@ -52,47 +54,44 @@ extern "C" { typedef enum { // Sleep - RADIO_STATE_DISABLING, // Entering low power (DISABLED) mode - RADIO_STATE_SLEEP, // Low power (DISABLED) mode + RADIO_STATE_SLEEP, ///< Low power (DISABLED) mode - the only state in which HF clock is released and RAAL disabled. + RADIO_STATE_FALLING_ASLEEP, ///< Prior entering SLEEP state RAAL and HF clock are active. // Receive - RADIO_STATE_WAITING_TIMESLOT, // Radio is inactive due to denied time slot - RADIO_STATE_WAITING_RX_FRAME, // Waiting for frame in receiver mode - RADIO_STATE_RX_HEADER, // Received SFD, receiving MAC header - RADIO_STATE_RX_FRAME, // Received MAC destination address, receiving rest of the frame - RADIO_STATE_TX_ACK, // Received frame and transmitting ACK + RADIO_STATE_RX, ///< Receiver is enabled and it is receiving frames. + RADIO_STATE_TX_ACK, ///< Received frame and transmitting ACK. // Transmit - RADIO_STATE_CCA_BEFORE_TX, // Performing CCA prior to transmission - RADIO_STATE_TX_FRAME, // Transmitting data frame (or beacon) - RADIO_STATE_RX_ACK, // Receiving ACK after transmitted frame + RADIO_STATE_CCA_TX, ///< Performing CCA followed by frame transmission. + RADIO_STATE_TX, ///< Transmitting data frame (or beacon). + RADIO_STATE_RX_ACK, ///< Receiving ACK after transmitted frame. // Energy Detection - RADIO_STATE_ED, // Performing Energy Detection procedure + RADIO_STATE_ED, ///< Performing Energy Detection procedure. // CCA - RADIO_STATE_CCA, // Performing CCA procedure + RADIO_STATE_CCA, ///< Performing CCA procedure. // Continuous carrier - RADIO_STATE_CONTINUOUS_CARRIER, // Emitting continuous carrier wave. + RADIO_STATE_CONTINUOUS_CARRIER, ///< Emitting continuous carrier wave. } radio_state_t; /** - * @brief Initialize 802.15.4 driver FSM. + * @brief Initialize 802.15.4 driver core. */ -void nrf_drv_radio802154_fsm_init(void); +void nrf_802154_core_init(void); /** - * @brief Deinitialize 802.15.4 driver FSM. + * @brief Deinitialize 802.15.4 driver core. */ -void nrf_drv_radio802154_fsm_deinit(void); +void nrf_802154_core_deinit(void); /** * @brief Get current state of nRF 802.15.4 driver. * * @return Current state of the 802.15.4 driver. */ -radio_state_t nrf_drv_radio802154_fsm_state_get(void); +radio_state_t nrf_802154_core_state_get(void); /*************************************************************************************************** * @section State machine transition requests @@ -104,12 +103,12 @@ radio_state_t nrf_drv_radio802154_fsm_state_get(void); * @note This function shall be called from a critical section context. It shall not be interrupted * by the RADIO event handler or RAAL notification. * - * @note This function shall be called when the driver is in RECEIVE state. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. * * @retval true Entering SLEEP state succeeded. * @retval false Entering SLEEP state failed (driver is performing other procedure). */ -bool nrf_drv_radio802154_fsm_sleep(void); +bool nrf_802154_core_sleep(nrf_802154_term_t term_lvl); /** * @brief Request transition to RECEIVE state. @@ -117,12 +116,17 @@ bool nrf_drv_radio802154_fsm_sleep(void); * @note This function shall be called from a critical section context. It shall not be interrupted * by the RADIO event handler or RAAL notification. * - * @note This function shall be called when the driver is in SLEEP or TRANSMIT state. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + * @param[in] notify_function Function called to notify status of this procedure instead of + * default notification. If NULL default notification is used. * * @retval true Entering RECEIVE state succeeded. * @retval false Entering RECEIVE state failed (driver is performing other procedure). */ -bool nrf_drv_radio802154_fsm_receive(void); +bool nrf_802154_core_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function); /** * @brief Request transition to TRANSMIT state. @@ -130,15 +134,21 @@ bool nrf_drv_radio802154_fsm_receive(void); * @note This function shall be called from a critical section context. It shall not be interrupted * by the RADIO event handler or RAAL notification. * - * @note This function shall be called when the driver is in RECEIVE state. - * - * @param[in] p_data Pointer to a frame to transmit. - * @param[in] cca If the driver should perform CCA procedure before transmission. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + * @param[in] p_data Pointer to a frame to transmit. + * @param[in] cca If the driver should perform CCA procedure before transmission. + * @param[in] notify_function Function called to notify status of this procedure instead of + * default notification. If NULL default notification is used. * * @retval true Entering TRANSMIT state succeeded. * @retval false Entering TRANSMIT state failed (driver is performing other procedure). */ -bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, bool cca); +bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function); /** * @brief Request transition to ENERGY_DETECTION state. @@ -149,12 +159,13 @@ bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, bool cca); * @note This function shall be called when the driver is in SLEEP or RECEIVE state. When Energy * detection procedure is finished the driver will transit to RECEIVE state. * - * @param[in] time_us Minimal time of energy detection procedure. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] time_us Minimal time of energy detection procedure. * * @retval true Entering ENERGY_DETECTION state succeeded. * @retval false Entering ENERGY_DETECTION state failed (driver is performing other procedure). */ -bool nrf_drv_radio802154_fsm_energy_detection(uint32_t time_us); +bool nrf_802154_core_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us); /** * @brief Request transition to CCA state. @@ -162,13 +173,12 @@ bool nrf_drv_radio802154_fsm_energy_detection(uint32_t time_us); * @note This function shall be called from a critical section context. It shall not be interrupted * by the RADIO event handler or RAAL notification. * - * @note This function shall be called when the driver is in SLEEP or RECEIVE state. When CCA - * procedure is finished the driver will transit to RECEIVE state. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. * * @retval true Entering CCA state succeeded. * @retval false Entering CCA state failed (driver is performing other procedure). */ -bool nrf_drv_radio802154_fsm_cca(void); +bool nrf_802154_core_cca(nrf_802154_term_t term_lvl); /** * @brief Request transition to CONTINUOUS_CARRIER state. @@ -176,54 +186,53 @@ bool nrf_drv_radio802154_fsm_cca(void); * @note This function shall be called from a critical section context. It shall not be interrupted * by the RADIO event handler or RAAL notification. * - * @note This function shall be called when the driver is in RECEIVE or SLEEP state. When - * CONTINUOUS_CARRIER procedure is finished the driver will transit to RECEIVE state. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. * * @retval true Entering CONTINUOUS_CARRIER state succeeded. * @retval false Entering CONTINUOUS_CARRIER state failed (driver is performing other procedure). */ -bool nrf_drv_radio802154_fsm_continuous_carrier(void); +bool nrf_802154_core_continuous_carrier(nrf_802154_term_t term_lvl); /*************************************************************************************************** * @section State machine notifications **************************************************************************************************/ /** - * @brief Notify the FSM that higher layer freed a frame buffer. + * @brief Notify the Core module that higher layer freed a frame buffer. * - * When there were no free buffers available the FSM does not start receiver. If FSM receives this - * notification in changes internal state to make sure receiver is started if requested. + * When there were no free buffers available the core does not start receiver. If core receives this + * notification it changes internal state to make sure receiver is started if requested. * * @note This function shall be called from a critical section context. It shall not be interrupted * by the RADIO event handler or RAAL notification. * - * @param[in] p_buffer Pointer to buffer that has been freed. + * @param[in] p_data Pointer to buffer that has been freed. */ -void nrf_drv_radio802154_fsm_notify_buffer_free(rx_buffer_t * p_buffer); +bool nrf_802154_core_notify_buffer_free(uint8_t * p_data); /** - * @brief Notify the FSM that next higher layer requested change of the channel. + * @brief Notify the Core module that next higher layer requested change of the channel. * - * FSM should update frequency register of the peripheral and in case it is in RECEIVE state the + * Core should update frequency register of the peripheral and in case it is in RECEIVE state the * receiver should be disabled and enabled again to use new channel. */ -void nrf_drv_radio802154_fsm_channel_update(void); +bool nrf_802154_core_channel_update(void); /** - * @brief Notify the FSM that next higher layer requested change of the CCA configuration. + * @brief Notify the Core module that next higher layer requested change of the CCA configuration. */ -void nrf_drv_radio802154_fsm_cca_cfg_update(void); +bool nrf_802154_core_cca_cfg_update(void); -#if !NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING +#if !NRF_802154_INTERNAL_IRQ_HANDLING /** - * @brief Notify the FSM that there is a pending IRQ that should be handled. + * @brief Notify the Core module that there is a pending IRQ that should be handled. */ -void nrf_drv_radio802154_fsm_irq_handler(void); -#endif // !NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING +void nrf_802154_core_irq_handler(void); +#endif // !NRF_802154_INTERNAL_IRQ_HANDLING #ifdef __cplusplus } #endif -#endif /* NRF_DRV_RADIO802154_FSM_H_ */ +#endif /* NRF_802154_CORE_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.c new file mode 100644 index 000000000..b80d73ba7 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.c @@ -0,0 +1,185 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements hooks for the 802.15.4 driver Core module. + * + * Hooks are used by optional driver features to modify way in which notifications are propagated + * through the driver. + * + */ + +#include "nrf_802154_core_hooks.h" + +#include + +#include "mac_features/nrf_802154_ack_timeout.h" +#include "mac_features/nrf_802154_csma_ca.h" +#include "nrf_802154_config.h" +#include "nrf_802154_types.h" + + +typedef bool (* abort_hook)(nrf_802154_term_t term_lvl, req_originator_t req_orig); +typedef void (* transmitted_hook)(const uint8_t * p_frame); +typedef bool (* tx_failed_hook)(const uint8_t * p_frame, nrf_802154_tx_error_t error); +typedef bool (* tx_started_hook)(const uint8_t * p_frame); + +/* Since some compilers do not allow empty initializers for arrays with unspecified bounds, + * NULL pointer is appended to below arrays if the compiler used is not GCC. It is intentionally + * unused, but it prevents the arrays from being empty. GCC manages to optimize empty arrays away, + * so such a solution is unnecessary. */ + +static const abort_hook m_abort_hooks[] = +{ +#if NRF_802154_CSMA_CA_ENABLED + nrf_802154_csma_ca_abort, +#endif + +#if NRF_802154_ACK_TIMEOUT_ENABLED + nrf_802154_ack_timeout_abort, +#endif + + NULL, +}; + +static const transmitted_hook m_transmitted_hooks[] = +{ +#if NRF_802154_ACK_TIMEOUT_ENABLED + nrf_802154_ack_timeout_transmitted_hook, +#endif + + NULL, +}; + +static const tx_failed_hook m_tx_failed_hooks[] = +{ +#if NRF_802154_CSMA_CA_ENABLED + nrf_802154_csma_ca_tx_failed_hook, +#endif + +#if NRF_802154_ACK_TIMEOUT_ENABLED + nrf_802154_ack_timeout_tx_failed_hook, +#endif + + NULL, +}; + +static const tx_started_hook m_tx_started_hooks[] = +{ +#if NRF_802154_CSMA_CA_ENABLED + nrf_802154_csma_ca_tx_started_hook, +#endif + +#if NRF_802154_ACK_TIMEOUT_ENABLED + nrf_802154_ack_timeout_tx_started_hook, +#endif + + NULL, +}; + +bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_t req_orig) +{ + bool result = true; + + for (uint32_t i = 0; i < sizeof(m_abort_hooks) / sizeof(m_abort_hooks[0]); i++) + { + if (m_abort_hooks[i] == NULL) + { + break; + } + + result = m_abort_hooks[i](term_lvl, req_orig); + + if (!result) + { + break; + } + } + + return result; +} + +void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame) +{ + for (uint32_t i = 0; i < sizeof(m_transmitted_hooks) / sizeof(m_transmitted_hooks[0]); i++) + { + if (m_transmitted_hooks[i] == NULL) + { + break; + } + + m_transmitted_hooks[i](p_frame); + } +} + +bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error) +{ + bool result = true; + + for (uint32_t i = 0; i < sizeof(m_tx_failed_hooks) / sizeof(m_tx_failed_hooks[0]); i++) + { + if (m_tx_failed_hooks[i] == NULL) + { + break; + } + + result = m_tx_failed_hooks[i](p_frame, error); + + if (!result) + { + break; + } + } + + return result; +} + +bool nrf_802154_core_hooks_tx_started(const uint8_t * p_frame) +{ + bool result = true; + + for (uint32_t i = 0; i < sizeof(m_tx_started_hooks) / sizeof(m_tx_started_hooks[0]); i++) + { + if (m_tx_started_hooks[i] == NULL) + { + break; + } + + result = m_tx_started_hooks[i](p_frame); + + if (!result) + { + break; + } + } + + return result; +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h new file mode 100644 index 000000000..1f7bdc148 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h @@ -0,0 +1,95 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_CORE_HOOKS_H__ +#define NRF_802154_CORE_HOOKS_H__ + +#include +#include + +#include "nrf_802154_const.h" +#include "nrf_802154_types.h" + +/** + * @defgroup nrf_802154_hooks Hooks for the 802.15.4 driver core + * @{ + * @ingroup nrf_802154 + * @brief Hooks for the 802.15.4 driver core module. + * + * Hooks are used by optional driver features to modify way in which notifications are propagated + * through the driver. + */ + +/** + * @brief Process hooks for the terminate request. + * + * @param[in] term_lvl Termination level of request that terminates current operation. + * @param[in] req_orig Module that originates this request. + * + * @retval true All procedures are aborted. + * @retval false There is ongoing procedure that cannot be aborted due to too low @p priority. + */ +bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_t req_orig); + +/** + * @brief Process hooks for the transmitted event. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that was transmitted. + */ +void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame); + +/** + * @brief Process hooks for the TX failed event. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that was not transmitted. + * @param[in] error Cause of failed transmission. + * + * @retval true TX failed event should be propagated to the MAC layer. + * @retval false TX failed event should not be propagated to the MAC layer. It is handled + * internally. + */ +bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error); + +/** + * @brief Process hooks for the TX started event. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that is being transmitted. + * + * @retval true TX started event should be propagated to the MAC layer. + * @retval false TX started event should not be propagated to the MAC layer. It is handled + * internally. + */ +bool nrf_802154_core_hooks_tx_started(const uint8_t * p_frame); + +/** + *@} + **/ + +#endif // NRF_802154_CORE_HOOKS_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c new file mode 100644 index 000000000..7b39b360b --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c @@ -0,0 +1,220 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements critical sections used with requests by 802.15.4 driver. + * + */ + +#include "nrf_802154_critical_section.h" + +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_debug.h" +#include "hal/nrf_radio.h" +#include "platform/timer/nrf_802154_timer.h" +#include "raal/nrf_raal_api.h" + +#include + +#define CMSIS_IRQ_NUM_VECTACTIVE_DIFF 16 + +#define NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE (-1) + +static volatile uint8_t m_nested_critical_section_counter; ///< Counter of nested critical sections +static volatile int8_t m_nested_critical_section_allowed_priority; ///< Indicator if nested critical sections are currently allowed + +/** @brief Enter critical section for RADIO peripheral + * + * @note RADIO peripheral registers (and NVIC) are modified only when timeslot is granted for the + * 802.15.4 driver. + */ +static void radio_critical_section_enter(void) +{ + if (nrf_raal_timeslot_is_granted()) + { + NVIC_DisableIRQ(RADIO_IRQn); + __DSB(); + __ISB(); + } +} + +/** @brief Exit critical section for RADIO peripheral + * + * @note RADIO peripheral registers (and NVIC) are modified only when timeslot is granted for the + * 802.15.4 driver. + */ +static void radio_critical_section_exit(void) +{ + if (nrf_raal_timeslot_is_granted()) + { + NVIC_EnableIRQ(RADIO_IRQn); + } +} + +/** @brief Convert active priority value to int8_t type. + * + * @param[in] active_priority Active priority in uint32_t format + * + * @return Active_priority value in int8_t format. + */ +static int8_t active_priority_convert(uint32_t active_priority) +{ + return active_priority == UINT32_MAX ? INT8_MAX : (int8_t)active_priority; +} + +/** @brief Check if active vector priority is equal to priority that allows nested crit sections. + * + * @retval true Active vector priority allows nested critical sections. + * @retval false Active vector priority denies nested critical sections. + */ +static bool nested_critical_section_is_allowed_in_this_context(void) +{ + return m_nested_critical_section_allowed_priority == + active_priority_convert( + nrf_802154_critical_section_active_vector_priority_get()); +} + +static bool critical_section_enter(bool forced) +{ + bool result = true; + uint8_t cnt; + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CRIT_SECT_ENTER); + + do + { + cnt = __LDREXB(&m_nested_critical_section_counter); + + assert(cnt < UINT8_MAX); + + if (!forced && cnt > 0 && !nested_critical_section_is_allowed_in_this_context()) + { + __CLREX(); + result = false; + break; + } + + radio_critical_section_enter(); + nrf_raal_critical_section_enter(); + } + while (__STREXB(cnt + 1, &m_nested_critical_section_counter)); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_CRIT_SECT_ENTER); + return result; +} + +void nrf_802154_critical_section_init(void) +{ + m_nested_critical_section_counter = 0; + m_nested_critical_section_allowed_priority = NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE; +} + +bool nrf_802154_critical_section_enter(void) +{ + return critical_section_enter(false); +} + +void nrf_802154_critical_section_forcefully_enter(void) +{ + bool critical_section_entered = critical_section_enter(true); + assert(critical_section_entered); +} + +void nrf_802154_critical_section_exit(void) +{ + uint8_t cnt; + static bool exiting_crit_sect; + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CRIT_SECT_EXIT); + + do + { + cnt = __LDREXB(&m_nested_critical_section_counter); + + assert(cnt > 0); + + if (cnt == 1) + { + assert(!exiting_crit_sect); + exiting_crit_sect = true; + + // RAAL critical section shall be exited before RADIO IRQ handler is enabled. In other + // case RADIO IRQ handler may be called out of timeslot. + nrf_raal_critical_section_exit(); + radio_critical_section_exit(); + + exiting_crit_sect = false; + } + } + while (__STREXB(cnt - 1, &m_nested_critical_section_counter)); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_CRIT_SECT_EXIT); +} + +void nrf_802154_critical_section_nesting_allow(void) +{ + assert(m_nested_critical_section_allowed_priority == + NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE); + + m_nested_critical_section_allowed_priority = active_priority_convert( + nrf_802154_critical_section_active_vector_priority_get()); +} + +void nrf_802154_critical_section_nesting_deny(void) +{ + assert(m_nested_critical_section_allowed_priority >= 0); + + m_nested_critical_section_allowed_priority = NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE; +} + +uint32_t nrf_802154_critical_section_active_vector_priority_get(void) +{ + uint32_t active_vector_id = (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos; + IRQn_Type irq_number; + uint32_t active_priority; + + // Check if this function is called from main thread. + if (active_vector_id == 0) + { + return UINT32_MAX; + } + + assert(active_vector_id >= CMSIS_IRQ_NUM_VECTACTIVE_DIFF); + + irq_number = (IRQn_Type)(active_vector_id - CMSIS_IRQ_NUM_VECTACTIVE_DIFF); + active_priority = NVIC_GetPriority(irq_number); + + return active_priority; +} + diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.h similarity index 53% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.h index 130f1e5ad..e37c98abf 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,8 +28,8 @@ * */ -#ifndef NRF_DRIVER_RADIO802154_CRITICAL_SECTION_H__ -#define NRF_DRIVER_RADIO802154_CRITICAL_SECTION_H__ +#ifndef NRF_802154_CRITICAL_SECTION_H__ +#define NRF_802154_CRITICAL_SECTION_H__ #include #include @@ -39,21 +39,62 @@ extern "C" { #endif /** - * @defgroup nrf_driver_radio802154_critical_section 802.15.4 driver critical section + * @defgroup nrf_802154_critical_section 802.15.4 driver critical section * @{ - * @ingroup nrf_driver_radio802154 + * @ingroup nrf_802154 * @brief Critical section used with requests to the 802.15.4 driver. */ /** - * @brief Enter critical section in the 802.15.4 driver. + * @brief Initialize critical section module. */ -void nrf_drv_radio802154_critical_section_enter(void); +void nrf_802154_critical_section_init(void); + +/** + * @brief Enter critical section in the 802.15.4 driver. + * + * @note Entering critical section may be prohibited at given time. If critical section is not + * entered, request should not be proceeded. + * + * @retval true Entered critical section. + * @retval false Could not enter critical section. + */ +bool nrf_802154_critical_section_enter(void); /** * @brief Exit critical section in the 802.15.4 driver. */ -void nrf_drv_radio802154_critical_section_exit(void); +void nrf_802154_critical_section_exit(void); + +/** + * @brief Forcefully enter critical section in the 802.15.4 driver. + * + * This function enters critical section regardless critical sections is already entered. + * + * This function is intended to be used by RADIO IRQ handler and RAAL notifications handlers to + * prevent interrupting of these procedures by FSM requests from higher priority IRQ handlers. + */ +void nrf_802154_critical_section_forcefully_enter(void); + +/** + * @brief Allow entering nested critical section. + * + * This function is intended to be used with notification module in order to allow processing + * requests called from notification context. + */ +void nrf_802154_critical_section_nesting_allow(void); + +/** + * @brief Disallow entering nested critical section. + */ +void nrf_802154_critical_section_nesting_deny(void); + +/** + * @brief Get current IRQ priority. + * + * @return IRQ priority + */ +uint32_t nrf_802154_critical_section_active_vector_priority_get(void); /** *@} @@ -63,4 +104,4 @@ void nrf_drv_radio802154_critical_section_exit(void); } #endif -#endif // NRF_DRIVER_RADIO802154_CRITICAL_SECTION_H__ +#endif // NRF_802154_CRITICAL_SECTION_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.c similarity index 95% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.c rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.c index 9a911d665..7fcda41c8 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ * */ -#include "nrf_drv_radio802154_debug.h" +#include "nrf_802154_debug.h" #include @@ -45,9 +45,9 @@ #if ENABLE_DEBUG_LOG /// Buffer used to store debug log messages. -volatile uint32_t nrf_drv_radio802154_debug_log_buffer[NRF_DRV_RADIO802154_DEBUG_LOG_BUFFER_LEN]; +volatile uint32_t nrf_802154_debug_log_buffer[NRF_802154_DEBUG_LOG_BUFFER_LEN]; /// Index of the log buffer pointing to the element that should be filled with next log message. -volatile uint32_t nrf_drv_radio802154_debug_log_ptr = 0; +volatile uint32_t nrf_802154_debug_log_ptr = 0; #endif #if ENABLE_DEBUG_GPIO @@ -129,7 +129,7 @@ static void raal_softdevice_event_gpio_toggle_init(void) } #endif // ENABLE_DEBUG_GPIO -void nrf_drv_radio802154_debug_init(void) +void nrf_802154_debug_init(void) { #if ENABLE_DEBUG_GPIO radio_event_gpio_toggle_init(); diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.h similarity index 78% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.h index 374aa71a6..fcaca9ec6 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_debug.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,8 +33,8 @@ * */ -#ifndef NRF_DRV_RADIO802154_DEBUG_H_ -#define NRF_DRV_RADIO802154_DEBUG_H_ +#ifndef NRF_802154_DEBUG_H_ +#define NRF_802154_DEBUG_H_ #include @@ -42,12 +42,10 @@ extern "C" { #endif -#define NRF_DRV_RADIO802154_DEBUG_LOG_BUFFER_LEN 1024 +#define NRF_802154_DEBUG_LOG_BUFFER_LEN 1024 #define EVENT_TRACE_ENTER 0x0001UL #define EVENT_TRACE_EXIT 0x0002UL -#define EVENT_MUTEX_LOCK 0x0003UL -#define EVENT_MUTEX_UNLOCK 0x0004UL #define EVENT_SET_STATE 0x0005UL #define EVENT_RADIO_RESET 0x0006UL @@ -58,6 +56,7 @@ extern "C" { #define FUNCTION_BUFFER_FREE 0x0005UL #define FUNCTION_CCA 0x0006UL #define FUNCTION_CONTINUOUS_CARRIER 0x0007UL +#define FUNCTION_CSMACA 0x0008UL #define FUNCTION_IRQ_HANDLER 0x0100UL #define FUNCTION_EVENT_FRAMESTART 0x0101UL @@ -69,6 +68,8 @@ extern "C" { #define FUNCTION_EVENT_CCABUSY 0x0107UL #define FUNCTION_EVENT_EDEND 0x0108UL #define FUNCTION_EVENT_PHYEND 0x0109UL +#define FUNCTION_EVENT_CRCOK 0x010AUL +#define FUNCTION_EVENT_CRCERROR 0x010BUL #define FUNCTION_AUTO_ACK_ABORT 0x0201UL #define FUNCTION_TIMESLOT_STARTED 0x0202UL @@ -108,48 +109,48 @@ extern "C" { #define PIN_DBG_RTC0_EVT_REM 31 #if ENABLE_DEBUG_LOG -extern volatile uint32_t nrf_drv_radio802154_debug_log_buffer[ - NRF_DRV_RADIO802154_DEBUG_LOG_BUFFER_LEN]; -extern volatile uint32_t nrf_drv_radio802154_debug_log_ptr; +extern volatile uint32_t nrf_802154_debug_log_buffer[ + NRF_802154_DEBUG_LOG_BUFFER_LEN]; +extern volatile uint32_t nrf_802154_debug_log_ptr; -#define nrf_drv_radio802154_log(EVENT_CODE, EVENT_ARG) \ +#define nrf_802154_log(EVENT_CODE, EVENT_ARG) \ do { \ - uint32_t ptr = nrf_drv_radio802154_debug_log_ptr; \ - nrf_drv_radio802154_debug_log_buffer[ptr] = ((EVENT_CODE) | ((EVENT_ARG) << 16)); \ - nrf_drv_radio802154_debug_log_ptr = \ - ptr < (NRF_DRV_RADIO802154_DEBUG_LOG_BUFFER_LEN - 1) ? ptr + 1 : 0; \ + uint32_t ptr = nrf_802154_debug_log_ptr; \ + nrf_802154_debug_log_buffer[ptr] = ((EVENT_CODE) | ((EVENT_ARG) << 16)); \ + nrf_802154_debug_log_ptr = \ + ptr < (NRF_802154_DEBUG_LOG_BUFFER_LEN - 1) ? ptr + 1 : 0; \ } while (0) #else // ENABLE_DEBUG_LOG -#define nrf_drv_radio802154_log(EVENT_CODE, EVENT_ARG) +#define nrf_802154_log(EVENT_CODE, EVENT_ARG) #endif // ENABLE_DEBUG_LOG #if ENABLE_DEBUG_GPIO -#define nrf_drv_radio802154_pin_set(pin) NRF_P0->OUTSET = (1UL << (pin)) -#define nrf_drv_radio802154_pin_clr(pin) NRF_P0->OUTCLR = (1UL << (pin)) -#define nrf_drv_radio802154_pin_tgl(pin) do { volatile uint32_t ps = NRF_P0->OUT; \ - NRF_P0->OUTSET = (~ps & (1UL << (pin))); \ - NRF_P0->OUTCLR = (ps & (1UL << (pin))); \ +#define nrf_802154_pin_set(pin) NRF_P0->OUTSET = (1UL << (pin)) +#define nrf_802154_pin_clr(pin) NRF_P0->OUTCLR = (1UL << (pin)) +#define nrf_802154_pin_tgl(pin) do { volatile uint32_t ps = NRF_P0->OUT; \ + NRF_P0->OUTSET = (~ps & (1UL << (pin))); \ + NRF_P0->OUTCLR = (ps & (1UL << (pin))); \ } while(0); #else // ENABLE_DEBUG_GPIO -#define nrf_drv_radio802154_pin_set(pin) -#define nrf_drv_radio802154_pin_clr(pin) -#define nrf_drv_radio802154_pin_tgl(pin) +#define nrf_802154_pin_set(pin) +#define nrf_802154_pin_clr(pin) +#define nrf_802154_pin_tgl(pin) #endif // ENABLE_DEBUG_GPIO /** * @brief Initialize debug helpers for nRF 802.15.4 driver. */ -void nrf_drv_radio802154_debug_init(void); +void nrf_802154_debug_init(void); #ifdef __cplusplus } #endif -#endif /* NRF_DRV_RADIO802154_DEBUG_H_ */ +#endif /* NRF_802154_DEBUG_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification.h similarity index 56% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification.h index f8cdb711e..9425486bb 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,29 +28,39 @@ * */ -#ifndef NRF_DRIVER_RADIO802154_NOTIFICATION_H__ -#define NRF_DRIVER_RADIO802154_NOTIFICATION_H__ +#ifndef NRF_802154_NOTIFICATION_H__ +#define NRF_802154_NOTIFICATION_H__ #include #include -#include "nrf_drv_radio802154.h" +#include "nrf_802154.h" #ifdef __cplusplus extern "C" { #endif /** - * @defgroup nrf_driver_radio802154_notification 802.15.4 driver notification + * @defgroup nrf_802154_notification 802.15.4 driver notification * @{ - * @ingroup nrf_driver_radio802154 + * @ingroup nrf_802154 * @brief Notifications to the next higher layer triggered from 802.15.4 radio driver. */ +/** + * @brief Function type used for external notification + * + * This function is called instead of default notification. Function is passed to request to notify + * atomically during request processing. + * + * @param[in] result If called request succeeded. + */ +typedef void (*nrf_802154_notification_func_t)(bool result); + /** * @brief Initialize notification module. */ -void nrf_drv_radio802154_notification_init(void); +void nrf_802154_notification_init(void); /** * @brief Notify next higher layer that a frame was received. @@ -59,44 +69,65 @@ void nrf_drv_radio802154_notification_init(void); * @param[in] power RSSI measured during the frame reception. * @param[in] lqi LQI indicating measured link quality during the frame reception. */ -void nrf_drv_radio802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi); +void nrf_802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi); /** * @brief Notify next higher layer that reception of a frame failed. * * @param[in] error An error code that indicates reason of the failure. */ -void nrf_drv_radio802154_notify_receive_failed(nrf_drv_radio802154_rx_error_t error); +void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error); /** * @brief Notify next higher layer that a frame was transmitted. * - * @param[in] p_ack Pointer to buffer containing PSDU of ACK frame. NULL if ACK was not requested. - * @param[in] power RSSI of received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of received frame of 0 if ACK was not requested. + * @param[in] p_frame Pointer to buffer containing PSDU of transmitted frame. + * @param[in] p_ack Pointer to buffer containing PSDU of ACK frame. NULL if ACK was not + * requested. + * @param[in] power RSSI of received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of received frame of 0 if ACK was not requested. */ -void nrf_drv_radio802154_notify_transmitted(uint8_t * p_ack, int8_t power, int8_t lqi); +void nrf_802154_notify_transmitted(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + int8_t lqi); /** * @brief Notify next higher layer that a frame was not transmitted. * - * @param[in] error An error code indicating reason of the failure. + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that failed transmit + * operation. + * @param[in] error An error code indicating reason of the failure. */ -void nrf_drv_radio802154_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error); +void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error); /** * @brief Notify next higher layer that energy detection procedure ended. * * @param[in] result Detected energy level. */ -void nrf_drv_radio802154_notify_energy_detected(uint8_t result); +void nrf_802154_notify_energy_detected(uint8_t result); + +/** + * @brief Notify next higher layer that energy detection procedure failed. + * + * @param[in] error An error code indicating reason of the failure. + */ +void nrf_802154_notify_energy_detection_failed(nrf_802154_ed_error_t error); /** * @brief Notify next higher layer that CCA procedure ended. * * @param[in] is_free If detected that channel is free. */ -void nrf_drv_radio802154_notify_cca(bool is_free); +void nrf_802154_notify_cca(bool is_free); + +/** + * @brief Notify next higher layer that CCA procedure failed. + * + * @param[in] error An error code indicating reason of the failure. + */ +void nrf_802154_notify_cca_failed(nrf_802154_cca_error_t error); /** *@} @@ -106,4 +137,4 @@ void nrf_drv_radio802154_notify_cca(bool is_free); } #endif -#endif // NRF_DRIVER_RADIO802154_NOTIFICATION_H__ +#endif // NRF_802154_NOTIFICATION_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_direct.c new file mode 100644 index 000000000..db424abaf --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_direct.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements notifications triggered directly by the nrf 802.15.4 radio driver. + * + */ + +#include "nrf_802154_notification.h" + +#include +#include + +#include "nrf_802154.h" +#include "nrf_802154_critical_section.h" + +#define RAW_LENGTH_OFFSET 0 +#define RAW_PAYLOAD_OFFSET 1 + +void nrf_802154_notification_init(void) +{ + // Intentionally empty +} + +void nrf_802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi) +{ +#if NRF_802154_USE_RAW_API + nrf_802154_received_raw(p_data, power, lqi); +#else // NRF_802154_USE_RAW_API + nrf_802154_received(p_data + RAW_PAYLOAD_OFFSET, p_data[RAW_LENGTH_OFFSET], power, lqi); +#endif // NRF_802154_USE_RAW_API +} + +void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error) +{ + nrf_802154_receive_failed(error); +} + +void nrf_802154_notify_transmitted(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + int8_t lqi) +{ +#if NRF_802154_USE_RAW_API + nrf_802154_transmitted_raw(p_frame, p_ack, power, lqi); +#else // NRF_802154_USE_RAW_API + nrf_802154_transmitted(p_frame + RAW_PAYLOAD_OFFSET, + p_ack + RAW_PAYLOAD_OFFSET, + p_ack[RAW_LENGTH_OFFSET], + power, + lqi); +#endif // NRF_802154_USE_RAW_API +} + +void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error) +{ +#if NRF_802154_USE_RAW_API + nrf_802154_transmit_failed(p_frame, error); +#else // NRF_802154_USE_RAW_API + nrf_802154_transmit_failed(p_frame + RAW_PAYLOAD_OFFSET, error); +#endif // NRF_802154_USE_RAW_API +} + +void nrf_802154_notify_energy_detected(uint8_t result) +{ + nrf_802154_energy_detected(result); +} + +void nrf_802154_notify_energy_detection_failed(nrf_802154_ed_error_t error) +{ + nrf_802154_energy_detection_failed(error); +} + +void nrf_802154_notify_cca(bool is_free) +{ + nrf_802154_cca_done(is_free); +} + +void nrf_802154_notify_cca_failed(nrf_802154_cca_error_t error) +{ + nrf_802154_cca_failed(error); +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_swi.c similarity index 57% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_swi.c index ef99ad7ec..aed226628 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_swi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,47 +34,60 @@ * */ -#include "nrf_drv_radio802154_notification.h" +#include "nrf_802154_notification.h" #include #include -#include "nrf_drv_radio802154.h" -#include "nrf_drv_radio802154_swi.h" +#include "nrf_802154.h" +#include "nrf_802154_swi.h" #include "raal/nrf_raal_api.h" -void nrf_drv_radio802154_notification_init(void) +void nrf_802154_notification_init(void) { - nrf_drv_radio802154_swi_init(); + nrf_802154_swi_init(); } -void nrf_drv_radio802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi) +void nrf_802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi) { - nrf_drv_radio802154_swi_notify_received(p_data, power, lqi); + nrf_802154_swi_notify_received(p_data, power, lqi); } -void nrf_drv_radio802154_notify_receive_failed(nrf_drv_radio802154_rx_error_t error) +void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error) { - nrf_drv_radio802154_swi_notify_receive_failed(error); + nrf_802154_swi_notify_receive_failed(error); } -void nrf_drv_radio802154_notify_transmitted(uint8_t * p_ack, int8_t power, int8_t lqi) +void nrf_802154_notify_transmitted(const uint8_t * p_frame, + uint8_t * p_ack, + int8_t power, + int8_t lqi) { - nrf_drv_radio802154_swi_notify_transmitted(p_ack, power, lqi); + nrf_802154_swi_notify_transmitted(p_frame, p_ack, power, lqi); } -void nrf_drv_radio802154_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error) +void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error) { - nrf_drv_radio802154_swi_notify_transmit_failed(error); + nrf_802154_swi_notify_transmit_failed(p_frame, error); } -void nrf_drv_radio802154_notify_energy_detected(uint8_t result) +void nrf_802154_notify_energy_detected(uint8_t result) { - nrf_drv_radio802154_swi_notify_energy_detected(result); + nrf_802154_swi_notify_energy_detected(result); } -void nrf_drv_radio802154_notify_cca(bool is_free) +void nrf_802154_notify_energy_detection_failed(nrf_802154_ed_error_t error) { - nrf_drv_radio802154_swi_notify_cca(is_free); + nrf_802154_swi_notify_energy_detection_failed(error); +} + +void nrf_802154_notify_cca(bool is_free) +{ + nrf_802154_swi_notify_cca(is_free); +} + +void nrf_802154_notify_cca_failed(nrf_802154_cca_error_t error) +{ + nrf_802154_swi_notify_cca_failed(error); } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.c new file mode 100644 index 000000000..92c19003c --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.c @@ -0,0 +1,194 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements storage of PIB attributes in nRF 802.15.4 radio driver. + * + */ + +#include "nrf_802154_pib.h" + +#include +#include +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_const.h" + +typedef struct +{ + int8_t tx_power; ///< Transmit power. + uint8_t pan_id[PAN_ID_SIZE]; ///< Pan Id of this node. + uint8_t short_addr[SHORT_ADDRESS_SIZE]; ///< Short Address of this node. + uint8_t extended_addr[EXTENDED_ADDRESS_SIZE]; ///< Extended Address of this node. + nrf_802154_cca_cfg_t cca; ///< CCA mode and thresholds. + bool promiscuous :1; ///< Indicating if radio is in promiscuous mode. + bool auto_ack :1; ///< Indicating if auto ACK procedure is enabled. + uint8_t channel :5; ///< Channel on which the node receives messages. +} nrf_802154_pib_data_t; + +static nrf_802154_pib_data_t m_data; ///< Buffer containing PIB data. + +void nrf_802154_pib_init(void) +{ + m_data.promiscuous = false; + m_data.auto_ack = true; + m_data.channel = 11; + + memset(m_data.pan_id, 0xff, sizeof(m_data.pan_id)); + m_data.short_addr[0] = 0xfe; + m_data.short_addr[1] = 0xff; + memset(m_data.extended_addr, 0, sizeof(m_data.extended_addr)); + + m_data.cca.mode = NRF_802154_CCA_MODE_DEFAULT; + m_data.cca.ed_threshold = NRF_802154_CCA_ED_THRESHOLD_DEFAULT; + m_data.cca.corr_threshold = NRF_802154_CCA_CORR_THRESHOLD_DEFAULT; + m_data.cca.corr_limit = NRF_802154_CCA_CORR_LIMIT_DEFAULT; +} + +bool nrf_802154_pib_promiscuous_get(void) +{ + return m_data.promiscuous; +} + +void nrf_802154_pib_promiscuous_set(bool enabled) +{ + m_data.promiscuous = enabled; +} + +bool nrf_802154_pib_auto_ack_get(void) +{ + return m_data.auto_ack; +} + +void nrf_802154_pib_auto_ack_set(bool enabled) +{ + m_data.auto_ack = enabled; +} + +uint8_t nrf_802154_pib_channel_get(void) +{ + return m_data.channel; +} + +void nrf_802154_pib_channel_set(uint8_t channel) +{ + m_data.channel = channel; +} + +int8_t nrf_802154_pib_tx_power_get(void) +{ + return m_data.tx_power; +} + +void nrf_802154_pib_tx_power_set(int8_t dbm) +{ + const int8_t allowed_values[] = {-40, -20, -16, -12, -8, -4, 0, 2, 3, 4, 5, 6, 7, 8, 9}; + const int8_t highest_value = allowed_values[(sizeof(allowed_values) / sizeof(allowed_values[0])) - 1]; + if (dbm > highest_value) + { + dbm = highest_value; + } + else + { + for (uint32_t i = 0; i < sizeof(allowed_values) / sizeof(allowed_values[0]); i++) + { + if (dbm <= allowed_values[i]) + { + dbm = allowed_values[i]; + break; + } + } + } + + m_data.tx_power = dbm; +} + +const uint8_t * nrf_802154_pib_pan_id_get(void) +{ + return m_data.pan_id; +} + +void nrf_802154_pib_pan_id_set(const uint8_t * p_pan_id) +{ + memcpy(m_data.pan_id, p_pan_id, PAN_ID_SIZE); +} + +const uint8_t * nrf_802154_pib_extended_address_get(void) +{ + return m_data.extended_addr; +} + +void nrf_802154_pib_extended_address_set(const uint8_t * p_extended_address) +{ + memcpy(m_data.extended_addr, p_extended_address, EXTENDED_ADDRESS_SIZE); +} + +const uint8_t * nrf_802154_pib_short_address_get(void) +{ + return m_data.short_addr; +} + +void nrf_802154_pib_short_address_set(const uint8_t * p_short_address) +{ + memcpy(m_data.short_addr, p_short_address, SHORT_ADDRESS_SIZE); +} + +void nrf_802154_pib_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg) +{ + switch (p_cca_cfg->mode) + { + case NRF_RADIO_CCA_MODE_ED: + m_data.cca.mode = p_cca_cfg->mode; + m_data.cca.ed_threshold = p_cca_cfg->ed_threshold; + break; + + case NRF_RADIO_CCA_MODE_CARRIER: + m_data.cca.mode = p_cca_cfg->mode; + m_data.cca.corr_threshold = p_cca_cfg->corr_threshold; + m_data.cca.corr_limit = p_cca_cfg->corr_limit; + break; + + case NRF_RADIO_CCA_MODE_CARRIER_AND_ED: + case NRF_RADIO_CCA_MODE_CARRIER_OR_ED: + memcpy(&m_data.cca, p_cca_cfg, sizeof(m_data.cca)); + break; + + default: + assert(false); + } +} + +void nrf_802154_pib_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg) +{ + memcpy(p_cca_cfg, &m_data.cca, sizeof(m_data.cca)); +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.h similarity index 70% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.h index f92266b43..08ec8638c 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,13 +33,13 @@ * */ -#ifndef NRF_DRV_RADIO802154_PIB_H_ -#define NRF_DRV_RADIO802154_PIB_H_ +#ifndef NRF_802154_PIB_H_ +#define NRF_802154_PIB_H_ #include #include -#include "nrf_drv_radio802154.h" +#include "nrf_802154.h" #ifdef __cplusplus extern "C" { @@ -48,7 +48,7 @@ extern "C" { /** * @brief Initialize this module. */ -void nrf_drv_radio802154_pib_init(void); +void nrf_802154_pib_init(void); /** * @brief Check if promiscuous mode is enabled. @@ -56,14 +56,14 @@ void nrf_drv_radio802154_pib_init(void); * @retval true If promiscuous mode is enabled. * @retval false If promiscuous mode is disabled. */ -bool nrf_drv_radio802154_pib_promiscuous_get(void); +bool nrf_802154_pib_promiscuous_get(void); /** * @brief Enable or disable promiscuous mode. * * @param[in] enabled If promiscuous mode should be enabled. */ -void nrf_drv_radio802154_pib_promiscuous_set(bool enabled); +void nrf_802154_pib_promiscuous_set(bool enabled); /** * @brief Check if auto ACK procedure is enabled. @@ -71,14 +71,14 @@ void nrf_drv_radio802154_pib_promiscuous_set(bool enabled); * @retval true If auto ACK procedure is enabled. * @retval false If auto ACK procedure is disabled. */ -bool nrf_drv_radio802154_pib_auto_ack_get(void); +bool nrf_802154_pib_auto_ack_get(void); /** * @brief Enable or disable auto ACK procedure. * * @param[in] enabled If auto ACK procedure should be enabled. */ -void nrf_drv_radio802154_pib_auto_ack_set(bool enabled); +void nrf_802154_pib_auto_ack_set(bool enabled); /** @@ -86,28 +86,35 @@ void nrf_drv_radio802154_pib_auto_ack_set(bool enabled); * * @return Channel number used by the driver. */ -uint8_t nrf_drv_radio802154_pib_channel_get(void); +uint8_t nrf_802154_pib_channel_get(void); /** * @brief Set channel that will be used by the driver. * * @param[in] channel Number of channel used by the driver. */ -void nrf_drv_radio802154_pib_channel_set(uint8_t channel); +void nrf_802154_pib_channel_set(uint8_t channel); /** * @brief Get transmit power. * * @returns Transmit power [dBm]. */ -int8_t nrf_drv_radio802154_pib_tx_power_get(void); +int8_t nrf_802154_pib_tx_power_get(void); /** * @brief Set transmit power used for ACK frames. * * @param[in] dbm Transmit power [dBm]. */ -void nrf_drv_radio802154_pib_tx_power_set(int8_t dbm); +void nrf_802154_pib_tx_power_set(int8_t dbm); + +/** + * @brief Get PAN Id used by this device. + * + * @returns Pointer to buffer containing PAN Id value (2 bytes, little-endian). + */ +const uint8_t * nrf_802154_pib_pan_id_get(void); /** * @brief Set PAN Id used by this device. @@ -116,7 +123,14 @@ void nrf_drv_radio802154_pib_tx_power_set(int8_t dbm); * * This function makes copy of the PAN Id. */ -void nrf_drv_radio802154_pib_pan_id_set(const uint8_t * p_pan_id); +void nrf_802154_pib_pan_id_set(const uint8_t * p_pan_id); + +/** + * @brief Get Extended Address of this device + * + * @returns Pointer to buffer containing extended address (8 bytes, little-endian). + */ +const uint8_t * nrf_802154_pib_extended_address_get(void); /** * @brief Set Extended Address of this device. @@ -125,7 +139,14 @@ void nrf_drv_radio802154_pib_pan_id_set(const uint8_t * p_pan_id); * * This function makes copy of the address. */ -void nrf_drv_radio802154_pib_extended_address_set(const uint8_t * p_extended_address); +void nrf_802154_pib_extended_address_set(const uint8_t * p_extended_address); + +/** + * @brief Get Short Address of this device + * + * @returns Pointer to buffer containing short address (2 bytes, little-endian). + */ +const uint8_t * nrf_802154_pib_short_address_get(void); /** * @brief Set Short Address of this device. @@ -134,38 +155,25 @@ void nrf_drv_radio802154_pib_extended_address_set(const uint8_t * p_extended_add * * This function makes copy of the address. */ -void nrf_drv_radio802154_pib_short_address_set(const uint8_t * p_short_address); - -/** - * @brief Check if destination address in given frame matches address stored in this module or - * broadcast address. - * - * This function is intended to check if received frame is destined to this node. - * - * @param[in] p_psdu Pointer to PSDU of frame to check. - * - * @return If destination address in given PSDU matches address stored in this module or broadcast - * address. - */ -bool nrf_drv_radio802154_pib_dest_addr_matches(const uint8_t * p_psdu); +void nrf_802154_pib_short_address_set(const uint8_t * p_short_address); /** * @brief Set radio CCA mode and threshold. * * @param[in] p_cca_cfg A pointer to the CCA configuration structure. Only fields relevant to selected mode are updated. */ -void nrf_drv_radio802154_pib_cca_cfg_set(const nrf_drv_radio802154_cca_cfg_t * p_cca_cfg); +void nrf_802154_pib_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg); /** * @brief Get current radio CCA configuration. * * @param[out] p_cca_cfg A pointer to the structure for current CCA configuration. */ -void nrf_drv_radio802154_pib_cca_cfg_get(nrf_drv_radio802154_cca_cfg_t * p_cca_cfg); +void nrf_802154_pib_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); #ifdef __cplusplus } #endif -#endif /* NRF_DRV_RADIO802154_PIB_H_ */ +#endif /* NRF_802154_PIB_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h similarity index 82% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h index 3b03f666c..7558c2ec0 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,17 +28,17 @@ * */ -#ifndef NRF_DRIVER_RADIO802154_PRIORITY_DROP_H__ -#define NRF_DRIVER_RADIO802154_PRIORITY_DROP_H__ +#ifndef NRF_802154_PRIORITY_DROP_H__ +#define NRF_802154_PRIORITY_DROP_H__ #ifdef __cplusplus extern "C" { #endif /** - * @defgroup nrf_driver_radio802154_priority_drop 802.15.4 driver procedures with lower priority. + * @defgroup nrf_802154_priority_drop 802.15.4 driver procedures with lower priority. * @{ - * @ingroup nrf_driver_radio802154 + * @ingroup nrf_802154 * @brief Internal procedures of 802.15.4 driver that should be called with lower priority than * the caller's priority. */ @@ -46,14 +46,14 @@ extern "C" { /** * @brief Initialize notification module. */ -void nrf_drv_radio802154_priority_drop_init(void); +void nrf_802154_priority_drop_init(void); /** * @brief Request discarding of the timeslot. * * @note This function should be called through this module to prevent calling it from arbiter context. */ -void nrf_drv_radio802154_priority_drop_timeslot_exit(void); +void nrf_802154_priority_drop_timeslot_exit(void); /** *@} @@ -63,5 +63,5 @@ void nrf_drv_radio802154_priority_drop_timeslot_exit(void); } #endif -#endif // NRF_DRIVER_RADIO802154_PRIORITY_DROP_H__ +#endif // NRF_802154_PRIORITY_DROP_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c similarity index 89% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_direct.c rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c index 02163d894..3277b7237 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_direct.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,16 +35,16 @@ * */ -#include "nrf_drv_radio802154_priority_drop.h" +#include "nrf_802154_priority_drop.h" #include "raal/nrf_raal_api.h" -void nrf_drv_radio802154_priority_drop_init(void) +void nrf_802154_priority_drop_init(void) { // Intentionally empty } -void nrf_drv_radio802154_priority_drop_timeslot_exit(void) +void nrf_802154_priority_drop_timeslot_exit(void) { nrf_raal_continuous_mode_exit(); } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c similarity index 84% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_swi.c rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c index a4226b1e3..44b8cb764 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,17 +35,17 @@ * */ -#include "nrf_drv_radio802154_priority_drop.h" +#include "nrf_802154_priority_drop.h" -#include "nrf_drv_radio802154_swi.h" +#include "nrf_802154_swi.h" -void nrf_drv_radio802154_priority_drop_init(void) +void nrf_802154_priority_drop_init(void) { - nrf_drv_radio802154_swi_init(); + nrf_802154_swi_init(); } -void nrf_drv_radio802154_priority_drop_timeslot_exit(void) +void nrf_802154_priority_drop_timeslot_exit(void) { - nrf_drv_radio802154_swi_timeslot_exit(); + nrf_802154_swi_timeslot_exit(); } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_procedures_duration.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_procedures_duration.h similarity index 72% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_procedures_duration.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_procedures_duration.h index b09ada37b..7e8889d10 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_procedures_duration.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_procedures_duration.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,21 +33,20 @@ * */ -#ifndef NRF_DRV_RADIO802154_PROCEDURES_DURATION_H_ -#define NRF_DRV_RADIO802154_PROCEDURES_DURATION_H_ +#ifndef NRF_802154_PROCEDURES_DURATION_H_ +#define NRF_802154_PROCEDURES_DURATION_H_ #include #include +#include "nrf.h" + +#include "nrf_802154_const.h" #define TX_RAMP_UP_TIME 40 // us #define RX_RAMP_UP_TIME 40 // us #define RX_RAMP_DOWN_TIME 0 // us #define MAX_RAMP_DOWN_TIME 6 // us -#define PHY_US_PER_SYMBOL 16 // us/sym -#define PHY_SYMBOLS_PER_OCTET 2 // sym/byte -#define PHY_SHR_DURATION 10 // sym - #define A_CCA_DURATION 8 // sym #define A_TURNAROUND_TIME 12 // sym #define A_UNIT_BACKOFF_PERIOD 20 // sym @@ -59,9 +58,19 @@ PHY_SHR_DURATION + \ (NUM_OCTETS_IN_ACK * PHY_SYMBOLS_PER_OCTET)) -static inline uint16_t nrf_drv_radio802154_tx_duration_get(uint8_t psdu_length, - bool cca, - bool ack_requested) +__STATIC_INLINE uint16_t nrf_802154_tx_duration_get(uint8_t psdu_length, + bool cca, + bool ack_requested); + +__STATIC_INLINE uint16_t nrf_802154_rx_duration_get(uint8_t psdu_length, bool ack_requested); + +__STATIC_INLINE uint16_t nrf_802154_cca_duration_get(void); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint16_t nrf_802154_tx_duration_get(uint8_t psdu_length, + bool cca, + bool ack_requested) { // ramp down // if CCA: + RX ramp up + CCA + RX ramp down @@ -86,11 +95,11 @@ static inline uint16_t nrf_drv_radio802154_tx_duration_get(uint8_t psdu_length, return result; } -static inline uint16_t nrf_drv_radio802154_rx_duration_get(uint8_t psdu_length, bool ack_requested) +__STATIC_INLINE uint16_t nrf_802154_rx_duration_get(uint8_t psdu_length, bool ack_requested) { // SHR + PHR + PSDU // if ACK: + aTurnaroundTime + ACK frame duration - uint16_t result = PHY_SHR_DURATION + (psdu_length + 1) * PHY_SYMBOLS_PER_OCTET; + uint16_t result = PHY_SHR_DURATION + ((psdu_length + 1) * PHY_SYMBOLS_PER_OCTET); if (ack_requested) { @@ -104,12 +113,14 @@ static inline uint16_t nrf_drv_radio802154_rx_duration_get(uint8_t psdu_length, return result; } -static inline uint16_t nrf_drv_radio802154_cca_duration_get(void) +__STATIC_INLINE uint16_t nrf_802154_cca_duration_get(void) { // ramp down + rx ramp up + CCA - uint16_t result = MAX_RAMP_DOWN_TIME + RX_RAMP_UP_TIME + A_CCA_DURATION * PHY_US_PER_SYMBOL; + uint16_t result = MAX_RAMP_DOWN_TIME + RX_RAMP_UP_TIME + (A_CCA_DURATION * PHY_US_PER_SYMBOL); return result; } -#endif /* NRF_DRV_RADIO802154_PROCEDURES_DURATION_H_ */ +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +#endif /* NRF_802154_PROCEDURES_DURATION_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request.h similarity index 55% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_request.h index 7e3091dd7..233ec6ed4 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,97 +28,123 @@ * */ -#ifndef NRF_DRIVER_RADIO802154_REQUEST_H__ -#define NRF_DRIVER_RADIO802154_REQUEST_H__ +#ifndef NRF_802154_REQUEST_H__ +#define NRF_802154_REQUEST_H__ #include #include +#include "nrf_802154_const.h" +#include "nrf_802154_notification.h" +#include "nrf_802154_types.h" + #ifdef __cplusplus extern "C" { #endif /** - * @defgroup nrf_driver_radio802154_request 802.15.4 driver request + * @defgroup nrf_802154_request 802.15.4 driver request * @{ - * @ingroup nrf_driver_radio802154 + * @ingroup nrf_802154 * @brief Requests to the driver triggered from the MAC layer. */ /** * @brief Initialize request module. */ -void nrf_drv_radio802154_request_init(void); +void nrf_802154_request_init(void); /** * @brief Request entering sleep state. * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * * @retval true The driver will enter sleep state. * @retval false The driver cannot enter sleep state due to ongoing operation. */ -bool nrf_drv_radio802154_request_sleep(void); +bool nrf_802154_request_sleep(nrf_802154_term_t term_lvl); /** * @brief Request entering receive state. * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + * @param[in] notify_function Function called to notify status of this procedure instead of + * default notification. If NULL default notification is used. + * * @retval true The driver will enter receive state. * @retval false The driver cannot enter receive state due to ongoing operation. */ -bool nrf_drv_radio802154_request_receive(void); +bool nrf_802154_request_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function); /** * @brief Request entering transmit state. * - * @param[in] p_data Pointer to the frame to transmit. - * @param[in] cca If the driver should perform CCA procedure before transmission. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + * @param[in] p_data Pointer to the frame to transmit. + * @param[in] cca If the driver should perform CCA procedure before transmission. + * @param[in] notify_function Function called to notify status of this procedure instead of + * default notification. If NULL default notification is used. * * @retval true The driver will enter transmit state. * @retval false The driver cannot enter transmit state due to ongoing operation. */ -bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, bool cca); +bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function); /** * @brief Request entering energy detection state. * - * @param[in] time_us Requested duration of energy detection procedure. + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] time_us Requested duration of energy detection procedure. * * @retval true The driver will enter energy detection state. * @retval false The driver cannot enter energy detection state due to ongoing operation. */ -bool nrf_drv_radio802154_request_energy_detection(uint32_t time_us); +bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us); /** * @brief Request entering CCA state. * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * * @retval true The driver will enter CCA state. * @retval false The driver cannot enter CCA state due to ongoing operation. */ -bool nrf_drv_radio802154_request_cca(void); +bool nrf_802154_request_cca(nrf_802154_term_t term_lvl); /** * @brief Request entering continuous carrier state. * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * * @retval true The driver will enter continuous carrier state. * @retval false The driver cannot enter continuous carrier state due to ongoing operation. */ -bool nrf_drv_radio802154_request_continuous_carrier(void); +bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl); /** * @brief Request the driver to free given buffer. * * @param[in] p_data Pointer to the buffer to free. */ -void nrf_drv_radio802154_request_buffer_free(uint8_t * p_data); +bool nrf_802154_request_buffer_free(uint8_t * p_data); /** * @brief Request the driver to update channel number used by the RADIO peripheral. */ -void nrf_drv_radio802154_request_channel_update(void); +bool nrf_802154_request_channel_update(void); /** * @brief Request the driver to update CCA configuration used by the RADIO peripheral. */ -void nrf_drv_radio802154_request_cca_cfg_update(void); +bool nrf_802154_request_cca_cfg_update(void); /** *@} @@ -128,4 +154,4 @@ void nrf_drv_radio802154_request_cca_cfg_update(void); } #endif -#endif // NRF_DRIVER_RADIO802154_REQUEST_H__ +#endif // NRF_802154_REQUEST_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c new file mode 100644 index 000000000..8c07a9c92 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c @@ -0,0 +1,139 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements requests to the driver triggered directly by the MAC layer. + * + */ + +#include "nrf_802154_request.h" + +#include +#include + +#include "nrf_802154_core.h" +#include "nrf_802154_critical_section.h" +#include "hal/nrf_radio.h" + +#define REQUEST_FUNCTION(func_core, params_core) \ + bool result; \ + \ + if (nrf_802154_critical_section_enter()) \ + { \ + result = func_core params_core; \ + nrf_802154_critical_section_exit(); \ + } \ + else \ + { \ + result = false; \ + } \ + \ + return result; + + +#define REQUEST_FUNCTION_NO_ARGS(func_core) \ + REQUEST_FUNCTION(func_core, ()) + +#define REQUEST_FUNCTION_1_ARG(func_core, arg) \ + REQUEST_FUNCTION(func_core, (arg)) + +#define REQUEST_FUNCTION_2_ARGS(func_core, arg1, arg2) \ + REQUEST_FUNCTION(func_core, (arg1, arg2)) + +#define REQUEST_FUNCTION_3_ARGS(func_core, arg1, arg2, arg3) \ + REQUEST_FUNCTION(func_core, (arg1, arg2, arg3)) + +#define REQUEST_FUNCTION_4_ARGS(func_core, arg1, arg2, arg3, arg4) \ + REQUEST_FUNCTION(func_core, (arg1, arg2, arg3, arg4)) + +#define REQUEST_FUNCTION_5_ARGS(func_core, arg1, arg2, arg3, arg4, arg5) \ + REQUEST_FUNCTION(func_core, (arg1, arg2, arg3, arg4, arg5)) + +void nrf_802154_request_init(void) +{ + // Intentionally empty +} + +bool nrf_802154_request_sleep(nrf_802154_term_t term_lvl) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_sleep, term_lvl) +} + +bool nrf_802154_request_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function) +{ + REQUEST_FUNCTION_3_ARGS(nrf_802154_core_receive, term_lvl, req_orig, notify_function) +} + +bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function) +{ + REQUEST_FUNCTION_5_ARGS(nrf_802154_core_transmit, + term_lvl, + req_orig, + p_data, + cca, + notify_function) +} + +bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us) +{ + REQUEST_FUNCTION_2_ARGS(nrf_802154_core_energy_detection, term_lvl, time_us) +} + +bool nrf_802154_request_cca(nrf_802154_term_t term_lvl) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_cca, term_lvl) +} + +bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_continuous_carrier, term_lvl) +} + +bool nrf_802154_request_buffer_free(uint8_t * p_data) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_notify_buffer_free, p_data) +} + +bool nrf_802154_request_channel_update(void) +{ + REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_channel_update) +} + +bool nrf_802154_request_cca_cfg_update(void) +{ + REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update) +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c new file mode 100644 index 000000000..55029fd1e --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements requests to the driver triggered by the MAC layer through SWI. + * + */ + +#include "nrf_802154_request.h" + +#include +#include +#include + +#include "nrf_802154_config.h" +#include "nrf_802154_core.h" +#include "nrf_802154_critical_section.h" +#include "nrf_802154_debug.h" +#include "nrf_802154_rx_buffer.h" +#include "nrf_802154_swi.h" +#include "hal/nrf_radio.h" + +#include + +#define REQUEST_FUNCTION(func_core, params_core, func_swi, params_swi) \ + bool result = false; \ + \ + if (active_vector_priority_is_high()) \ + { \ + if (nrf_802154_critical_section_enter()) \ + { \ + result = func_core params_core; \ + nrf_802154_critical_section_exit(); \ + } \ + else \ + { \ + result = false; \ + } \ + } \ + else \ + { \ + func_swi params_swi; \ + } \ + \ + return result; + +#define REQUEST_FUNCTION_NO_ARGS(func_core, func_swi) \ + REQUEST_FUNCTION(func_core, (), func_swi, (&result)) + +#define REQUEST_FUNCTION_1_ARG(func_core, func_swi, arg) \ + REQUEST_FUNCTION(func_core, (arg), func_swi, (arg, &result)) + +#define REQUEST_FUNCTION_2_ARGS(func_core, func_swi, arg1, arg2) \ + REQUEST_FUNCTION(func_core, (arg1, arg2), func_swi, (arg1, arg2, &result)) + +#define REQUEST_FUNCTION_3_ARGS(func_core, func_swi, arg1, arg2, arg3) \ + REQUEST_FUNCTION(func_core, (arg1, arg2, arg3), func_swi, (arg1, arg2, arg3, &result)) + +#define REQUEST_FUNCTION_4_ARGS(func_core, func_swi, arg1, arg2, arg3, arg4) \ + REQUEST_FUNCTION(func_core, \ + (arg1, arg2, arg3, arg4), \ + func_swi, \ + (arg1, arg2, arg3, arg4, &result)) + +#define REQUEST_FUNCTION_5_ARGS(func_core, func_swi, arg1, arg2, arg3, arg4, arg5) \ + REQUEST_FUNCTION(func_core, \ + (arg1, arg2, arg3, arg4, arg5), \ + func_swi, \ + (arg1, arg2, arg3, arg4, arg5, &result)) + +/** Check if active vector priority is high enough to call requests directly. + * + * @retval true Active vector priority is greater or equal to SWI priority. + * @retval false Active vector priority is lower than SWI priority. + */ +static bool active_vector_priority_is_high(void) +{ + + return nrf_802154_critical_section_active_vector_priority_get() <= NRF_802154_SWI_PRIORITY; +} + +void nrf_802154_request_init(void) +{ + nrf_802154_swi_init(); +} + +bool nrf_802154_request_sleep(nrf_802154_term_t term_lvl) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_sleep, + nrf_802154_swi_sleep, + term_lvl) +} + +bool nrf_802154_request_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function) +{ + REQUEST_FUNCTION_3_ARGS(nrf_802154_core_receive, + nrf_802154_swi_receive, + term_lvl, + req_orig, + notify_function) +} + +bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function) +{ + REQUEST_FUNCTION_5_ARGS(nrf_802154_core_transmit, + nrf_802154_swi_transmit, + term_lvl, + req_orig, + p_data, + cca, + notify_function) +} + +bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, + uint32_t time_us) +{ + REQUEST_FUNCTION_2_ARGS(nrf_802154_core_energy_detection, + nrf_802154_swi_energy_detection, + term_lvl, + time_us) +} + +bool nrf_802154_request_cca(nrf_802154_term_t term_lvl) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_cca, + nrf_802154_swi_cca, + term_lvl) +} + +bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_continuous_carrier, + nrf_802154_swi_continuous_carrier, + term_lvl) +} + +bool nrf_802154_request_buffer_free(uint8_t * p_data) +{ + REQUEST_FUNCTION_1_ARG(nrf_802154_core_notify_buffer_free, + nrf_802154_swi_buffer_free, + p_data) +} + +bool nrf_802154_request_channel_update(void) +{ + REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_channel_update, + nrf_802154_swi_channel_update) +} + +bool nrf_802154_request_cca_cfg_update(void) +{ + REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update, + nrf_802154_swi_cca_cfg_update) +} + diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c similarity index 92% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.c rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c index 226d282bf..af6c0a63a 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ * */ -#include "nrf_drv_radio802154_revision.h" +#include "nrf_802154_revision.h" #include @@ -44,9 +44,9 @@ typedef enum NRF52840_REVISION_AAAA, NRF52840_REVISION_AABA, NRF52840_REVISION_UNKNOWN, -} nrf_drv_radio802154_chip_revision; +} nrf_802154_chip_revision; -static nrf_drv_radio802154_chip_revision m_nrf52840_revision = NRF52840_REVISION_UNKNOWN; +static nrf_802154_chip_revision m_nrf52840_revision = NRF52840_REVISION_UNKNOWN; /** * @brief Internal auxiliary function to check if the program is running on NRF52840 chip. @@ -88,7 +88,7 @@ static inline bool nrf_revision_type_52840_aaba(void) (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00)); // sub-revision } -void nrf_drv_radio802154_revision_init(void) +void nrf_802154_revision_init(void) { if (nrf_revision_type_52840_aaaa()) { @@ -104,7 +104,7 @@ void nrf_drv_radio802154_revision_init(void) } } -bool nrf_drv_radio802154_revision_has_phyend_event(void) +bool nrf_802154_revision_has_phyend_event(void) { #if NRF52840_AAAA return false; diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.h similarity index 89% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.h index c02b846ab..77bcae820 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_revision.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,8 +33,8 @@ * */ -#ifndef NRF_DRV_RADIO802154_REVISION_H_ -#define NRF_DRV_RADIO802154_REVISION_H_ +#ifndef NRF_802154_REVISION_H_ +#define NRF_802154_REVISION_H_ #include #include @@ -50,7 +50,7 @@ extern "C" { * @note If the chip revision is not recognized, this module assumes that it is running on a newer * chip revision that has all of the features, that the most recent known revision has. */ -void nrf_drv_radio802154_revision_init(void); +void nrf_802154_revision_init(void); /** * @brief Function to check if the program is running on NRF52840 revision that supports PHYEND event. @@ -58,10 +58,10 @@ void nrf_drv_radio802154_revision_init(void); * @retval true If PHYEND event is supported. * @retval false If PHYEND event is not supported. */ -bool nrf_drv_radio802154_revision_has_phyend_event(void); +bool nrf_802154_revision_has_phyend_event(void); #ifdef __cplusplus } #endif -#endif /* NRF_DRV_RADIO802154_REVISION_H_ */ +#endif /* NRF_802154_REVISION_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.c similarity index 73% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.c rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.c index 42e7b234c..ffc09b9c6 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,33 +34,33 @@ * */ -#include "nrf_drv_radio802154_rx_buffer.h" +#include "nrf_802154_rx_buffer.h" #include -#include "nrf_drv_radio802154_config.h" +#include "nrf_802154_config.h" -#if NRF_DRV_RADIO802154_RX_BUFFERS < 1 +#if NRF_802154_RX_BUFFERS < 1 #error Not enough rx buffers in the 802.15.4 radio driver. #endif -rx_buffer_t nrf_drv_radio802154_rx_buffers[NRF_DRV_RADIO802154_RX_BUFFERS]; ///< Receive buffers. +rx_buffer_t nrf_802154_rx_buffers[NRF_802154_RX_BUFFERS]; ///< Receive buffers. -void nrf_drv_radio802154_rx_buffer_init(void) +void nrf_802154_rx_buffer_init(void) { - for (uint32_t i = 0; i < NRF_DRV_RADIO802154_RX_BUFFERS; i++) + for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++) { - nrf_drv_radio802154_rx_buffers[i].free = true; + nrf_802154_rx_buffers[i].free = true; } } -rx_buffer_t * nrf_drv_radio802154_rx_buffer_free_find(void) +rx_buffer_t * nrf_802154_rx_buffer_free_find(void) { - for (uint32_t i = 0; i < NRF_DRV_RADIO802154_RX_BUFFERS; i++) + for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++) { - if (nrf_drv_radio802154_rx_buffers[i].free) + if (nrf_802154_rx_buffers[i].free) { - return &nrf_drv_radio802154_rx_buffers[i]; + return &nrf_802154_rx_buffers[i]; } } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.h similarity index 83% rename from third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.h rename to third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.h index e58923c4f..f3d94cb27 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,13 +33,13 @@ * */ -#ifndef NRF_DRV_RADIO802154_RX_BUFFER_H_ -#define NRF_DRV_RADIO802154_RX_BUFFER_H_ +#ifndef NRF_802154_RX_BUFFER_H_ +#define NRF_802154_RX_BUFFER_H_ #include #include -#include "nrf_drv_radio802154_const.h" +#include "nrf_802154_const.h" #ifdef __cplusplus extern "C" { @@ -57,27 +57,27 @@ typedef struct /** * @brief Array containing all buffers used to receive frame. * - * This array is in global scope to allow optimizations in FSM module in case there is only + * This array is in global scope to allow optimizations in Core module in case there is only * one buffer provided by this module. * */ -extern rx_buffer_t nrf_drv_radio802154_rx_buffers[]; +extern rx_buffer_t nrf_802154_rx_buffers[]; /** * @brief Initialize buffer for received frames. */ -void nrf_drv_radio802154_rx_buffer_init(void); +void nrf_802154_rx_buffer_init(void); /** * @brief Get free buffer to receive a frame. * * @return Pointer to free buffer of NULL if no free buffer is available. */ -rx_buffer_t * nrf_drv_radio802154_rx_buffer_free_find(void); +rx_buffer_t * nrf_802154_rx_buffer_free_find(void); #ifdef __cplusplus } #endif -#endif /* NRF_DRV_RADIO802154_RX_BUFFER_H_ */ +#endif /* NRF_802154_RX_BUFFER_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c new file mode 100644 index 000000000..75198d5d0 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c @@ -0,0 +1,821 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements SWI manager for nRF 802.15.4 driver. + * + */ + +#include "nrf_802154_swi.h" + +#include +#include +#include + +#include "nrf_802154.h" +#include "nrf_802154_config.h" +#include "nrf_802154_core.h" +#include "nrf_802154_critical_section.h" +#include "nrf_802154_rx_buffer.h" +#include "hal/nrf_egu.h" +#include "raal/nrf_raal_api.h" + + +/** Size of notification queue. + * + * One slot for each receive buffer, one for transmission, one for busy channel and one for energy + * detection. + */ +#define NTF_QUEUE_SIZE (NRF_802154_RX_BUFFERS + 3) +/** Size of requests queue. + * + * Two is minimal queue size. It is not expected in current implementation to queue a few requests. + */ +#define REQ_QUEUE_SIZE 2 + +#define SWI_EGU NRF_802154_SWI_EGU_INSTANCE ///< Label of SWI peripheral. +#define SWI_IRQn NRF_802154_SWI_IRQN ///< Symbol of SWI IRQ number. +#define SWI_IRQHandler NRF_802154_SWI_IRQ_HANDLER ///< Symbol of SWI IRQ handler. + +#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt. +#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task. +#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event. + +#define TIMESLOT_EXIT_INT NRF_EGU_INT_TRIGGERED1 ///< Label of timeslot exit interrupt. +#define TIMESLOT_EXIT_TASK NRF_EGU_TASK_TRIGGER1 ///< Label of timeslot exit task. +#define TIMESLOT_EXIT_EVENT NRF_EGU_EVENT_TRIGGERED1 ///< Label of timeslot exit event. + +#define REQ_INT NRF_EGU_INT_TRIGGERED2 ///< Label of request interrupt. +#define REQ_TASK NRF_EGU_TASK_TRIGGER2 ///< Label of request task. +#define REQ_EVENT NRF_EGU_EVENT_TRIGGERED2 ///< Label of request event. + +#define RAW_LENGTH_OFFSET 0 +#define RAW_PAYLOAD_OFFSET 1 + +/// Types of notifications in notification queue. +typedef enum +{ + NTF_TYPE_RECEIVED, ///< Frame received + NTF_TYPE_RECEIVE_FAILED, ///< Frame reception failed + NTF_TYPE_TRANSMITTED, ///< Frame transmitted + NTF_TYPE_TRANSMIT_FAILED, ///< Frame transmission failure + NTF_TYPE_ENERGY_DETECTED, ///< Energy detection procedure ended + NTF_TYPE_ENERGY_DETECTION_FAILED, ///< Energy detection procedure failed + NTF_TYPE_CCA, ///< CCA procedure ended + NTF_TYPE_CCA_FAILED, ///< CCA procedure failed +} nrf_802154_ntf_type_t; + +/// Notification data in the notification queue. +typedef struct +{ + nrf_802154_ntf_type_t type; ///< Notification type. + union + { + struct + { + uint8_t * p_psdu; ///< Pointer to received frame PSDU. + int8_t power; ///< RSSI of received frame. + int8_t lqi; ///< LQI of received frame. + } received; ///< Received frame details. + + struct + { + nrf_802154_rx_error_t error; ///< An error code that indicates reason of the failure. + } receive_failed; + + struct + { + const uint8_t * p_frame; ///< Pointer to frame that was transmitted. + uint8_t * p_psdu; ///< Pointer to received ACK PSDU or NULL. + int8_t power; ///< RSSI of received ACK or 0. + int8_t lqi; ///< LQI of received ACK or 0. + } transmitted; ///< Transmitted frame details. + + struct + { + const uint8_t * p_frame; ///< Pointer to frame that was requested to be transmitted, but failed. + nrf_802154_tx_error_t error; ///< An error code that indicates reason of the failure. + } transmit_failed; + + struct + { + int8_t result; ///< Energy detection result. + } energy_detected; ///< Energy detection details. + + struct + { + nrf_802154_ed_error_t error; ///< An error code that indicates reason of the failure. + } energy_detection_failed; ///< Energy detection failure details. + + struct + { + bool result; ///< CCA result. + } cca; ///< CCA details. + + struct + { + nrf_802154_cca_error_t error; ///< An error code that indicates reason of the failure. + } cca_failed; ///< CCA failure details. + } data; ///< Notification data depending on it's type. +} nrf_802154_ntf_data_t; + +/// Type of requests in request queue. +typedef enum +{ + REQ_TYPE_SLEEP, + REQ_TYPE_RECEIVE, + REQ_TYPE_TRANSMIT, + REQ_TYPE_ENERGY_DETECTION, + REQ_TYPE_CCA, + REQ_TYPE_CONTINUOUS_CARRIER, + REQ_TYPE_BUFFER_FREE, + REQ_TYPE_CHANNEL_UPDATE, + REQ_TYPE_CCA_CFG_UPDATE +} nrf_802154_req_type_t; + +/// Request data in request queue. +typedef struct +{ + nrf_802154_req_type_t type; ///< Type of the request. + union + { + struct + { + nrf_802154_term_t term_lvl; ///< Request priority. + bool * p_result; ///< Sleep request result. + } sleep; ///< Sleep request details. + + struct + { + nrf_802154_notification_func_t notif_func; ///< Error notified in case of success. + nrf_802154_term_t term_lvl; ///< Request priority. + req_originator_t req_orig; ///< Request originator. + bool * p_result; ///< Receive request result. + } receive; ///< Receive request details. + + struct + { + nrf_802154_notification_func_t notif_func; ///< Error notified in case of success. + nrf_802154_term_t term_lvl; ///< Request priority. + req_originator_t req_orig; ///< Request originator. + const uint8_t * p_data; ///< Pointer to PSDU to transmit. + bool cca; ///< If CCA was requested prior to transmission. + bool * p_result; ///< Transmit request result. + } transmit; ///< Transmit request details. + + struct + { + nrf_802154_term_t term_lvl; ///< Request priority. + bool * p_result; ///< Energy detection request result. + uint32_t time_us; ///< Requested time of energy detection procedure. + } energy_detection; ///< Energy detection request details. + + struct + { + nrf_802154_term_t term_lvl; ///< Request priority. + bool * p_result; ///< CCA request result. + } cca; ///< CCA request details. + + struct + { + nrf_802154_term_t term_lvl; ///< Request priority. + bool * p_result; ///< Continuous carrier request result. + } continuous_carrier; ///< Continuous carrier request details. + + struct + { + uint8_t * p_data; ///< Pointer to receive buffer to free. + bool * p_result; ///< Buffer free request result. + } buffer_free; ///< Buffer free request details. + + struct + { + bool * p_result; ///< Channel update request result. + } channel_update; ///< Channel update request details. + + struct + { + bool * p_result; ///< CCA config update request result. + } cca_cfg_update; ///< CCA config update request details. + } data; ///< Request data depending on it's type. +} nrf_802154_req_data_t; + +static nrf_802154_ntf_data_t m_ntf_queue[NTF_QUEUE_SIZE]; ///< Notification queue. +static uint8_t m_ntf_r_ptr; ///< Notification queue read index. +static uint8_t m_ntf_w_ptr; ///< Notification queue write index. + +static nrf_802154_req_data_t m_req_queue[REQ_QUEUE_SIZE]; ///< Request queue. +static uint8_t m_req_r_ptr; ///< Request queue read index. +static uint8_t m_req_w_ptr; ///< Request queue write index. + +/** + * Increment given index for any queue. + * + * @param[inout] p_ptr Index to increment. + * @param[in] queue_size Number of elements in the queue. + */ +static void queue_ptr_increment(uint8_t * p_ptr, uint8_t queue_size) +{ + if (++(*p_ptr) >= queue_size) + { + *p_ptr = 0; + } +} + +/** + * Check if given queue is full. + * + * @param[in] r_ptr Read index associated with given queue. + * @param[in] w_ptr Write index associated with given queue. + * @param[in] queue_size Number of elements in the queue. + * + * @retval true Given queue is full. + * @retval false Given queue is not full. + */ +static bool queue_is_full(uint8_t r_ptr, uint8_t w_ptr, uint8_t queue_size) +{ + if (w_ptr == (r_ptr - 1)) + { + return true; + } + + if ((r_ptr == 0) && (w_ptr == queue_size - 1)) + { + return true; + } + + return false; +} + +/** + * Check if given queue is empty. + * + * @param[in] r_ptr Read index associated with given queue. + * @param[in] w_ptr Write index associated with given queue. + * + * @retval true Given queue is empty. + * @retval false Given queue is not empty. + */ +static bool queue_is_empty(uint8_t r_ptr, uint8_t w_ptr) +{ + return (r_ptr == w_ptr); +} + +/** + * Increment given index associated with notification queue. + * + * @param[inout] p_ptr Pointer to the index to increment. + */ +static void ntf_queue_ptr_increment(uint8_t * p_ptr) +{ + queue_ptr_increment(p_ptr, NTF_QUEUE_SIZE); +} + +/** + * Check if notification queue is full. + * + * @retval true Notification queue is full. + * @retval false Notification queue is not full. + */ +static bool ntf_queue_is_full(void) +{ + return queue_is_full(m_ntf_r_ptr, m_ntf_w_ptr, NTF_QUEUE_SIZE); +} + +/** + * Check if notification queue is empty. + * + * @retval true Notification queue is empty. + * @retval false Notification queue is not empty. + */ +static bool ntf_queue_is_empty(void) +{ + return queue_is_empty(m_ntf_r_ptr, m_ntf_w_ptr); +} + +/** + * Increment given index associated with request queue. + * + * @param[inout] p_ptr Pointer to the index to increment. + */ +static void req_queue_ptr_increment(uint8_t * p_ptr) +{ + queue_ptr_increment(p_ptr, REQ_QUEUE_SIZE); +} + +/** + * Check if request queue is full. + * + * @retval true Request queue is full. + * @retval false Request queue is not full. + */ +static bool req_queue_is_full(void) +{ + return queue_is_full(m_req_r_ptr, m_req_w_ptr, REQ_QUEUE_SIZE); +} + +/** + * Check if request queue is empty. + * + * @retval true Request queue is empty. + * @retval false Request queue is not empty. + */ +static bool req_queue_is_empty(void) +{ + return queue_is_empty(m_req_r_ptr, m_req_w_ptr); +} + +/** + * Enter request block. + * + * This is a helper function used in all request functions to atomically + * find an empty slot in request queue and allow atomic slot update. + * + * @return Pointer to an empty slot in the request queue. + */ +static nrf_802154_req_data_t * req_enter(void) +{ + __disable_irq(); + __DSB(); + __ISB(); + + assert(!req_queue_is_full()); + + return &m_req_queue[m_req_w_ptr]; +} + +/** + * Exit request block. + * + * This is a helper function used in all request functions to end atomic slot update + * and trigger SWI to process the request from the slot. + */ +static void req_exit(void) +{ + req_queue_ptr_increment(&m_req_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, REQ_TASK); + + __enable_irq(); + __DSB(); + __ISB(); +} + +void nrf_802154_swi_init(void) +{ + m_ntf_r_ptr = 0; + m_ntf_w_ptr = 0; + + nrf_egu_int_enable(SWI_EGU, NTF_INT | TIMESLOT_EXIT_INT | REQ_INT); + + NVIC_SetPriority(SWI_IRQn, NRF_802154_SWI_PRIORITY); + NVIC_ClearPendingIRQ(SWI_IRQn); + NVIC_EnableIRQ(SWI_IRQn); +} + +void nrf_802154_swi_notify_received(uint8_t * p_data, int8_t power, int8_t lqi) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_RECEIVED; + p_slot->data.received.p_psdu = p_data; + p_slot->data.received.power = power; + p_slot->data.received.lqi = lqi; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_receive_failed(nrf_802154_rx_error_t error) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_RECEIVE_FAILED; + p_slot->data.receive_failed.error = error; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_transmitted(const uint8_t * p_frame, + uint8_t * p_data, + int8_t power, + int8_t lqi) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_TRANSMITTED; + p_slot->data.transmitted.p_frame = p_frame; + p_slot->data.transmitted.p_psdu = p_data; + p_slot->data.transmitted.power = power; + p_slot->data.transmitted.lqi = lqi; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_TRANSMIT_FAILED; + p_slot->data.transmit_failed.p_frame = p_frame; + p_slot->data.transmit_failed.error = error; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_energy_detected(uint8_t result) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_ENERGY_DETECTED; + p_slot->data.energy_detected.result = result; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_energy_detection_failed(nrf_802154_ed_error_t error) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_ENERGY_DETECTION_FAILED; + p_slot->data.energy_detection_failed.error = error; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_cca(bool channel_free) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_CCA; + p_slot->data.cca.result = channel_free; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_notify_cca_failed(nrf_802154_cca_error_t error) +{ + assert(!ntf_queue_is_full()); + + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_CCA_FAILED; + p_slot->data.cca_failed.error = error; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + +void nrf_802154_swi_timeslot_exit(void) +{ + assert(!nrf_egu_event_check(SWI_EGU, TIMESLOT_EXIT_EVENT)); + + nrf_egu_task_trigger(SWI_EGU, TIMESLOT_EXIT_TASK); +} + +void nrf_802154_swi_sleep(nrf_802154_term_t term_lvl, bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_SLEEP; + p_slot->data.sleep.term_lvl = term_lvl; + p_slot->data.sleep.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function, + bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_RECEIVE; + p_slot->data.receive.term_lvl = term_lvl; + p_slot->data.receive.req_orig = req_orig; + p_slot->data.receive.notif_func = notify_function; + p_slot->data.receive.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function, + bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_TRANSMIT; + p_slot->data.transmit.term_lvl = term_lvl; + p_slot->data.transmit.req_orig = req_orig; + p_slot->data.transmit.p_data = p_data; + p_slot->data.transmit.cca = cca; + p_slot->data.transmit.notif_func = notify_function; + p_slot->data.transmit.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_energy_detection(nrf_802154_term_t term_lvl, + uint32_t time_us, + bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_ENERGY_DETECTION; + p_slot->data.energy_detection.term_lvl = term_lvl; + p_slot->data.energy_detection.time_us = time_us; + p_slot->data.energy_detection.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_cca(nrf_802154_term_t term_lvl, bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_CCA; + p_slot->data.cca.term_lvl = term_lvl; + p_slot->data.cca.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_continuous_carrier(nrf_802154_term_t term_lvl, bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_CONTINUOUS_CARRIER; + p_slot->data.continuous_carrier.term_lvl = term_lvl; + p_slot->data.continuous_carrier.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_buffer_free(uint8_t * p_data, bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_BUFFER_FREE; + p_slot->data.buffer_free.p_data = p_data; + p_slot->data.buffer_free.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_channel_update(bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_CHANNEL_UPDATE; + p_slot->data.channel_update.p_result = p_result; + + req_exit(); +} + +void nrf_802154_swi_cca_cfg_update(bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_CCA_CFG_UPDATE; + p_slot->data.cca_cfg_update.p_result = p_result; + + req_exit(); +} + +void SWI_IRQHandler(void) +{ + if (nrf_egu_event_check(SWI_EGU, NTF_EVENT)) + { + nrf_egu_event_clear(SWI_EGU, NTF_EVENT); + + while (!ntf_queue_is_empty()) + { + nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_r_ptr]; + + switch (p_slot->type) + { + case NTF_TYPE_RECEIVED: +#if NRF_802154_USE_RAW_API + nrf_802154_received_raw(p_slot->data.received.p_psdu, + p_slot->data.received.power, + p_slot->data.received.lqi); +#else // NRF_802154_USE_RAW_API + nrf_802154_received(p_slot->data.received.p_psdu + RAW_PAYLOAD_OFFSET, + p_slot->data.received.p_psdu[RAW_LENGTH_OFFSET], + p_slot->data.received.power, + p_slot->data.received.lqi); +#endif + break; + + case NTF_TYPE_RECEIVE_FAILED: + nrf_802154_receive_failed(p_slot->data.receive_failed.error); + break; + + case NTF_TYPE_TRANSMITTED: +#if NRF_802154_USE_RAW_API + nrf_802154_transmitted_raw(p_slot->data.transmitted.p_frame, + p_slot->data.transmitted.p_psdu, + p_slot->data.transmitted.power, + p_slot->data.transmitted.lqi); +#else // NRF_802154_USE_RAW_API + nrf_802154_transmitted(p_slot->data.transmitted.p_frame + RAW_PAYLOAD_OFFSET, + p_slot->data.transmitted.p_psdu + RAW_PAYLOAD_OFFSET, + p_slot->data.transmitted.p_psdu[RAW_LENGTH_OFFSET], + p_slot->data.transmitted.power, + p_slot->data.transmitted.lqi); +#endif + break; + + case NTF_TYPE_TRANSMIT_FAILED: +#if NRF_802154_USE_RAW_API + nrf_802154_transmit_failed(p_slot->data.transmit_failed.p_frame, + p_slot->data.transmit_failed.error); +#else // NRF_802154_USE_RAW_API + nrf_802154_transmit_failed(p_slot->data.transmit_failed.p_frame + RAW_PAYLOAD_OFFSET, + p_slot->data.transmit_failed.error); +#endif + break; + + case NTF_TYPE_ENERGY_DETECTED: + nrf_802154_energy_detected(p_slot->data.energy_detected.result); + break; + + case NTF_TYPE_ENERGY_DETECTION_FAILED: + nrf_802154_energy_detection_failed( + p_slot->data.energy_detection_failed.error); + break; + + case NTF_TYPE_CCA: + nrf_802154_cca_done(p_slot->data.cca.result); + break; + + case NTF_TYPE_CCA_FAILED: + nrf_802154_cca_failed(p_slot->data.cca_failed.error); + break; + + default: + assert(false); + } + + ntf_queue_ptr_increment(&m_ntf_r_ptr); + } + } + + if (nrf_egu_event_check(SWI_EGU, TIMESLOT_EXIT_EVENT)) + { + nrf_raal_continuous_mode_exit(); + + nrf_egu_event_clear(SWI_EGU, TIMESLOT_EXIT_EVENT); + } + + if (nrf_egu_event_check(SWI_EGU, REQ_EVENT)) + { + nrf_egu_event_clear(SWI_EGU, REQ_EVENT); + + while (!req_queue_is_empty()) + { + nrf_802154_req_data_t * p_slot = &m_req_queue[m_req_r_ptr]; + bool in_crit_sect; + + in_crit_sect = nrf_802154_critical_section_enter(); + + switch (p_slot->type) + { + case REQ_TYPE_SLEEP: + *(p_slot->data.sleep.p_result) = in_crit_sect ? + nrf_802154_core_sleep(p_slot->data.sleep.term_lvl) : + false; + break; + + case REQ_TYPE_RECEIVE: + *(p_slot->data.receive.p_result) = in_crit_sect ? + nrf_802154_core_receive(p_slot->data.receive.term_lvl, + p_slot->data.receive.req_orig, + p_slot->data.receive.notif_func) : + false; + break; + + case REQ_TYPE_TRANSMIT: + *(p_slot->data.transmit.p_result) = in_crit_sect ? + nrf_802154_core_transmit(p_slot->data.transmit.term_lvl, + p_slot->data.transmit.req_orig, + p_slot->data.transmit.p_data, + p_slot->data.transmit.cca, + p_slot->data.transmit.notif_func) : + false; + break; + + case REQ_TYPE_ENERGY_DETECTION: + *(p_slot->data.energy_detection.p_result) = in_crit_sect ? + nrf_802154_core_energy_detection( + p_slot->data.energy_detection.term_lvl, + p_slot->data.energy_detection.time_us) : + false; + break; + + case REQ_TYPE_CCA: + *(p_slot->data.cca.p_result) = in_crit_sect ? + nrf_802154_core_cca(p_slot->data.cca.term_lvl) : + false; + break; + + case REQ_TYPE_CONTINUOUS_CARRIER: + *(p_slot->data.continuous_carrier.p_result) = in_crit_sect ? + nrf_802154_core_continuous_carrier( + p_slot->data.continuous_carrier.term_lvl) : + false; + break; + + case REQ_TYPE_BUFFER_FREE: + *(p_slot->data.buffer_free.p_result) = in_crit_sect ? + nrf_802154_core_notify_buffer_free( + p_slot->data.buffer_free.p_data): + false; + break; + + case REQ_TYPE_CHANNEL_UPDATE: + *(p_slot->data.channel_update.p_result) = in_crit_sect ? + nrf_802154_core_channel_update() : + false; + break; + + case REQ_TYPE_CCA_CFG_UPDATE: + *(p_slot->data.cca_cfg_update.p_result) = in_crit_sect ? + nrf_802154_core_cca_cfg_update() : + false; + break; + + default: + assert(false); + } + + if (in_crit_sect) + { + nrf_802154_critical_section_exit(); + } + + req_queue_ptr_increment(&m_req_r_ptr); + } + } +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h new file mode 100644 index 000000000..861dcb193 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h @@ -0,0 +1,222 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_SWI_H__ +#define NRF_802154_SWI_H__ + +#include +#include + +#include "nrf_802154.h" +#include "nrf_802154_const.h" +#include "nrf_802154_notification.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_802154_swi 802.15.4 driver SWI management + * @{ + * @ingroup nrf_802154 + * @brief SWI manager for 802.15.4 driver. + */ + +/** + * @brief Initialize SWI module. + */ +void nrf_802154_swi_init(void); + +/** + * @brief Notify next higher layer that a frame was received from SWI priority level. + * + * @param[in] p_data Array of bytes containing PSDU. First byte contains frame length, other contain the frame itself. + * @param[in] power RSSI measured during the frame reception. + * @param[in] lqi LQI indicating measured link quality during the frame reception. + */ +void nrf_802154_swi_notify_received(uint8_t * p_data, int8_t power, int8_t lqi); + +/** + * @brief Notify next higher layer that reception of a frame failed. + * + * @param[in] error An error code that indicates reason of the failure. + */ +void nrf_802154_swi_notify_receive_failed(nrf_802154_rx_error_t error); + +/** + * @brief Notify next higher layer that a frame was transmitted from SWI priority level. + * + * @param[in] p_frame Pointer to buffer containing PSDU of transmitted frame. + * @param[in] p_ack Pointer to buffer containing PSDU of ACK frame. NULL if ACK was not requested. + * @param[in] power RSSI of received frame or 0 if ACK was not requested. + * @param[in] lqi LQI of received frame of 0 if ACK was not requested. + */ +void nrf_802154_swi_notify_transmitted(const uint8_t * p_frame, + uint8_t * p_data, + int8_t power, + int8_t lqi); + +/** + * @brief Notify next higher layer that a frame was not transmitted from SWI priority level. + * + * @param[in] p_frame Pointer to buffer containing PSDU of the frame that failed transmit + * operation. + * @param[in] error Reason of the transmission failure. + */ +void nrf_802154_swi_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error); + +/** + * @brief Notify next higher layer that energy detection procedure ended from SWI priority level. + * + * @param[in] result Detected energy level. + */ +void nrf_802154_swi_notify_energy_detected(uint8_t result); + +/** + * @brief Notify next higher layer that energy detection procedure failed from SWI priority level. + * + * @param[in] error Reason of the energy detection failure. + */ +void nrf_802154_swi_notify_energy_detection_failed(nrf_802154_ed_error_t error); + +/** + * @brief Notify next higher layer that CCA procedure ended from SWI priority level. + * + * @param[in] channel_free If detected free channel. + */ +void nrf_802154_swi_notify_cca(bool channel_free); + +/** + * @brief Notify next higher layer that CCA procedure failed from SWI priority level. + * + * @param[in] error Reason of the CCA failure. + */ +void nrf_802154_swi_notify_cca_failed(nrf_802154_cca_error_t error); + +/** + * @brief Request discarding of the timeslot from SWI priority level. + * + * @note This function should be called through notification module to prevent calling it from arbiter context. + */ +void nrf_802154_swi_timeslot_exit(void); + +/** + * @brief Request entering sleep state from SWI priority. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[out] p_result Result of entering sleep state. + */ +void nrf_802154_swi_sleep(nrf_802154_term_t term_lvl, bool * p_result); + +/** + * @brief Request entering receive state from SWI priority. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + * @param[in] notify_function Function called to notify status of this procedure instead of + * default notification. If NULL default notification is used. + * @param[out] p_result Result of entering receive state. + */ +void nrf_802154_swi_receive(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + nrf_802154_notification_func_t notify_function, + bool * p_result); + +/** + * @biref Request entering transmit state from SWI priority. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] req_orig Module that originates this request. + * @param[in] p_data Pointer to PSDU of the frame to transmit. + * @param[in] cca If the driver should perform CCA procedure before transmission. + * @param[in] notify_function Function called to notify status of this procedure instead of + * default notification. If NULL default notification is used. + * @param[out] p_result Result of entering transmit state. + */ +void nrf_802154_swi_transmit(nrf_802154_term_t term_lvl, + req_originator_t req_orig, + const uint8_t * p_data, + bool cca, + nrf_802154_notification_func_t notify_function, + bool * p_result); + +/** + * @brief Request entering energy detection state from SWI priority. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] time_us Requested duration of energy detection procedure. + * @param[out] p_result Result of entering energy detection state. + */ +void nrf_802154_swi_energy_detection(nrf_802154_term_t term_lvl, + uint32_t time_us, + bool * p_result); + +/** + * @brief Request entering CCA state from SWI priority. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[out] p_result Result of entering CCA state. + */ +void nrf_802154_swi_cca(nrf_802154_term_t term_lvl, bool * p_result); + +/** + * @brief Request entering continuous carrier state from SWI priority. + * + * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[out] p_result Result of entering continuous carrier state. + */ +void nrf_802154_swi_continuous_carrier(nrf_802154_term_t term_lvl, bool * p_result); + +/** + * @brief Notify Core module that given buffer is not used anymore and can be freed. + * + * @param[in] p_data Pointer to the buffer to free. + */ +void nrf_802154_swi_buffer_free(uint8_t * p_data, bool * p_result); + +/** + * @brief Notify Core module that the next higher layer requested channel change. + */ +void nrf_802154_swi_channel_update(bool * p_result); + +/** + * @brief Notify Core module that the next higher layer requested CCA configuration change. + */ +void nrf_802154_swi_cca_cfg_update(bool * p_result); + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_802154_SWI_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_types.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_types.h new file mode 100644 index 000000000..0de181bd8 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_types.h @@ -0,0 +1,124 @@ +/* Copyright (c) 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_TYPES_H__ +#define NRF_802154_TYPES_H__ + +#include + +#include "hal/nrf_radio.h" + +/** + * @defgroup nrf_802154_types Types definitions used in the 802.15.4 driver. + * @{ + * @ingroup nrf_802154 + * @brief Definitions of types used in the 802.15.4 driver. + */ + +/** + * @brief States of the driver. + */ +typedef uint8_t nrf_802154_state_t; + +#define NRF_802154_STATE_INVALID 0x01 /**< Radio in an invalid state. */ +#define NRF_802154_STATE_SLEEP 0x02 /**< Radio in Sleep state. */ +#define NRF_802154_STATE_RECEIVE 0x03 /**< Radio in Receive state. */ +#define NRF_802154_STATE_TRANSMIT 0x04 /**< Radio in Transmit state. */ +#define NRF_802154_STATE_ENERGY_DETECTION 0x05 /**< Radio in Energy Detection state. */ +#define NRF_802154_STATE_CCA 0x06 /**< Radio in CCA state. */ +#define NRF_802154_STATE_CONTINUOUS_CARRIER 0x07 /**< Radio in Continuous Carrier state. */ + +/** + * @brief Errors reported during frame transmission. + */ +typedef uint8_t nrf_802154_tx_error_t; + +#define NRF_802154_TX_ERROR_NONE 0x00 /**< There is no transmit error. */ +#define NRF_802154_TX_ERROR_BUSY_CHANNEL 0x01 /**< CCA reported busy channel prior to transmission. */ +#define NRF_802154_TX_ERROR_INVALID_ACK 0x02 /**< Received ACK frame is other than expected. */ +#define NRF_802154_TX_ERROR_NO_MEM 0x03 /**< No receive buffer are available to receive an ACK. */ +#define NRF_802154_TX_ERROR_TIMESLOT_ENDED 0x04 /**< Radio timeslot ended during transmission procedure. */ +#define NRF_802154_TX_ERROR_NO_ACK 0x05 /**< ACK frame was not received during timeout period. */ +#define NRF_802154_TX_ERROR_ABORTED 0x06 /**< Procedure was aborted by other driver operation with FORCE priority. */ + +/** + * @brief Possible errors during frame reception. + */ +typedef uint8_t nrf_802154_rx_error_t; + +#define NRF_802154_RX_ERROR_NONE 0x00 /**< There is no receive error */ +#define NRF_802154_RX_ERROR_INVALID_FRAME 0x01 /**< Received a malformed frame */ +#define NRF_802154_RX_ERROR_INVALID_FCS 0x02 /**< Received a frame with invalid checksum. */ +#define NRF_802154_RX_ERROR_INVALID_DEST_ADDR 0x03 /**< Received a frame with mismatched destination address. */ +#define NRF_802154_RX_ERROR_RUNTIME 0x04 /**< A runtime error occured (e.g. CPU was hold for too long.) */ +#define NRF_802154_RX_ERROR_TIMESLOT_ENDED 0x05 /**< Radio timeslot ended during frame reception. */ +#define NRF_802154_RX_ERROR_ABORTED 0x06 /**< Procedure was aborted by other driver operation with FORCE priority. */ + +/** + * @brief Possible errors during energy detection. + */ +typedef uint8_t nrf_802154_ed_error_t; + +#define NRF_802154_ED_ERROR_ABORTED 0x01 /**< Procedure was aborted by other driver operation with FORCE priority. */ + +/** + * @brief Possible errors during CCA procedure. + */ +typedef uint8_t nrf_802154_cca_error_t; + +#define NRF_802154_CCA_ERROR_ABORTED 0x01 /**< Procedure was aborted by other driver operation with FORCE priority. */ + +/** + * @brief Termination level selected for particular request. + * + * Each request is able to terminate ongoing operation. This type selects which operation should be + * aborted by given request. + */ +typedef uint8_t nrf_802154_term_t; + +#define NRF_802154_TERM_NONE 0x00 /**< Request is skipped if another operation is ongoing. */ +#define NRF_802154_TERM_802154 0x01 /**< Request terminates ongoing 802.15.4 operation. */ + +/** + * @brief Structure for configuring CCA. + */ +typedef struct +{ + nrf_radio_cca_mode_t mode; /**< CCA mode. */ + uint8_t ed_threshold; /**< CCA Energy Busy Threshold. Not used in NRF_RADIO_CCA_MODE_CARRIER. */ + uint8_t corr_threshold; /**< CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. */ + uint8_t corr_limit; /**< Limit of occurrences above CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. */ +} nrf_802154_cca_cfg_t; + +/** + *@} + **/ + +#endif // NRF_802154_TYPES_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c deleted file mode 100644 index 6413919d8..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c +++ /dev/null @@ -1,478 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements the nrf 802.15.4 radio driver. - * - */ - -#include "nrf_drv_radio802154.h" - -#include -#include -#include -#include -#include - -#include "nrf_drv_radio802154_ack_pending_bit.h" -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_const.h" -#include "nrf_drv_radio802154_debug.h" -#include "nrf_drv_radio802154_fsm.h" -#include "nrf_drv_radio802154_notification.h" -#include "nrf_drv_radio802154_pib.h" -#include "nrf_drv_radio802154_priority_drop.h" -#include "nrf_drv_radio802154_request.h" -#include "nrf_drv_radio802154_revision.h" -#include "nrf_drv_radio802154_rx_buffer.h" -#include "hal/nrf_radio.h" -#include "platform/clock/nrf_drv_radio802154_clock.h" -#include "platform/timer/nrf_drv_radio802154_timer.h" -#include "raal/nrf_raal_api.h" - -#include - -#if ENABLE_FEM -#include "fem/nrf_fem_control_api.h" -#endif - -#define RAW_LENGTH_OFFSET 0 -#define RAW_PAYLOAD_OFFSET 1 - - -void nrf_drv_radio802154_channel_set(uint8_t channel) -{ - bool changed = nrf_drv_radio802154_pib_channel_get() != channel; - - nrf_drv_radio802154_pib_channel_set(channel); - - if (changed) - { - nrf_drv_radio802154_request_channel_update(); - } -} - -uint8_t nrf_drv_radio802154_channel_get(void) -{ - return nrf_drv_radio802154_pib_channel_get(); -} - -void nrf_drv_radio802154_tx_power_set(int8_t power) -{ - nrf_drv_radio802154_pib_tx_power_set(power); -} - -int8_t nrf_drv_radio802154_tx_power_get(void) -{ - return nrf_drv_radio802154_pib_tx_power_get(); -} - -void nrf_drv_radio802154_pan_id_set(const uint8_t * p_pan_id) -{ - nrf_drv_radio802154_pib_pan_id_set(p_pan_id); -} - -void nrf_drv_radio802154_extended_address_set(const uint8_t * p_extended_address) -{ - nrf_drv_radio802154_pib_extended_address_set(p_extended_address); -} - -void nrf_drv_radio802154_short_address_set(const uint8_t * p_short_address) -{ - nrf_drv_radio802154_pib_short_address_set(p_short_address); -} - -int8_t nrf_drv_radio802154_dbm_from_energy_level_calculate(uint8_t energy_level) -{ - // TODO: Correct this calculation after lab tests. - return -94 + energy_level; -} - -void nrf_drv_radio802154_init(void) -{ - nrf_drv_radio802154_ack_pending_bit_init(); - nrf_drv_radio802154_clock_init(); - nrf_drv_radio802154_debug_init(); - nrf_drv_radio802154_fsm_init(); - nrf_drv_radio802154_notification_init(); - nrf_drv_radio802154_pib_init(); - nrf_drv_radio802154_priority_drop_init(); - nrf_drv_radio802154_request_init(); - nrf_drv_radio802154_revision_init(); - nrf_drv_radio802154_rx_buffer_init(); - nrf_drv_radio802154_timer_init(); - nrf_raal_init(); -} - -void nrf_drv_radio802154_deinit(void) -{ - nrf_drv_radio802154_timer_deinit(); - nrf_drv_radio802154_fsm_deinit(); - nrf_drv_radio802154_clock_deinit(); -} - -#if !NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING -void nrf_drv_radio802154_irq_handler(void) -{ - nrf_drv_radio802154_fsm_irq_handler(); -} -#endif // !NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING - -#if ENABLE_FEM -void nrf_drv_radio802154_fem_control_cfg_set(const nrf_drv_radio802154_fem_control_cfg_t * p_cfg) -{ - nrf_fem_control_cfg_set(p_cfg); -} - -void nrf_drv_radio802154_fem_control_cfg_get(nrf_drv_radio802154_fem_control_cfg_t * p_cfg) -{ - nrf_fem_control_cfg_get(p_cfg); -} -#endif - -nrf_drv_radio802154_state_t nrf_drv_radio802154_state_get(void) -{ - switch (nrf_drv_radio802154_fsm_state_get()) - { - case RADIO_STATE_DISABLING: - case RADIO_STATE_SLEEP: - return NRF_DRV_RADIO802154_STATE_SLEEP; - - case RADIO_STATE_WAITING_TIMESLOT: - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - return NRF_DRV_RADIO802154_STATE_RECEIVE; - - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - return NRF_DRV_RADIO802154_STATE_TRANSMIT; - - case RADIO_STATE_ED: - return NRF_DRV_RADIO802154_STATE_ENERGY_DETECTION; - - case RADIO_STATE_CCA: - return NRF_DRV_RADIO802154_STATE_CCA; - - case RADIO_STATE_CONTINUOUS_CARRIER: - return NRF_DRV_RADIO802154_STATE_CONTINUOUS_CARRIER; - } - - return NRF_DRV_RADIO802154_STATE_INVALID; -} - -bool nrf_drv_radio802154_sleep(void) -{ - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_SLEEP); - - bool result = true; - - switch (nrf_drv_radio802154_fsm_state_get()) - { - case RADIO_STATE_DISABLING: - case RADIO_STATE_SLEEP: - break; - - case RADIO_STATE_WAITING_TIMESLOT: - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - result = nrf_drv_radio802154_request_sleep(); - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_SLEEP); - return result; -} - -void nrf_drv_radio802154_receive(void) -{ - bool result; - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RECEIVE); - - result = nrf_drv_radio802154_request_receive(); - assert(result == true); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RECEIVE); -} - -bool nrf_drv_radio802154_transmit_raw(const uint8_t * p_data, bool cca) -{ - bool result; - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT); - - result = nrf_drv_radio802154_request_transmit(p_data, cca); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_TRANSMIT); - return result; -} - -bool nrf_drv_radio802154_transmit(const uint8_t * p_data, uint8_t length, bool cca) -{ - static uint8_t tx_buffer[RAW_PAYLOAD_OFFSET + MAX_PACKET_SIZE]; - - assert(length <= MAX_PACKET_SIZE - FCS_SIZE); - - tx_buffer[RAW_LENGTH_OFFSET] = length + FCS_SIZE; - memcpy(&tx_buffer[RAW_PAYLOAD_OFFSET], p_data, length); - - return nrf_drv_radio802154_transmit_raw(tx_buffer, cca); -} - -bool nrf_drv_radio802154_energy_detection(uint32_t time_us) -{ - bool result; - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_ENERGY_DETECTION); - - result = nrf_drv_radio802154_request_energy_detection(time_us); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_ENERGY_DETECTION); - return result; -} - -bool nrf_drv_radio802154_cca(void) -{ - bool result; - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_CCA); - - result = nrf_drv_radio802154_request_cca(); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_CCA); - return result; -} - -bool nrf_drv_radio802154_continuous_carrier(void) -{ - bool result; - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_CONTINUOUS_CARRIER); - - result = nrf_drv_radio802154_request_continuous_carrier(); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_CONTINUOUS_CARRIER); - return result; -} - -void nrf_drv_radio802154_buffer_free_raw(uint8_t * p_data) -{ - rx_buffer_t * p_buffer = (rx_buffer_t *)p_data; - - assert(p_buffer->free == false); - - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); - - nrf_drv_radio802154_request_buffer_free(p_data); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); -} - -void nrf_drv_radio802154_buffer_free(uint8_t * p_data) -{ - nrf_drv_radio802154_buffer_free_raw(p_data - RAW_PAYLOAD_OFFSET); -} - -int8_t nrf_drv_radio802154_rssi_last_get(void) -{ - uint8_t minus_dbm = nrf_radio_rssi_sample_get(); - return - (int8_t)minus_dbm; -} - -int8_t nrf_drv_radio802154_rssi_corrected_get(int8_t rssi, int8_t temp) -{ - if (temp <= -30) - { - return rssi + 3; - } - - if (temp <= -10) - { - return rssi + 2; - } - - if (temp <= 10) - { - return rssi + 1; - } - - if (temp <= 30) - { - return rssi; - } - - if (temp <= 50) - { - return rssi - 1; - } - - if (temp <= 70) - { - return rssi - 2; - } - - return rssi - 3; -} - -bool nrf_drv_radio802154_promiscuous_get(void) -{ - return nrf_drv_radio802154_pib_promiscuous_get(); -} - -void nrf_drv_radio802154_promiscuous_set(bool enabled) -{ - nrf_drv_radio802154_pib_promiscuous_set(enabled); -} - -void nrf_drv_radio802154_auto_ack_set(bool enabled) -{ - nrf_drv_radio802154_pib_auto_ack_set(enabled); -} - -bool nrf_drv_radio802154_auto_ack_get(void) -{ - return nrf_drv_radio802154_pib_auto_ack_get(); -} - -void nrf_drv_radio802154_auto_pending_bit_set(bool enabled) -{ - nrf_drv_radio802154_ack_pending_bit_set(enabled); -} - -bool nrf_drv_radio802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended) -{ - return nrf_drv_radio802154_ack_pending_bit_for_addr_set(p_addr, extended); -} - -bool nrf_drv_radio802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended) -{ - return nrf_drv_radio802154_ack_pending_bit_for_addr_clear(p_addr, extended); -} - -void nrf_drv_radio802154_pending_bit_for_addr_reset(bool extended) -{ - nrf_drv_radio802154_ack_pending_bit_for_addr_reset(extended); -} - -void nrf_drv_radio802154_cca_cfg_set(const nrf_drv_radio802154_cca_cfg_t * p_cca_cfg) -{ - nrf_drv_radio802154_pib_cca_cfg_set(p_cca_cfg); - - nrf_drv_radio802154_request_cca_cfg_update(); -} - -void nrf_drv_radio802154_cca_cfg_get(nrf_drv_radio802154_cca_cfg_t * p_cca_cfg) -{ - nrf_drv_radio802154_pib_cca_cfg_get(p_cca_cfg); -} - -__WEAK void nrf_drv_radio802154_rx_started(void) -{ - // Intentionally empty -} - -__WEAK void nrf_drv_radio802154_tx_ack_started(void) -{ - // Intentionally empty -} - -__WEAK void nrf_drv_radio802154_received(uint8_t * p_data, uint8_t length, int8_t power, int8_t lqi) -{ - (void) length; - (void) power; - (void) lqi; - - nrf_drv_radio802154_buffer_free(p_data); -} - -__WEAK void nrf_drv_radio802154_received_raw(uint8_t * p_data, int8_t power, int8_t lqi) -{ - nrf_drv_radio802154_received(p_data + RAW_PAYLOAD_OFFSET, - p_data[RAW_LENGTH_OFFSET], - power, - lqi); -} - -__WEAK void nrf_drv_radio802154_receive_failed(nrf_drv_radio802154_rx_error_t error) -{ - (void) error; -} - -__WEAK void nrf_drv_radio802154_tx_started(void) -{ - // Intentionally empty -} - -__WEAK void nrf_drv_radio802154_rx_ack_started(void) -{ - // Intentionally empty -} - -__WEAK void nrf_drv_radio802154_transmitted(uint8_t * p_ack, uint8_t length, int8_t power, int8_t lqi) -{ - (void) length; - (void) power; - (void) lqi; - - if (p_ack != NULL) - { - nrf_drv_radio802154_buffer_free(p_ack); - } -} - -__WEAK void nrf_drv_radio802154_transmitted_raw(uint8_t * p_ack, int8_t power, int8_t lqi) -{ - nrf_drv_radio802154_transmitted(p_ack + RAW_PAYLOAD_OFFSET, - p_ack[RAW_LENGTH_OFFSET], - power, - lqi); -} - -__WEAK void nrf_drv_radio802154_transmit_failed(nrf_drv_radio802154_tx_error_t error) -{ - (void) error; -} - -__WEAK void nrf_drv_radio802154_energy_detected(uint8_t result) -{ - (void) result; -} - -__WEAK void nrf_drv_radio802154_cca_done(bool channel_free) -{ - (void) channel_free; -} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h deleted file mode 100644 index c3a56d5c9..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h +++ /dev/null @@ -1,768 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @brief This module contains generic 802.15.4 radio driver for nRF SoC devices. - * - */ - -#ifndef NRF_DRV_RADIO802154_H_ -#define NRF_DRV_RADIO802154_H_ - -#include -#include - -#include "nrf_drv_radio802154_config.h" -#include "hal/nrf_radio.h" - -#if ENABLE_FEM -#include "fem/nrf_fem_control_api.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief States of the driver. - */ -typedef uint8_t nrf_drv_radio802154_state_t; - -#define NRF_DRV_RADIO802154_STATE_INVALID 0x01 /**< Radio in an invalid state. */ -#define NRF_DRV_RADIO802154_STATE_SLEEP 0x02 /**< Radio in Sleep state. */ -#define NRF_DRV_RADIO802154_STATE_RECEIVE 0x03 /**< Radio in Receive state. */ -#define NRF_DRV_RADIO802154_STATE_TRANSMIT 0x04 /**< Radio in Transmit state. */ -#define NRF_DRV_RADIO802154_STATE_ENERGY_DETECTION 0x05 /**< Radio in Energy Detection state. */ -#define NRF_DRV_RADIO802154_STATE_CCA 0x06 /**< Radio in CCA state. */ -#define NRF_DRV_RADIO802154_STATE_CONTINUOUS_CARRIER 0x07 /**< Radio in Continuous Carrier state. */ - -/** - * @brief Errors reported during frame transmission. - */ -typedef uint8_t nrf_drv_radio802154_tx_error_t; - -#define NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL 0x01 /**< CCA reported busy channel prior to transmission. */ -#define NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK 0x02 /**< Received ACK frame is other than expected. */ -#define NRF_DRV_RADIO802154_TX_ERROR_NO_MEM 0x03 /**< No receive buffer are available to receive an ACK. */ -#define NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED 0x04 /**< Radio timeslot ended during transmission procedure. */ - -/** - * @brief Possible errors during frame reception. - */ -typedef uint8_t nrf_drv_radio802154_rx_error_t; - -#define NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME 0x01 /**< Received a malformed frame */ -#define NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS 0x02 /**< Received a frame with invalid checksum. */ -#define NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR 0x03 /**< Received a frame with mismatched destination address. */ -#define NRF_DRV_RADIO802154_RX_ERROR_RUNTIME 0x04 /**< A runtime error occured (e.g. CPU was hold for too long.) */ -#define NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED 0x05 /**< Radio timeslot ended during frame reception. */ - -/** - * @brief Structure for configuring CCA. - */ -typedef struct -{ - nrf_radio_cca_mode_t mode; /**< CCA mode. */ - uint8_t ed_threshold; /**< CCA Energy Busy Threshold. Not used in NRF_RADIO_CCA_MODE_CARRIER. */ - uint8_t corr_threshold; /**< CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. */ - uint8_t corr_limit; /**< Limit of occurrences above CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. */ -} nrf_drv_radio802154_cca_cfg_t; - -/** - * @brief Initialize 802.15.4 driver. - * - * @note This function shall be called once, before any other function from this module. - * - * Initialize radio peripheral to Sleep state. - */ -void nrf_drv_radio802154_init(void); - -/** - * @brief Deinitialize 802.15.4 driver. - * - * Deinitialize radio peripheral and reset it to the default state. - */ -void nrf_drv_radio802154_deinit(void); - -#if !NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING -/** - * @brief Handle interrupt request from the RADIO peripheral. - * - * @note When NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING is enabled the driver internally handles the - * RADIO IRQ and this function shall not be called. - * - * This function is intended to be used in Operating System environment when the OS handles IRQ - * and indirectly passes it to the driver or with RAAL implementation that indirectly passes radio - * IRQ handler to the driver (i.e. SoftDevice). - */ -void nrf_drv_radio802154_irq_handler(void); -#endif // !NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING - -/** - * @brief Set channel on which the radio shall operate right now. - * - * @param[in] channel Channel number (11-26). - */ -void nrf_drv_radio802154_channel_set(uint8_t channel); - -/** - * @brief Get channel on which the radio operates right now. - * - * @returns Channel number (11-26). - */ -uint8_t nrf_drv_radio802154_channel_get(void); - -/** - * @brief Set transmit power. - * - * @note The driver recalculates requested value to the nearest value accepted by the hardware. - * The calculation result is rounded up. - * - * @param[in] power Transmit power [dBm]. - */ -void nrf_drv_radio802154_tx_power_set(int8_t power); - -/** - * @brief Get currently set transmit power. - * - * @return Currently used transmit power [dBm]. - */ -int8_t nrf_drv_radio802154_tx_power_get(void); - -/** - * @section Front-end module management. - */ - -#if ENABLE_FEM - -typedef nrf_fem_control_cfg_t nrf_drv_radio802154_fem_control_cfg_t; - -#define NRF_DRV_RADIO802154_FEM_DEFAULT_SETTINGS \ - ((nrf_drv_radio802154_fem_control_cfg_t) { \ - .pa_cfg = { \ - .enable = 1, \ - .active_high = 1, \ - .gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \ - }, \ - .lna_cfg = { \ - .enable = 1, \ - .active_high = 1, \ - .gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \ - }, \ - .ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \ - .ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \ - .radio_ppi_grp = NRF_FEM_CONTROL_DEFAULT_TIMER_MATCH_PPI_GROUP, \ - .timer_ppi_grp = NRF_FEM_CONTROL_DEFAULT_RADIO_DISABLED_PPI_GROUP, \ - .gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_GPIOTE_CHANNEL, \ - }) - -/** - * @brief Set PA & LNA GPIO toggle configuration. - * - * @note This function shall not be called when radio is in use. - * - * @param[in] p_cfg A pointer to the PA & LNA GPIO toggle configuration. - * - */ -void nrf_drv_radio802154_fem_control_cfg_set(const nrf_drv_radio802154_fem_control_cfg_t * p_cfg); - -/** - * @brief Get PA & LNA GPIO toggle configuration. - * - * @param[out] p_cfg A pointer to the structure for the PA & LNA GPIO toggle configuration. - * - */ -void nrf_drv_radio802154_fem_control_cfg_get(nrf_drv_radio802154_fem_control_cfg_t * p_cfg); - -#endif // ENABLE_FEM - - -/** - * @section Setting addresses and Pan Id of this device. - */ - -/** - * @brief Set PAN Id used by this device. - * - * @param[in] p_pan_id Pointer to PAN Id (2 bytes, little-endian). - * - * This function makes copy of the PAN Id. - */ -void nrf_drv_radio802154_pan_id_set(const uint8_t *p_pan_id); - -/** - * @brief Set Extended Address of this device. - * - * @param[in] p_extended_address Pointer to extended address (8 bytes, little-endian). - * - * This function makes copy of the address. - */ -void nrf_drv_radio802154_extended_address_set(const uint8_t *p_extended_address); - -/** - * @brief Set Short Address of this device. - * - * @param[in] p_short_address Pointer to short address (2 bytes, little-endian). - * - * This function makes copy of the address. - */ -void nrf_drv_radio802154_short_address_set(const uint8_t *p_short_address); - -/** - * @brief Calculate dBm from energy level received during energy detection procedure. - * - * @param[in] energy_level Energy level passed by @sa nrf_drv_radio802154_energy_detected - * - * @return Result of energy detection procedure in dBm. - */ -int8_t nrf_drv_radio802154_dbm_from_energy_level_calculate(uint8_t energy_level); - - -/** - * @section Functions to request FSM transitions and check current state. - */ - -/** - * @brief Get current state of the radio. - */ -nrf_drv_radio802154_state_t nrf_drv_radio802154_state_get(void); - -/** - * @brief Change radio state to Sleep. - * - * @note This function should be called only if radio is in Receive state. - * - * Sleep state is the lowest power state. In this state radio cannot transmit or receive frames. - * - * @return true If the radio changes it's state to low power mode. - * @return false If the driver could not schedule changing state. - */ -bool nrf_drv_radio802154_sleep(void); - -/** - * @brief Change radio state to Receive. - * - * @note This function should be called in Sleep or Transmit state. - * - * In Receive state radio receives frames and automatically sends ACK frames when appropriate. - * Received frame is reported to higher layer by nrf_radio802154_received() call. - */ -void nrf_drv_radio802154_receive(void); - -/** - * @brief Change radio state to Transmit. - * - * @note This function should be called in Receive state. In other states transmission will not be - * scheduled. - * @note If the CPU was halted or interrupted during performing this function - * @sa nrf_drv_radio802154_transmitted() or @sa nrf_drv_radio802154_transmit_failed() may be - * called before nrf_drv_radio802154_transmit_raw() returns result. - * @note This function is implemented in zero-copy fashion. It passes given buffer pointer to - * the RADIO peripheral. - * - * In Transmit state radio transmits given frame. If requested it waits for ACK frame. - * Radio driver waits infinitely for ACK frame. Higher layer is responsible to call - * @sa nrf_radio802154_receive() after ACK timeout. - * Transmission result is reported to higher layer by @sa nrf_radio802154_transmitted() or - * @sa nrf_radio802154_transmit_failed() calls. - * - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC Header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <---------------------------- PHR -----------------------------------> | - * - * @param[in] p_data Pointer to array containing data to transmit. First byte should contain - * frame length (including PHR and FCS). Following bytes should contain data. - * CRC is computed automatically by radio hardware and because of that FCS - * field can contain any bytes. - * @param[in] cca If the driver should perform CCA procedure before transmission. - * - * @return true If the transmission procedure was scheduled. - * @return false If the driver could not schedule the transmission procedure. - */ -bool nrf_drv_radio802154_transmit_raw(const uint8_t *p_data, bool cca); - -/** - * @brief Change radio state to Transmit. - * - * @note This function should be called in Receive state. In other states transmission will not be - * scheduled. - * @note If the CPU was halted or interrupted during performing this function - * @sa nrf_drv_radio802154_transmitted() or @sa nrf_drv_radio802154_transmit_failed() may be - * called before nrf_drv_radio802154_transmit() returns result. - * @note This function makes copy of given buffer. There is an internal buffer maintained by this - * function. It is used to make a frame copy. To prevent unnecessary memory consumption and - * to perform zero-copy transmission @sa nrf_drv_radio802154_transmit_raw() function should - * be used instead of this. - * - * In Transmit state radio transmits given frame. If requested, it waits for ACK frame. - * Radio driver waits infinitely for ACK frame. Higher layer is responsible to call - * @sa nrf_radio802154_receive() after ACK timeout. - * Transmission result is reported to higher layer by @sa nrf_radio802154_transmitted() or - * @sa nrf_radio802154_transmit_failed() calls. - * - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC Header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <------------------ length -----------------------------> | - * - * @param[in] p_data Pointer to array containing payload of a data to transmit. The array - * should exclude PHR or FCS fields of 802.15.4 frame. - * @param[in] length Length of given frame. This value shall exclude PHR and FCS fields from - * the given frame (exact size of buffer pointed by @p p_data). - * @param[in] cca If the driver should perform CCA procedure before transmission. - * - * @return true If the transmission procedure was scheduled. - * @return false If the driver could not schedule the transmission procedure. - */ -bool nrf_drv_radio802154_transmit(const uint8_t * p_data, uint8_t length, bool cca); - -/** - * @brief Change radio state to Energy Detection. - * - * @note This function should be called in Receive state or Sleep state. - * @note If this function is called in Sleep state nrf_drv_radio802154_energy_detected() may be - * called before nrf_drv_radio802154_energy_detection() returns result. - * - * In Energy Detection state radio detects maximum energy for given time. Result of the detection - * is reported to the higher layer by @sa nrf_drv_radio802154_energy_detected() call. - * - * @param[in] time_us Duration of energy detection procedure. Given value is rounded up to - * multiplication of 8s (128 us). - * - * @return true If the energy detection procedure was scheduled. - * @return false If the driver could not schedule the energy detection procedure. - */ -bool nrf_drv_radio802154_energy_detection(uint32_t time_us); - -/** - * @brief Change radio state to CCA. - * @note This function should be called in Receive state or Sleep state. - * @note If this function is called in Sleep state nrf_drv_radio802154_cca_done() may be - * called before nrf_drv_radio802154_cca() returns result. - * - * In CCA state radio verifies if channel is clear. Result of verification is reported to the higher - * layer by @sa nrf_drv_radio802154_cca_done() call. - * - * @return true If the CCA procedure was scheduled. - * @return false If the driver could not schedule the CCA procedure. - */ -bool nrf_drv_radio802154_cca(void); - -/** - * @brief Change radio state to CONTINUOUS_CARRIER. - * @note This function should be called in Receive or Sleep state. - * @note When radio is emitting continuous carrier it blocks all transmissions on selected channel. - * This function should be called only during radio tests. It should not be used during - * normal device operation. - * @note This function works correctly only with a single-phy arbiter. It should not be used with - * any other arbiter. - * - * @return true If the continuous carrier procedure was scheduled. - * @return false If the driver could not schedule the continuous carrier procedure. - */ -bool nrf_drv_radio802154_continuous_carrier(void); - - -/** - * @section Calls to higher layer. - */ - -/** - * @brief Notify that receiving frame has started. - * - * @note It is possible the frame is dropped during receive procedure and - * @sa nrf_drv_radio802154_received won't be called. - * @note This function should be very short to prevent dropping frames by the driver. - */ -extern void nrf_drv_radio802154_rx_started(void); - -/** - * @brief Notify that transmitting ACK frame has started. - * - * @note This function should be very short to prevent dropping frames by the driver. - */ -extern void nrf_drv_radio802154_tx_ack_started(void); - -/** - * @brief Notify that frame was received. - * - * @note Buffer pointed by the p_data pointer is not modified by the radio driver (and can't - * be used to receive a frame) until nrf_drv_radio802154_buffer_free_raw() function is called. - * @note Buffer pointed by the p_data pointer may be modified by the function handler (and other - * modules) until @sa nrf_drv_radio802154_buffer_free_raw() function is called. - * @note The next higher layer should handle @sa nrf_drv_radio802154_received_raw() or @sa - * nrf_drv_radio802154_received() function. It should not handle both. - * - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC Header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <---------------------------- PHR -----------------------------------> | - * - * @param[in] p_data Pointer to the buffer containing received data (PHR + PSDU). First byte in - * the buffer is length of the frame (PHR) and following bytes is the frame - * itself (PSDU). Length byte (PHR) includes FCS. FCS is already verified by - * the hardware and may be modified by the hardware. - * @param[in] power RSSI of received frame. - * @param[in] lqi LQI of received frame. - */ -extern void nrf_drv_radio802154_received_raw(uint8_t * p_data, int8_t power, int8_t lqi); - -/** - * @brief Notify that frame was received. - * - * @note Buffer pointed by the p_data pointer is not modified by the radio driver (and can't - * be used to receive a frame) until nrf_drv_radio802154_buffer_free() function is called. - * @note Buffer pointed by the p_data pointer may be modified by the function handler (and other - * modules) until @sa nrf_drv_radio802154_buffer_free() function is called. - * @note The next higher layer should handle @sa nrf_drv_radio802154_received_raw() or @sa - * nrf_drv_radio802154_received() function. It should not handle both. - * - * p_data - * v - * +-----+-----------------------------------------------------------+------------+ - * | PHR | MAC Header and payload | FCS | - * +-----+-----------------------------------------------------------+------------+ - * | | - * | <------------------ length -----------------------------> | - * - * @param[in] p_data Pointer to the buffer containing payload of received frame (PSDU without FCS). - * @param[in] length Length of received payload. - * @param[in] power RSSI of received frame. - * @param[in] lqi LQI of received frame. - */ -extern void nrf_drv_radio802154_received(uint8_t * p_data, uint8_t length, int8_t power, int8_t lqi); - -/** - * @brief Notify that reception of a frame failed. - * - * @param[in] error An error code that indicates reason of the failure. - */ -extern void nrf_drv_radio802154_receive_failed(nrf_drv_radio802154_rx_error_t error); - -/** - * @brief Notify that transmitting frame has started. - * - * @note It is possible that transmit procedure is interrupted and - * @sa nrf_drv_radio802154_transmitted won't be called. - * @note This function should be very short to prevent dropping frames by the driver. - */ -extern void nrf_drv_radio802154_tx_started(void); - -/** - * @brief Notify that receiving ACK frame has started. - * - * @note It is possible that the frame being received is not expected ACK and - * @sa nrf_drv_radio802154_transmitted won't be called. - * @note This function should be very short to prevent dropping frames by the driver. - */ -extern void nrf_drv_radio802154_rx_ack_started(void); - -/** - * @brief Notify that frame was transmitted. - * - * @note If ACK was requested for transmitted frame this function is called after proper ACK is - * received. If ACK was not requested this function is called just after transmission is - * ended. - * @note Buffer pointed by the @p p_ack pointer is not modified by the radio driver (and can't - * be used to receive a frame) until @sa nrf_drv_radio802154_buffer_free_raw() function is - * called. - * @note Buffer pointed by the @p p_ack pointer may be modified by the function handler (and other - * modules) until @sa nrf_drv_radio802154_buffer_free_raw() function is called. - * @note The next higher layer should handle @sa nrf_drv_radio802154_transmitted_raw() or @sa - * nrf_drv_radio802154_transmitted() function. It should not handle both. - * - * @param[in] p_ack Pointer to received ACK buffer. Fist byte in the buffer is length of the - * frame (PHR) and following bytes are the ACK frame itself (PSDU). Length byte - * (PHR) includes FCS. FCS is already verified by the hardware and may be - * modified by the hardware. - * If ACK was not requested @p p_ack is set to NULL. - * @param[in] power RSSI of received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of received frame or 0 if ACK was not requested. - */ -extern void nrf_drv_radio802154_transmitted_raw(uint8_t * p_ack, int8_t power, int8_t lqi); - -/** - * @brief Notify that frame was transmitted. - * - * @note If ACK was requested for transmitted frame this function is called after proper ACK is - * received. If ACK was not requested this function is called just after transmission is - * ended. - * @note Buffer pointed by the @p p_ack pointer is not modified by the radio driver (and can't - * be used to receive a frame) until @sa nrf_drv_radio802154_buffer_free() function is - * called. - * @note Buffer pointed by the @p p_ack pointer may be modified by the function handler (and other - * modules) until @sa nrf_drv_radio802154_buffer_free() function is called. - * @note The next higher layer should handle @sa nrf_drv_radio802154_transmitted() or @sa - * nrf_drv_radio802154_transmitted() function. It should not handle both. - * - * @param[in] p_ack Pointer to buffer containing received ACK payload (PHR excluding FCS). - * If ACK was not requested @p p_ack is set to NULL. - * @param[in] length Length of received ACK payload. - * @param[in] power RSSI of received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of received frame or 0 if ACK was not requested. - */ -extern void nrf_drv_radio802154_transmitted(uint8_t * p_ack, uint8_t length, int8_t power, int8_t lqi); - - -/** - * @brief Notify that frame was not transmitted due to busy channel. - * - * This function is called if transmission procedure fails. - * - * @param[in] error Reason of the failure. - */ -extern void nrf_drv_radio802154_transmit_failed(nrf_drv_radio802154_tx_error_t error); - -/** - * @brief Notify that Energy Detection procedure finished. - * - * @note This function passes EnergyLevel defined in 802.15.4-2006 specification: - * 0x00 - 0xff proportional to detected energy level (dBm above receiver sensitivity). To - * calculate result in dBm use @sa nrf_drv_radio802154_dbm_from_energy_level_calculate(). - * - * @param[in] result Maximum energy detected during Energy Detection procedure. - */ -extern void nrf_drv_radio802154_energy_detected(uint8_t result); - -/** - * @brief Notify that CCA procedure has finished. - * - * @param[in] channel_free Indication if channel is free. - */ -extern void nrf_drv_radio802154_cca_done(bool channel_free); - - -/** - * @section Driver memory management - */ - -/** - * @brief Notify driver that buffer containing received frame is not used anymore. - * - * @note The buffer pointed by the @p p_data pointer may be modified by this function. - * @note Use this function with buffers provided by @sa nrf_drv_radio802154_received_raw() and - * @sa nrf_drv_radio802154_transmitted_raw(). To free buffers provided by @sa - * nrf_drv_radio802154_received() or @sa nrf_drv_radio802154_transmitted() use - * @sa nrf_drv_radio802154_buffer_free(). - * - * @param[in] p_data A pointer to the buffer containing received data that is no more needed by - * the higher layer. - */ -void nrf_drv_radio802154_buffer_free_raw(uint8_t * p_data); - -/** - * @brief Notify driver that buffer containing received frame is not used anymore. - * - * @note The buffer pointed by the @p p_data pointer may be modified by this function. - * @note Use this function with buffers provided by @sa nrf_drv_radio802154_received() and - * @sa nrf_drv_radio802154_transmitted(). To free buffers provided by @sa - * nrf_drv_radio802154_received_raw() or @sa nrf_drv_radio802154_transmitted_raw() use - * @sa nrf_drv_radio802154_buffer_free_raw(). - * - * @param[in] p_data A pointer to the buffer containing received data that is no more needed by - * the higher layer. - */ -void nrf_drv_radio802154_buffer_free(uint8_t * p_data); - - -/** - * @section RSSI measurement function. - */ - -/** - * @brief Begin RSSI measurement. - * - * @note This function should be called in Receive state. - * - * Begin RSSI measurement. The result will be available in 8 uS. The result can be read by - * nrf_radio802154_rssi_last_get() function. - */ -void nrf_drv_radio802154_rssi_measure(void); - -/** - * @brief Get result of last RSSI measurement. - * - * @returns RSSI measurement result [dBm]. - */ -int8_t nrf_drv_radio802154_rssi_last_get(void); - -/** - * @brief Adjust given RSSI measurement using a temperature correction factor. - * - * @param[in] rssi Measured RSSI value [dBm]. - * @param[in] temp Temperature value when RSSI sample took place [C]. - * - * @returns RSSI [dBm] corrected by a temperature factor (Errata 153). - */ -int8_t nrf_drv_radio802154_rssi_corrected_get(int8_t rssi, int8_t temp); - - -/** - * @section Promiscuous mode. - */ - -/** - * @brief Enable or disable promiscuous radio mode. - * - * @note Promiscuous mode is disabled by default. - * - * In promiscuous mode driver notifies higher layer that it received any frame (regardless - * frame type or destination address). - * In normal mode (not promiscuous) higher layer is not notified about ACK frames and frames with - * unknown type. Also frames with destination address not matching this device address are ignored. - * - * @param[in] enabled If promiscuous mode should be enabled. - */ -void nrf_drv_radio802154_promiscuous_set(bool enabled); - -/** - * @brief Check if radio is in promiscuous mode. - * - * @retval True Radio is in promiscuous mode. - * @retval False Radio is not in promiscuous mode. - */ -bool nrf_drv_radio802154_promiscuous_get(void); - - -/** - * @section Auto ACK management. - */ - -/** - * @brief Enable or disable auto ACK procedure. - * - * @note Auto ACK procedure is enabled by default. - * - * If auto ACK procedure is enabled the driver prepares and sends ACK frames automatically - * aTurnaroundTime (192 us) after proper frame is received. The driver sets sequence number in - * the ACK frame and pending bit according to auto pending bit feature settings. When auto ACK - * procedure is enabled the driver notifies the next higher layer about received frame after ACK - * frame is transmitted. - * If auto ACK procedure is disabled the driver does not transmit ACK frames. It notifies the next - * higher layer about received frame when a frame is received. In this mode the next higher layer - * is responsible for sending ACK frame. ACK frames should be sent using - * nrf_drv_radio802154_transmit() function. - * - * @param[in] enabled If auto ACK procedure should be enabled. - */ -void nrf_drv_radio802154_auto_ack_set(bool enabled); - -/** - * @brief Check if auto ACK procedure is enabled. - * - * @retval True Auto ACK procedure is enabled. - * @retval False Auto ACK procedure is disabled. - */ -bool nrf_drv_radio802154_auto_ack_get(void); - -/** - * @brief Enable or disable setting pending bit in automatically transmitted ACK frames. - * - * @note Setting pending bit in automatically transmitted ACK frames is enabled by default. - * - * Radio driver automatically sends ACK frames in response to unicast frames destined to this node. - * Pending bit in ACK frame can be set or cleared regarding data in pending buffer destined to ACK - * destination. - * - * If setting pending bit in ACK frames is disabled, pending bit in every ACK frame is set. - * If setting pending bit in ACK frames is enabled, radio driver checks if there is data - * in pending buffer destined to ACK destination. If there is no such data, pending bit is cleared. - * - * @note It is possible that if there is a lot of supported peers radio driver cannot verify - * if there is pending data before ACK is sent. In this case pending bit is set. - * - * @param[in] enabled If setting pending bit in ACK frames is enabled. - */ -void nrf_drv_radio802154_auto_pending_bit_set(bool enabled); - -/** - * @brief Add address of peer node for which there is pending data in the buffer. - * - * @note This function makes a copy of given address. - * - * @param[in] p_addr Array of bytes containing address of the node (little-endian). - * @param[in] extended If given address is Extended MAC Address or Short MAC Address. - * - * @retval True Address successfully added to the list. - * @retval False There is not enough memory to store this address in the list. - */ -bool nrf_drv_radio802154_pending_bit_for_addr_set(const uint8_t *p_addr, bool extended); - -/** - * @brief Remove address of peer node for which there is no more pending data in the buffer. - * - * @param[in] p_addr Array of bytes containing address of the node (little-endian). - * @param[in] extended If given address is Extended MAC Address or Short MAC Address. - * - * @retval True Address successfully removed from the list. - * @retval False There is no such address in the list. - */ -bool nrf_drv_radio802154_pending_bit_for_addr_clear(const uint8_t *p_addr, bool extended); - -/** - * @brief Remove all addresses of given type from pending bit list. - * - * @param[in] extended If function should remove all Exnteded MAC Adresses of all Short Addresses. - */ -void nrf_drv_radio802154_pending_bit_for_addr_reset(bool extended); - -/** - * @section CCA configuration management. - */ - -/** - * @brief Configure radio CCA mode and threshold. - * - * @param[in] p_cca_cfg A pointer to the CCA configuration structure. Only fields relevant to selected mode are updated. - */ -void nrf_drv_radio802154_cca_cfg_set(const nrf_drv_radio802154_cca_cfg_t * p_cca_cfg); - -/** - * @brief Get current radio CCA configuration - * - * @param[out] p_cca_cfg A pointer to the structure for current CCA configuration. - */ -void nrf_drv_radio802154_cca_cfg_get(nrf_drv_radio802154_cca_cfg_t * p_cca_cfg); - -#ifdef __cplusplus -} -#endif - -#endif /* NRF_DRV_RADIO802154_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.c deleted file mode 100644 index c3ef25478..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_ack_pending_bit.c +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements procedures to set pending bit in nRF 802.15.4 radio driver. - * - */ - -#include "nrf_drv_radio802154_ack_pending_bit.h" - -#include -#include -#include - -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_const.h" - -#include "hal/nrf_radio.h" - -/// Maximum number of Short Addresses of nodes for which there is pending data in buffer. -#define NUM_PENDING_SHORT_ADDRESSES NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES -/// Maximum number of Extended Addresses of nodes for which there is pending data in buffer. -#define NUM_PENDING_EXTENDED_ADDRESSES NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES -/// Value used to mark Short Address as unused. -#define UNUSED_PENDING_SHORT_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff}) -/// Value used to mark Extended Address as unused. -#define UNUSED_PENDING_EXTENDED_ADDRESS ((uint8_t [EXTENDED_ADDRESS_SIZE]) {0}) - -/// If pending bit in ACK frame should be set to valid or default value. -static bool m_setting_pending_bit_enabled; -/// Array of Short Addresses of nodes for which there is pending data in the buffer. -static uint8_t m_pending_short[NUM_PENDING_SHORT_ADDRESSES][SHORT_ADDRESS_SIZE]; -/// Array of Extended Addresses of nodes for which there is pending data in the buffer. -static uint8_t m_pending_extended[NUM_PENDING_EXTENDED_ADDRESSES][EXTENDED_ADDRESS_SIZE]; - -void nrf_drv_radio802154_ack_pending_bit_init(void) -{ - memset(m_pending_extended, 0, sizeof(m_pending_extended)); - memset(m_pending_short, 0xff, sizeof(m_pending_short)); - m_setting_pending_bit_enabled = true; -} - -void nrf_drv_radio802154_ack_pending_bit_set(bool enabled) -{ - m_setting_pending_bit_enabled = enabled; -} - -bool nrf_drv_radio802154_ack_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended) -{ - uint8_t * p_empty_slot = NULL; - - if (extended) - { - for (uint32_t i = 0; i < NUM_PENDING_EXTENDED_ADDRESSES; i++) - { - if (0 == memcmp(m_pending_extended[i], p_addr, sizeof(m_pending_extended[i]))) - { - return true; - } - - if (0 == memcmp(m_pending_extended[i], UNUSED_PENDING_EXTENDED_ADDRESS, sizeof(m_pending_extended[i]))) - { - p_empty_slot = m_pending_extended[i]; - } - } - - if (p_empty_slot != NULL) - { - memcpy(p_empty_slot, p_addr, EXTENDED_ADDRESS_SIZE); - return true; - } - } - else - { - for (uint32_t i = 0; i < NUM_PENDING_SHORT_ADDRESSES; i++) - { - if (0 == memcmp(m_pending_short[i], p_addr, sizeof(m_pending_short[i]))) - { - return true; - } - - if (0 == memcmp(m_pending_short[i], UNUSED_PENDING_SHORT_ADDRESS, sizeof(m_pending_short[i]))) - { - p_empty_slot = m_pending_short[i]; - } - } - - if (p_empty_slot != NULL) - { - memcpy(p_empty_slot, p_addr, SHORT_ADDRESS_SIZE); - return true; - } - } - - return false; -} - -bool nrf_drv_radio802154_ack_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended) -{ - bool result = false; - - if (extended) - { - for (uint32_t i = 0; i < NUM_PENDING_EXTENDED_ADDRESSES; i++) - { - if (0 == memcmp(m_pending_extended[i], p_addr, sizeof(m_pending_extended[i]))) - { - memset(m_pending_extended[i], 0, sizeof(m_pending_extended[i])); - result = true; - } - } - } - else - { - for (uint32_t i = 0; i < NUM_PENDING_SHORT_ADDRESSES; i++) - { - if (0 == memcmp(m_pending_short[i], p_addr, sizeof(m_pending_short[i]))) - { - memset(m_pending_short[i], 0xff, sizeof(m_pending_short[i])); - result = true; - } - } - } - - return result; -} - -void nrf_drv_radio802154_ack_pending_bit_for_addr_reset(bool extended) -{ - if (extended) - { - memset(m_pending_extended, 0, sizeof(m_pending_extended)); - } - else - { - memset(m_pending_short, 0xff, sizeof(m_pending_short)); - } -} - -bool nrf_drv_radio802154_ack_pending_bit_should_be_set(const uint8_t * p_psdu) -{ - const uint8_t * p_src_addr; - uint32_t i; - - // If automatic setting of pending bit in ACK frames is disabled the pending bit is always set. - if (!m_setting_pending_bit_enabled) - { - return true; - } - - switch (p_psdu[DEST_ADDR_TYPE_OFFSET] & DEST_ADDR_TYPE_MASK) - { - case DEST_ADDR_TYPE_SHORT: - p_src_addr = &p_psdu[SRC_ADDR_OFFSET_SHORT_DST]; - break; - - case DEST_ADDR_TYPE_EXTENDED: - p_src_addr = &p_psdu[SRC_ADDR_OFFSET_EXTENDED_DST]; - break; - - default: - return true; - } - - if (0 == (p_psdu[PAN_ID_COMPR_OFFSET] & PAN_ID_COMPR_MASK)) - { - p_src_addr += PAN_ID_SIZE; - } - - switch (p_psdu[SRC_ADDR_TYPE_OFFSET] & SRC_ADDR_TYPE_MASK) - { - case SRC_ADDR_TYPE_SHORT: - for (i = 0; i < NUM_PENDING_SHORT_ADDRESSES; i++) - { - if (nrf_radio_state_get() != NRF_RADIO_STATE_TX_RU) - { - break; - } - - if (0 == memcmp(p_src_addr, m_pending_short[i], sizeof(m_pending_short[i]))) - { - return true; - } - } - - break; - - case SRC_ADDR_TYPE_EXTENDED: - for (i = 0; i < NUM_PENDING_EXTENDED_ADDRESSES; i++) - { - if (nrf_radio_state_get() != NRF_RADIO_STATE_TX_RU) - { - break; - } - - if (0 == memcmp(p_src_addr, m_pending_extended[i], sizeof(m_pending_extended[i]))) - { - return true; - } - } - - break; - - default: - return true; - } - - return false; -} - diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h deleted file mode 100644 index ea6542a40..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NRF_DRIVER_RADIO802154_CONFIG_H__ -#define NRF_DRIVER_RADIO802154_CONFIG_H__ - -#ifdef NRF_DRV_RADIO802154_PROJECT_CONFIG -#include NRF_DRV_RADIO802154_PROJECT_CONFIG -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup nrf_driver_radio802154_config 802.15.4 driver configuration - * @{ - * @ingroup nrf_driver_radio802154 - * @brief Configuration of 802.15.4 radio driver for nRF SoC. - */ - -/******************************************************************************* - * @section Radio Driver Configuration. - ******************************************************************************/ - -/** - * @def NRF_DRV_RADIO802154_CCA_MODE - * - * CCA Mode used by the driver. - * - */ -#ifndef NRF_DRV_RADIO802154_CCA_MODE_DEFAULT -#define NRF_DRV_RADIO802154_CCA_MODE_DEFAULT NRF_RADIO_CCA_MODE_ED -#endif - -/** - * @def NRF_DRV_RADIO802154_CCA_ED_THRESHOLD - * - * Energy Detection Threshold used in CCA procedure. - * - */ -#ifndef NRF_DRV_RADIO802154_CCA_ED_THRESHOLD_DEFAULT -#define NRF_DRV_RADIO802154_CCA_ED_THRESHOLD_DEFAULT 0x2D -#endif - -/** - * @def NRF_DRV_RADIO802154_CCA_CORR_THRESHOLD - * - * Correlator Threshold used in CCA procedure. - * - */ -#ifndef NRF_DRV_RADIO802154_CCA_CORR_THRESHOLD_DEFAULT -#define NRF_DRV_RADIO802154_CCA_CORR_THRESHOLD_DEFAULT 0x2D -#endif - -/** - * @def NRF_DRV_RADIO802154_CCA_CORR_LIMIT - * - * Correlator limit used in CCA procedure. - * - */ -#ifndef NRF_DRV_RADIO802154_CCA_CORR_LIMIT_DEFAULT -#define NRF_DRV_RADIO802154_CCA_CORR_LIMIT_DEFAULT 0x02 -#endif - -/** - * @def NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING - * - * If the driver should internally handle the RADIO IRQ. - * In case the driver is used in an OS the RADIO IRQ may be handled by the OS and passed to - * the driver @sa nrf_drv_radio802154_irq_handler(). In this case internal handling should be - * disabled. - */ - -#ifndef NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING - -#if RAAL_SOFTDEVICE -#define NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING 0 -#else // RAAL_SOFTDEVICE -#define NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING 1 -#endif // RAAL_SOFTDEVICE - -#endif // NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING - -/** - * @def NRF_DRV_RADIO802154_IRQ_PRIORITY - * - * Interrupt priority for RADIO peripheral. - * It is recommended to keep IRQ priority high (low number) to prevent losing frames due to - * preemption. - * - */ -#ifndef NRF_DRV_RADIO802154_IRQ_PRIORITY -#define NRF_DRV_RADIO802154_IRQ_PRIORITY 0 -#endif - -/** - * @def NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES - * - * Number of slots containing short addresses of nodes for which pending data is stored. - * - */ -#ifndef NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES -#define NRF_DRV_RADIO802154_PENDING_SHORT_ADDRESSES 10 -#endif - -/** - * @def NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES - * - * Number of slots containing extended addresses of nodes for which pending data is stored. - * - */ -#ifndef NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES -#define NRF_DRV_RADIO802154_PENDING_EXTENDED_ADDRESSES 10 -#endif - -/** - * @def NRF_DRV_RADIO802154_RX_BUFFERS - * - * Number of buffers in receive queue. - * - */ -#ifndef NRF_DRV_RADIO802154_RX_BUFFERS -#define NRF_DRV_RADIO802154_RX_BUFFERS 16 -#endif - -/** - * @def NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN - * - * RADIO peripheral can start transmission using short CCAIDLE->TXEN or interrupt handler. - * If NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN is set to 0 interrupt handler is used, otherwise - * short is used. - * - */ -#ifndef NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN -#define NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN 1 -#endif - -/** - * @def NRF_DRV_RADIO802154_NOTIFICATION_SWI_PRIORITY - * - * Priority of software interrupt used to call notification from 802.15.4 driver. - * - */ -#ifndef NRF_DRV_RADIO802154_NOTIFICATION_SWI_PRIORITY -#define NRF_DRV_RADIO802154_NOTIFICATION_SWI_PRIORITY 5 -#endif - -/** - * @def NRF_DRV_RADIO802154_CLOCK_IRQ_PRIORITY - * - * Priority of clock interrupt used in standalone clock driver implementation. - * - * @note This configuration is only applicable for Clock Abstraction Layer implementation - * in nrf_drv_radio802154_clock_nodrv.c. - * - */ -#ifndef NRF_DRV_RADIO802154_CLOCK_IRQ_PRIORITY -#define NRF_DRV_RADIO802154_CLOCK_IRQ_PRIORITY 10 -#endif - -/** - *@} - **/ - -#ifdef __cplusplus -} -#endif - -#endif // NRF_DRIVER_RADIO802154_CONFIG_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.c deleted file mode 100644 index 63e449a7d..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_critical_section.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements critical sections used with requests by 802.15.4 driver. - * - */ - -#include "nrf_drv_radio802154_critical_section.h" - -#include -#include - -#include "nrf_drv_radio802154_debug.h" -#include "nrf_drv_radio802154_fsm.h" -#include "hal/nrf_radio.h" -#include "platform/timer/nrf_drv_radio802154_timer.h" -#include "raal/nrf_raal_api.h" - -#include - -#if RAAL_SOFTDEVICE -// When Softdevice is selected as arbiter critical sections should not be nested. -#define PREVENT_NESTED_CRIT_SECTIONS 1 -#endif // RAAL_SOFTDEVICE - -#if PREVENT_NESTED_CRIT_SECTIONS -/// Flag indicating if the driver entered critical section. -static volatile bool m_in_critical_section; -#endif // PREVENT_NESTED_CRIT_SECTIONS - -void nrf_drv_radio802154_critical_section_enter(void) -{ - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_CRIT_SECT_ENTER); - radio_state_t state; - -#if PREVENT_NESTED_CRIT_SECTIONS - __disable_irq(); - __DSB(); - __ISB(); - - assert(!m_in_critical_section); - m_in_critical_section = true; -#endif // PREVENT_NESTED_CRIT_SECTIONS - - nrf_drv_radio802154_timer_critical_section_enter(); - nrf_raal_critical_section_enter(); - - state = nrf_drv_radio802154_fsm_state_get(); - - if (state != RADIO_STATE_WAITING_TIMESLOT && - state != RADIO_STATE_SLEEP) - { - NVIC_DisableIRQ(RADIO_IRQn); -#if !RAAL_SOFTDEVICE - __DSB(); - __ISB(); -#endif // !RAAL_SOFTDEVICE - } - -#if PREVENT_NESTED_CRIT_SECTIONS - __enable_irq(); -#endif // PREVENT_NESTED_CRIT_SECTIONS - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_CRIT_SECT_ENTER); -} - -void nrf_drv_radio802154_critical_section_exit(void) -{ - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_CRIT_SECT_EXIT); - -#if PREVENT_NESTED_CRIT_SECTIONS - assert(m_in_critical_section); - m_in_critical_section = false; -#endif // PREVENT_NESTED_CRIT_SECTIONS - - radio_state_t state; - - // RAAL critical section shall be exited before RADIO IRQ handler is enabled. In other case - // RADIO IRQ handler may be called out of timeslot. - nrf_raal_critical_section_exit(); - - state = nrf_drv_radio802154_fsm_state_get(); - - if (state != RADIO_STATE_WAITING_TIMESLOT && - state != RADIO_STATE_SLEEP) - { - NVIC_EnableIRQ(RADIO_IRQn); - } - - nrf_drv_radio802154_timer_critical_section_exit(); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_CRIT_SECT_EXIT); -} - diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c deleted file mode 100644 index 21592d8ca..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c +++ /dev/null @@ -1,2281 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements Finite State Machine of nRF 802.15.4 radio driver. - * - */ - -#include "nrf_drv_radio802154_fsm.h" - -#include -#include -#include -#include - -#include "nrf_drv_radio802154.h" -#include "nrf_drv_radio802154_ack_pending_bit.h" -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_const.h" -#include "nrf_drv_radio802154_debug.h" -#include "nrf_drv_radio802154_notification.h" -#include "nrf_drv_radio802154_pib.h" -#include "nrf_drv_radio802154_priority_drop.h" -#include "nrf_drv_radio802154_procedures_duration.h" -#include "nrf_drv_radio802154_revision.h" -#include "nrf_drv_radio802154_rx_buffer.h" -#include "fem/nrf_fem_control_api.h" -#include "hal/nrf_radio.h" -#include "raal/nrf_raal_api.h" - - -/// Workaround for missing PHYEND event in older chip revision. -static inline uint32_t short_phyend_disable_mask_get(void) -{ - if (nrf_drv_radio802154_revision_has_phyend_event()) - { - return NRF_RADIO_SHORT_PHYEND_DISABLE_MASK; - } - - return NRF_RADIO_SHORT_END_DISABLE_MASK; -} - -/// Value set to SHORTS register when no shorts should be enabled. -#define SHORTS_IDLE 0 -/// Value set to SHORTS register when receiver is waiting for incoming frame. -#define SHORTS_RX_INITIAL (NRF_RADIO_SHORT_END_DISABLE_MASK | NRF_RADIO_SHORT_DISABLED_TXEN_MASK | \ - NRF_RADIO_SHORT_FRAMESTART_BCSTART_MASK) - -/// Value set to SHORTS register when receiver started receiving a frame. -#define SHORTS_RX_FOLLOWING (short_phyend_disable_mask_get() | NRF_RADIO_SHORT_READY_START_MASK | \ - NRF_RADIO_SHORT_FRAMESTART_BCSTART_MASK) -/// Value set to SHORTS register when received frame should be acknowledged. -#define SHORTS_TX_ACK (short_phyend_disable_mask_get()) -#if NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN -/// Value set to SHORTS register during transmission of a frame -#define SHORTS_TX_FRAME (short_phyend_disable_mask_get() | NRF_RADIO_SHORT_READY_START_MASK | \ - NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK) -#else -/// Value set to SHORTS register during transmission of a frame -#define SHORTS_TX_FRAME (short_phyend_disable_mask_get() | NRF_RADIO_SHORT_READY_START_MASK) -#endif - -/// Delay before sending ACK (12sym = 192uS) -#define TIFS_ACK_US 192 -/// Delay before first check of received frame: 16 bits is MAC Frame Control field. -#define BCC_INIT (2 * 8) -/// Delay before second check of received frame if destination address is short. -#define BCC_SHORT_ADDR ((DEST_ADDR_OFFSET + SHORT_ADDRESS_SIZE) * 8) -/// Delay before second check of received frame if destination address is extended. -#define BCC_EXTENDED_ADDR ((DEST_ADDR_OFFSET + EXTENDED_ADDRESS_SIZE) * 8) - -/// Duration of single iteration of Energy Detection procedure -#define ED_ITER_DURATION 128U -/// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations] -#define ED_ITERS_OVERHEAD 2U - -#define CRC_LENGTH 2 ///< Length of CRC in 802.15.4 frames [bytes] -#define CRC_POLYNOMIAL 0x011021 ///< Polynomial used for CRC calculation in 802.15.4 frames - -#define MHMU_MASK 0xff000700 ///< Mask of known bytes in ACK packet -#define MHMU_PATTERN 0x00000200 ///< Values of known bytes in ACK packet -#define MHMU_PATTERN_DSN_OFFSET 24 ///< Offset of DSN in MHMU_PATTER [bits] - -/** Get LQI of given received packet. If CRC is calculated by hardware LQI is included instead of CRC - * in the frame. Length is stored in byte with index 0; CRC is 2 last bytes. - */ -#define RX_FRAME_LQI(psdu) ((psdu)[(psdu)[0] - 1]) - -#if NRF_DRV_RADIO802154_RX_BUFFERS > 1 -/// Pointer to currently used receive buffer. -static rx_buffer_t * mp_current_rx_buffer; -#else -/// If there is only one buffer use const pointer to the receive buffer. -static rx_buffer_t * const mp_current_rx_buffer = &nrf_drv_radio802154_rx_buffers[0]; -#endif - -static uint8_t m_ack_psdu[ACK_LENGTH + 1]; ///< Ack frame buffer. -static const uint8_t * mp_tx_data; ///< Pointer to data to transmit. -static uint32_t m_ed_time_left; ///< Remaining time of current energy detection procedure [us]. -static uint8_t m_ed_result; ///< Result of current energy detection procedure. - -static volatile radio_state_t m_state = RADIO_STATE_SLEEP; ///< State of the radio driver - -typedef struct -{ - bool prevent_ack :1; ///< If frame being received is not destined to this node (promiscuous mode). -} nrf_radio802154_flags_t; -static nrf_radio802154_flags_t m_flags; ///< Flags used to store current driver state. - -static volatile uint8_t m_mutex; ///< Mutex preventing race condition. - - -/*************************************************************************************************** - * @section Mutex - **************************************************************************************************/ - -/// Lock mutex to prevent race conditions. -static bool mutex_lock(void) -{ - do - { - volatile uint8_t mutex_value = __LDREXB(&m_mutex); - - if (mutex_value) - { - return false; - } - } - while (__STREXB(1, &m_mutex)); - - __DMB(); - - // Driver may be in WAITING_TIMESLOT state if timeslot ended during mutex locking. - assert(m_state == RADIO_STATE_WAITING_RX_FRAME || - m_state == RADIO_STATE_SLEEP || - m_state == RADIO_STATE_WAITING_TIMESLOT); - - nrf_drv_radio802154_log(EVENT_MUTEX_LOCK, 0); - - return true; -} - -/// Unlock mutex. -static void mutex_unlock(void) -{ - assert(m_state == RADIO_STATE_SLEEP || - m_state == RADIO_STATE_WAITING_RX_FRAME); - - nrf_drv_radio802154_log(EVENT_MUTEX_UNLOCK, 0); - - __DMB(); - m_mutex = 0; -} - - -/*************************************************************************************************** - * @section FSM common operations - **************************************************************************************************/ - -/** Set driver state. - * - * @param[in] state Driver state to set. - */ -static inline void state_set(radio_state_t state) -{ - m_state = state; - - if (m_state == RADIO_STATE_SLEEP) - { - nrf_fem_control_deactivate(); - } - else - { - nrf_fem_control_activate(); - } - - nrf_drv_radio802154_log(EVENT_SET_STATE, (uint32_t)state); -} - -/// Common procedure when the driver enters SLEEP state. -static inline void sleep_start(void) -{ - state_set(RADIO_STATE_SLEEP); - nrf_drv_radio802154_priority_drop_timeslot_exit(); - mutex_unlock(); -} - -/// Start receiver to wait for frames. -static inline void rx_start(void) -{ - nrf_radio_packet_ptr_set(mp_current_rx_buffer->psdu); - nrf_radio_task_trigger(NRF_RADIO_TASK_START); -} - -/// Start receiver to wait for frame that can be acknowledged. -static inline void rx_frame_start(void) -{ - rx_start(); - - // Just after starting receiving to receive buffer set packet pointer to ACK frame that can be - // sent automatically. - nrf_radio_packet_ptr_set(m_ack_psdu); -} - -/** Get result of last RSSI measurement. - * - * @returns Result of last RSSI measurement [dBm]. - */ -static inline int8_t rssi_last_measurement_get(void) -{ - return -((int8_t)nrf_radio_rssi_sample_get()); -} - -/// Notify MAC layer that a frame was received. -static inline void received_frame_notify(void) -{ - mp_current_rx_buffer->free = false; - nrf_drv_radio802154_notify_received(mp_current_rx_buffer->psdu, // data - rssi_last_measurement_get(), // rssi - RX_FRAME_LQI(mp_current_rx_buffer->psdu)); // lqi -} - -/** Set currently used rx buffer to given address. - * - * @param[in] p_rx_buffer Pointer to receive buffer that should be used now. - */ -static inline void rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer) -{ -#if NRF_DRV_RADIO802154_RX_BUFFERS > 1 - mp_current_rx_buffer = p_rx_buffer; -#else - (void) p_rx_buffer; -#endif -} - -/** Update CCA configuration in RADIO registers. */ -static void cca_configuration_update(void) -{ - nrf_drv_radio802154_cca_cfg_t cca_cfg; - nrf_drv_radio802154_pib_cca_cfg_get(&cca_cfg); - nrf_radio_cca_mode_set(cca_cfg.mode); - nrf_radio_cca_ed_threshold_set(cca_cfg.ed_threshold); - nrf_radio_cca_corr_threshold_set(cca_cfg.corr_threshold); - nrf_radio_cca_corr_counter_set(cca_cfg.corr_limit); -} - -/** Trigger RX task. */ -static void rx_enable(void) -{ - nrf_fem_control_time_latch(); - nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); - nrf_fem_control_lna_set(false); -} - -/** Trigger TX task. */ -static void tx_enable(void) -{ - nrf_fem_control_time_latch(); - nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN); - nrf_fem_control_pa_set(false, false); -} - -/*************************************************************************************************** - * @section Radio parameters calculators - **************************************************************************************************/ - -/** Set radio channel - * - * @param[in] channel Channel number to set (11-26). - */ -static void channel_set(uint8_t channel) -{ - assert(channel >= 11 && channel <= 26); - - nrf_radio_frequency_set(5 + (5 * (channel - 11))); -} - - -/*************************************************************************************************** - * @section Shorts management - **************************************************************************************************/ - -/// Disable peripheral shorts. -static inline void shorts_disable(void) -{ - nrf_radio_shorts_set(SHORTS_IDLE); - nrf_radio_ifs_set(0); - nrf_radio_ramp_up_mode_set(NRF_RADIO_RAMP_UP_MODE_FAST); -} - -/// Enable peripheral shorts used during data frame transmission. -static inline void shorts_tx_frame_set(void) -{ - nrf_radio_shorts_set(SHORTS_TX_FRAME); -} - -/// Enable peripheral shorts used in receive state to enable automatic ACK procedure. -static inline void shorts_rx_initial_set(void) -{ - nrf_radio_ifs_set(TIFS_ACK_US); - nrf_radio_ramp_up_mode_set(NRF_RADIO_RAMP_UP_MODE_DEFAULT); - nrf_radio_bcc_set(BCC_INIT); - - nrf_radio_shorts_set(SHORTS_RX_INITIAL); -} - -/// Enable peripheral shorts used during automatic ACK transmission. -static inline void shorts_rx_following_set(void) -{ - nrf_radio_shorts_set(SHORTS_RX_FOLLOWING); -} - -/// Disable peripheral shorts used during automatic ACK transmission when ACK is being transmitted -static inline void shorts_tx_ack_set(void) -{ - // If ACK is sent PHYEND_DISABLE short should persist to disable transmitter automatically. - nrf_radio_shorts_set(SHORTS_TX_ACK); - nrf_radio_ifs_set(0); - nrf_radio_ramp_up_mode_set(NRF_RADIO_RAMP_UP_MODE_FAST); -} - -/*************************************************************************************************** - * @section ACK transmission management - **************************************************************************************************/ - -/// Set valid sequence number in ACK frame. -static inline void ack_prepare(void) -{ - // Copy sequence number from received frame to ACK frame. - m_ack_psdu[DSN_OFFSET] = mp_current_rx_buffer->psdu[DSN_OFFSET]; -} - -/// Set pending bit in ACK frame. -static inline void ack_pending_bit_set(void) -{ - m_ack_psdu[FRAME_PENDING_OFFSET] = ACK_HEADER_WITH_PENDING; - - if (!nrf_drv_radio802154_ack_pending_bit_should_be_set(mp_current_rx_buffer->psdu)) - { - m_ack_psdu[FRAME_PENDING_OFFSET] = ACK_HEADER_WITHOUT_PENDING; - } -} - -/** Check if ACK is requested in given frame. - * - * @param[in] p_frame Pointer to a frame to check. - * - * @retval true ACK is requested in given frame. - * @retval false ACK is not requested in given frame. - */ -static inline bool ack_is_requested(const uint8_t * p_frame) -{ - return (p_frame[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT) ? true : false; -} - -/** Abort automatic ACK procedure. - * - * @param[in] state_to_set Driver state that shall be set after the procedure is aborted. - */ -static void auto_ack_abort(radio_state_t state_to_set) -{ - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_AUTO_ACK_ABORT); - - shorts_disable(); - - switch (nrf_radio_state_get()) - { - case NRF_RADIO_STATE_RX: // When stopping before whole frame received. - case NRF_RADIO_STATE_RX_RU: // When transmission is initialized during receiver ramp up. - case NRF_RADIO_STATE_RX_IDLE: - case NRF_RADIO_STATE_TX_RU: - case NRF_RADIO_STATE_TX_IDLE: - case NRF_RADIO_STATE_TX: - nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); // Clear disabled event that was set by short. - state_set(state_to_set); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - break; - - case NRF_RADIO_STATE_RX_DISABLE: - case NRF_RADIO_STATE_DISABLED: - case NRF_RADIO_STATE_TX_DISABLE: - // Do not trigger DISABLE task in those states to prevent double DISABLED events. - state_set(state_to_set); - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_AUTO_ACK_ABORT); -} - -/*************************************************************************************************** - * @section ACK receiving management - **************************************************************************************************/ - -/// Enable hardware ACK matching accelerator. -static inline void ack_matching_enable(void) -{ - nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH); - nrf_radio_mhmu_search_pattern_set(MHMU_PATTERN | - ((uint32_t) mp_tx_data[DSN_OFFSET] << - MHMU_PATTERN_DSN_OFFSET)); -} - -/// Disable hardware ACK matching accelerator. -static inline void ack_matching_disable(void) -{ - nrf_radio_mhmu_search_pattern_set(0); - nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH); -} - -/** Check if hardware ACK matching accelerator matched ACK pattern in received frame. - * - * @retval true ACK matching accelerator matched ACK pattern. - * @retval false ACK matching accelerator did not match ACK pattern. - */ -static inline bool ack_is_matched(void) -{ - return (nrf_radio_event_get(NRF_RADIO_EVENT_MHRMATCH)) && - (nrf_radio_crc_status_get() == NRF_RADIO_CRC_STATUS_OK); -} - -/// Start receiver to receive data after receiving of ACK frame. -static inline void frame_rx_start_after_ack_rx(void) -{ - ack_matching_disable(); - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); // Errata [110] -} - -/*************************************************************************************************** - * @section RADIO peripheral management - **************************************************************************************************/ - -/// Initialize radio peripheral -static void nrf_radio_init(void) -{ - nrf_radio_mode_set(NRF_RADIO_MODE_IEEE802154_250KBIT); - nrf_radio_config_length_field_length_set(8); - nrf_radio_config_preamble_length_set(NRF_RADIO_PREAMBLE_LENGTH_32BIT_ZERO); - nrf_radio_config_crc_included_set(true); - nrf_radio_config_max_length_set(MAX_PACKET_SIZE); - nrf_radio_ramp_up_mode_set(NRF_RADIO_RAMP_UP_MODE_FAST); - - // Configure CRC - nrf_radio_crc_length_set(CRC_LENGTH); - nrf_radio_crc_includes_address_set(NRF_RADIO_CRC_INCLUDES_ADDR_IEEE802154); - nrf_radio_crc_polynominal_set(CRC_POLYNOMIAL); - - // Configure CCA - cca_configuration_update(); - - // Configure MAC Header Match Unit - nrf_radio_mhmu_search_pattern_set(0); - nrf_radio_mhmu_pattern_mask_set(MHMU_MASK); - - nrf_radio_int_enable(NRF_RADIO_INT_FRAMESTART_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_END_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_DISABLED_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_CCAIDLE_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_CCABUSY_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_READY_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_BCMATCH_MASK); - nrf_radio_int_enable(NRF_RADIO_INT_EDEND_MASK); - - /// Workaround for missing PHYEND event in older chip revision. - if (nrf_drv_radio802154_revision_has_phyend_event()) - { - nrf_radio_int_enable(NRF_RADIO_INT_PHYEND_MASK); - } -} - -/// Reset radio peripheral -static void nrf_radio_reset(void) -{ - nrf_radio_power_set(false); - nrf_radio_power_set(true); - - nrf_drv_radio802154_log(EVENT_RADIO_RESET, 0); -} - -/// Initialize interrupts for radio peripheral -static void irq_init(void) -{ - NVIC_SetPriority(RADIO_IRQn, NRF_DRV_RADIO802154_IRQ_PRIORITY); - NVIC_ClearPendingIRQ(RADIO_IRQn); - NVIC_EnableIRQ(RADIO_IRQn); -} - -/// Deinitialize interrupts for radio peripheral -static void irq_deinit(void) -{ - NVIC_DisableIRQ(RADIO_IRQn); - NVIC_ClearPendingIRQ(RADIO_IRQn); - NVIC_SetPriority(RADIO_IRQn, 0); - - __DSB(); - __ISB(); -} - - -/*************************************************************************************************** - * @section Energy detection management - **************************************************************************************************/ - -/** Setup next iteration of energy detection procedure. - * - * Energy detection procedure is performed in iterations to make sure it is performed for requested - * time regardless radio arbitration. - * - * @param[in] Remaining time of energy detection procedure [us]. - * - * @retval true Next iteration of energy detection procedure will be performed now. - * @retval false Next iteration of energy detection procedure will not be performed now due to - * ending timeslot. - */ -static inline bool ed_iter_setup(uint32_t time_us) -{ - uint32_t us_left_in_timeslot = nrf_raal_timeslot_us_left_get(); - uint32_t next_ed_iters = us_left_in_timeslot / ED_ITER_DURATION; - - if (next_ed_iters > ED_ITERS_OVERHEAD) - { - next_ed_iters -= ED_ITERS_OVERHEAD; - - if ((time_us / ED_ITER_DURATION) < next_ed_iters) - { - m_ed_time_left = 0; - next_ed_iters = time_us / ED_ITER_DURATION; - } - else - { - m_ed_time_left = time_us - (next_ed_iters * ED_ITER_DURATION); - next_ed_iters--; // Time of ED procedure is (next_ed_iters + 1) * 128us - } - - nrf_radio_ed_loop_count_set(next_ed_iters); - - return true; - } - else - { - irq_deinit(); - nrf_radio_reset(); - - m_ed_time_left = time_us; - - return false; - } -} - - -/*************************************************************************************************** - * @section RAAL notification handlers - **************************************************************************************************/ - -void nrf_raal_timeslot_started(void) -{ - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_TIMESLOT_STARTED); - - nrf_radio_reset(); - nrf_radio_init(); - irq_init(); - - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - channel_set(nrf_drv_radio802154_pib_channel_get()); - - switch (m_state) - { - case RADIO_STATE_WAITING_TIMESLOT: - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - break; - - case RADIO_STATE_ED: - if (ed_iter_setup(m_ed_time_left)) - { - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - } - - break; - - case RADIO_STATE_CCA: - case RADIO_STATE_CONTINUOUS_CARRIER: - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - break; - - case RADIO_STATE_SLEEP: - // This case may happen when sleep is requested by the next higher layer right before - // timeslot starts and the driver uses SWI for requests and notifications. In this case - // RAAL may report timeslot start event when exiting sleep request critical section. - // The driver is already in SLEEP state but did not request timeslot end yet - it will - // be requested in the next SWI handler. - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_TIMESLOT_STARTED); -} - -void nrf_raal_timeslot_ended(void) -{ - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_TIMESLOT_ENDED); - - irq_deinit(); - nrf_radio_reset(); - nrf_fem_control_deactivate(); - - switch (m_state) - { - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED); - break; - - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED); - break; - - default: - break; - } - - switch (m_state) - { - case RADIO_STATE_DISABLING: - sleep_start(); - break; - - case RADIO_STATE_SLEEP: - case RADIO_STATE_WAITING_TIMESLOT: - case RADIO_STATE_ED: - case RADIO_STATE_CCA: - case RADIO_STATE_CONTINUOUS_CARRIER: - // Intentionally empty. - break; - - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - mutex_lock(); - state_set(RADIO_STATE_WAITING_TIMESLOT); - break; - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_TIMESLOT_ENDED); -} - - -/*************************************************************************************************** - * @section RADIO interrupt handler - **************************************************************************************************/ - -/// This event is handled when the radio starts receiving a frame. -static inline void irq_framestart_state_waiting_rx_frame(void) -{ - if (mutex_lock()) - { - state_set(RADIO_STATE_RX_HEADER); - assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL); - - if ((mp_current_rx_buffer->psdu[0] < ACK_LENGTH) || - (mp_current_rx_buffer->psdu[0] > MAX_PACKET_SIZE)) - { - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); - } - else - { - nrf_radio_task_trigger(NRF_RADIO_TASK_RSSISTART); - - nrf_drv_radio802154_rx_started(); - } - } - - switch (nrf_radio_state_get()) - { - case NRF_RADIO_STATE_RX: - - // If the received frame was short the radio could have changed it's state. - case NRF_RADIO_STATE_RX_IDLE: - - // The radio could have changed state to one of the following due to enabled shorts. - case NRF_RADIO_STATE_RX_DISABLE: - case NRF_RADIO_STATE_DISABLED: - case NRF_RADIO_STATE_TX_RU: - break; - - // If something had stopped the CPU too long. Try to recover radio state. - case NRF_RADIO_STATE_TX_IDLE: - case NRF_RADIO_STATE_TX_DISABLE: - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_RUNTIME); - break; - - default: - assert(false); - } -} - -/// This event is handled when the radio starts receiving an ACK frame. -static inline void irq_framestart_state_rx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - if ((mp_current_rx_buffer->psdu[0] < ACK_LENGTH) || - (mp_current_rx_buffer->psdu[0] > MAX_PACKET_SIZE)) - { - nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK); - - frame_rx_start_after_ack_rx(); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); // In case frame ended before task DISABLE - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - } - else - { - nrf_radio_task_trigger(NRF_RADIO_TASK_RSSISTART); - - nrf_drv_radio802154_rx_ack_started(); - } -} - -/// This event is handled when the radio starts transmitting a requested frame. -static inline void irq_framestart_state_tx_frame(void) -{ - nrf_drv_radio802154_tx_started(); -} - -/// This event is handled when the radio starts transmitting an ACK frame. -static inline void irq_framestart_state_tx_ack(void) -{ - nrf_drv_radio802154_tx_ack_started(); -} - -/// This event is handled when MHR is received -static inline void irq_bcmatch_mhr(void) -{ - // Verify if time slot for receiving is available. - if (nrf_raal_timeslot_request(nrf_drv_radio802154_rx_duration_get( - mp_current_rx_buffer->psdu[0], - ack_is_requested(mp_current_rx_buffer->psdu)))) - { - uint8_t frame_type = mp_current_rx_buffer->psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK; - - // Check Frame Control field. - switch (frame_type) - { - case FRAME_TYPE_BEACON: - // Beacon is broadcast frame. - m_flags.prevent_ack = false; - state_set(RADIO_STATE_RX_FRAME); - break; - - case FRAME_TYPE_DATA: - case FRAME_TYPE_COMMAND: - - // For data or command check destination address. - switch (mp_current_rx_buffer->psdu[DEST_ADDR_TYPE_OFFSET] & - DEST_ADDR_TYPE_MASK) - { - case DEST_ADDR_TYPE_SHORT: - nrf_radio_bcc_set(BCC_SHORT_ADDR); - break; - - case DEST_ADDR_TYPE_EXTENDED: - nrf_radio_bcc_set(BCC_EXTENDED_ADDR); - break; - - default: - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); - } - - break; - - default: - - // For ACK and other types: in promiscuous mode accept it as broadcast; - // in normal mode drop the frame. - if (nrf_drv_radio802154_pib_promiscuous_get()) - { - m_flags.prevent_ack = true; - state_set(RADIO_STATE_RX_FRAME); - } - else - { - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - // Do not count received ACK as an error. - if (frame_type != FRAME_TYPE_ACK) - { - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); - } - } - } - } - else - { - irq_deinit(); - nrf_radio_reset(); - - state_set(RADIO_STATE_WAITING_TIMESLOT); - - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED); - } -} - -/// This event is generated when destination address fields are received. -static inline void irq_bcmatch_address(void) -{ - if (nrf_drv_radio802154_pib_dest_addr_matches(mp_current_rx_buffer->psdu)) - { - m_flags.prevent_ack = false; - state_set(RADIO_STATE_RX_FRAME); - } - else - { - if (nrf_drv_radio802154_pib_promiscuous_get()) - { - m_flags.prevent_ack = true; - state_set(RADIO_STATE_RX_FRAME); - } - else - { - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR); - } - } -} - -/** This event is generated twice during frame reception: - * when MHR is received and when destination address fields are received. - */ -static inline void irq_bcmatch_state_rx_header(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL); - - switch (nrf_radio_state_get()) - { - case NRF_RADIO_STATE_RX: - case NRF_RADIO_STATE_RX_IDLE: - case NRF_RADIO_STATE_RX_DISABLE: - case NRF_RADIO_STATE_DISABLED: - case NRF_RADIO_STATE_TX_RU: // A lot of states due to shorts. - - switch (nrf_radio_bcc_get()) - { - case BCC_INIT: // Received MHR - irq_bcmatch_mhr(); - break; - - case BCC_SHORT_ADDR: // Received short destination address - case BCC_EXTENDED_ADDR: // Received extended destination address - // Check destination address during second match. - irq_bcmatch_address(); - break; - - default: - assert(false); - } - - break; - - case NRF_RADIO_STATE_TX_IDLE: - // Something had stopped the CPU too long. Start receiving again. - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_RUNTIME); - break; - - default: - assert(false); - } -} - -/** This event is generated when radio receives invalid frame with length set to 0 or started - * receiving a frame after other procedure locked mutex. - */ -static inline void irq_end_state_waiting_rx_frame(void) -{ - // Radio state is not asserted here. It can be a lot of states due to shorts. - if (mp_current_rx_buffer->psdu[0] == 0) - { - // If length of the frame is 0 there was no FRAMESTART event. Lock mutex now and abort sending ACK. - if (mutex_lock()) - { - assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL); - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - } - } - else - { - // Do nothing. Whoever took mutex shall stop sending ACK. - } -} - -/// This event is generated if frame being received is shorter than expected MAC header length. -static inline void irq_end_state_rx_header(void) -{ - // Frame ended before header was received. - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); -} - -/// This event is generated when radio peripheral ends receiving of a complete frame. -static inline void irq_end_state_rx_frame(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL); - - switch (nrf_radio_state_get()) - { - case NRF_RADIO_STATE_RX_IDLE: - case NRF_RADIO_STATE_RX_DISABLE: - case NRF_RADIO_STATE_DISABLED: - case NRF_RADIO_STATE_TX_RU: - - if (nrf_radio_crc_status_get() == NRF_RADIO_CRC_STATUS_OK) - { - if ((!ack_is_requested(mp_current_rx_buffer->psdu)) || - (!nrf_drv_radio802154_pib_auto_ack_get()) || - m_flags.prevent_ack) - { - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - received_frame_notify(); - } - else - { - ack_prepare(); - state_set(RADIO_STATE_TX_ACK); - } - } - else - { - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS); - } - - break; - - case NRF_RADIO_STATE_TX_IDLE: - // CPU was hold too long. - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_RUNTIME); - break; - - default: - assert(false); - } -} - -/// This event is generated when the radio ends transmission of ACK frame. -static inline void irq_phyend_state_tx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_TX_ACK || - nrf_radio_shorts_get() == SHORTS_RX_FOLLOWING); // In case PHYEND is handled before READY - shorts_disable(); - - received_frame_notify(); - - // Clear event READY in case CPU was halted and event PHYEND is handled before READY. - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - - state_set(RADIO_STATE_WAITING_RX_FRAME); - // Receiver is enabled by shorts. -} - -/** This event may occur at the beginning of transmission procedure (the procedure already has - * disabled shorts). - */ -static inline void irq_end_state_cca_before_tx(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); -} - -/// This event is generated when the radio ends transmission of a frame. -static inline void irq_phyend_state_tx_frame(void) -{ - shorts_disable(); - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - // Clear event READY in case CPU was halted and event PHYEND is handled before READY. - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - - if (!ack_is_requested(mp_tx_data)) - { - nrf_drv_radio802154_notify_transmitted(NULL, 0, 0); - - state_set(RADIO_STATE_WAITING_RX_FRAME); - } - else - { - state_set(RADIO_STATE_RX_ACK); - - ack_matching_enable(); - } - - // Task DISABLE is triggered by shorts. -} - -/// This event is generated when the radio ends receiving of ACK frame. -static inline void irq_end_state_rx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - if (ack_is_matched()) - { - mp_current_rx_buffer->free = false; - nrf_drv_radio802154_notify_transmitted(mp_current_rx_buffer->psdu, // psdu - rssi_last_measurement_get(), // rssi - RX_FRAME_LQI(mp_current_rx_buffer->psdu)); // lqi - } - else - { - nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK); - } - - frame_rx_start_after_ack_rx(); -} - -/// This event is generated when radio peripheral disables in order to enter sleep state. -static inline void irq_disabled_state_disabling(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - sleep_start(); -} - -/** This event is generated when the driver enters receive state. - * - * The radio is now disabled and the driver starts enabling receiver. - */ -static inline void irq_disabled_state_waiting_rx_frame(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - while (nrf_radio_state_get() == NRF_RADIO_STATE_TX_DISABLE) - { - // This event can be handled in TXDISABLE state due to double DISABLE event (IC-15879). - // This busy loop waits to the end of this state. - } - - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - - rx_enable(); - mutex_unlock(); - - rx_buffer_in_use_set(nrf_drv_radio802154_rx_buffer_free_find()); - nrf_radio_tx_power_set(nrf_drv_radio802154_pib_tx_power_get()); - - // Clear this event after RXEN task in case event is triggered just before. - nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); -} - -/** This event is generated in case both END and DISABLED events are notified between - * checking if END event was notified and checking if DISABLED event was notified. - * - * In this invalid and rare case just drop received frame. - */ -static inline void irq_disabled_state_rx_frame(void) -{ - assert(nrf_radio_event_get(NRF_RADIO_EVENT_END)); - assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL); - - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); -} - -/** This event is generated during automatic ACK transmission. - * - * Receiver is disabled and transmitter is being enabled by shorts. - */ -static inline void irq_disabled_state_tx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL); - - shorts_rx_following_set(); - ack_pending_bit_set(); - - // IC-15879 - nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); - - if (nrf_radio_state_get() == NRF_RADIO_STATE_TX_IDLE) - { - // CPU was hold too long. - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - } - else - { - // nrf_fem_control_time_latch was called at the beginning of the irq handler, - // to capture the time as close to short occurence as possible - nrf_fem_control_pa_set(true, false); - } -} - -/** This event is generated before CCA procedure starts. - * - * The radio is disabled and the drivers enables receiver in order to start CCA procedure. - */ -static inline void irq_disabled_state_cca_before_tx(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - - rx_enable(); -} - -/** This event is generated before transmission of a frame starts. - * - * The radio is disabled and enabling transmitter is requested by shorts or by the driver. - */ -static inline void irq_disabled_state_tx_frame(void) -{ - if (nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED) - { - shorts_tx_frame_set(); - - tx_enable(); - } - - assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME); -} - -/** This event is generated when radio is disabled after transmission of a frame with ACK request. - * - * The driver enables receiver to receive ACK frame. - */ -static inline void irq_disabled_state_rx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - - rx_enable(); - - if (mp_current_rx_buffer == NULL || (!mp_current_rx_buffer->free)) - { - rx_buffer_in_use_set(nrf_drv_radio802154_rx_buffer_free_find()); - } -} - -/** This event is generated before energy detection procedure. - * - * The radio is disabled and the driver enables receiver in order to start energy detection - * procedure. - */ -static inline void irq_disabled_state_ed(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - - rx_enable(); -} - -/** This event is generated before stand-alone CCA procedure. - * - * The radio is disabled and the driver enables receiver in order to start CCA procedure. - */ -static inline void irq_disabled_state_cca(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - - rx_enable(); -} - -/** This event is generated before continuous-carrier procedure is started. - * - * The radio is disabled and the driver enables transmitter in order to start emitting carrier - * continuously. - */ -static inline void irq_disabled_state_continuous_carrier(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - - tx_enable(); -} - -/** This event is generated when receiver is ready to start receiving a frame. - * - * Driver checks if buffer for a frame is available and starts receiver. - */ -static inline void irq_ready_state_waiting_rx_frame(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - if ((mp_current_rx_buffer != NULL) && (mp_current_rx_buffer->free)) - { - if (mutex_lock()) - { - shorts_rx_initial_set(); - rx_frame_start(); - - mutex_unlock(); - } - } -} - -/** This event is generated when transmitter is ready to transmit ACK frame. - * - * Transmission is started by shorts. The driver sets shorts to gracefully end transmission of ACK. - */ -static inline void irq_ready_state_tx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_RX_FOLLOWING); - shorts_tx_ack_set(); -} - -/** This event is generated when receiver is ready to start CCA procedure. - * - * The driver prepares for transmission and starts CCA procedure. - */ -static inline void irq_ready_state_cca_before_tx(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - state_set(RADIO_STATE_TX_FRAME); - - shorts_tx_frame_set(); - nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTART); -} - -/** This event is generated when transmitter is ready to transmit a frame. - * - * Transmission is started by shorts. - */ -static inline void irq_ready_state_tx_frame(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME); -} - -/// This event is generated when receiver is ready to receive an ACK frame. -static inline void irq_ready_state_rx_ack(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - if (mp_current_rx_buffer == NULL || (!mp_current_rx_buffer->free)) - { - nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_NO_MEM); - frame_rx_start_after_ack_rx(); - } - else - { - rx_start(); - } -} - -/// This event is generated when receiver is ready to start energy detection procedure. -static inline void irq_ready_state_ed(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - nrf_radio_task_trigger(NRF_RADIO_TASK_EDSTART); -} - -/// This event is generated when receiver is ready to start CCA procedure. -static inline void irq_ready_state_cca(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTART); -} - -/// This event is generated when transmitter is emitting carrier continuously. -static inline void irq_ready_state_continuous_carrier(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_TX_IDLE); -} - -#if !NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN -/// This event is generated when CCA reports that channel is idle. -static inline void irq_ccaidle_state_tx_frame(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME); - - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); -} -#endif // NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN - -/// This event is generated when CCA reports idle channel during stand-alone procedure. -static inline void irq_ccaidle_state_cca(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - nrf_drv_radio802154_notify_cca(true); - - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); -} - -/// This event is generated when CCA reports busy channel prior to transmission. -static inline void irq_ccabusy_state_tx_frame(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - shorts_disable(); - - nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL); - - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); -} - -/// This event is generated when CCA reports busy channel during stand-alone procedure. -static inline void irq_ccabusy_state_cca(void) -{ - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - - nrf_drv_radio802154_notify_cca(false); - - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); -} - -/// This event is generated when energy detection procedure ends. -static inline void irq_edend(void) -{ - assert(m_state == RADIO_STATE_ED); - assert(nrf_radio_state_get() == NRF_RADIO_STATE_RX_IDLE); - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - uint32_t result = nrf_radio_ed_sample_get(); - m_ed_result = result > m_ed_result ? result : m_ed_result; - - if (m_ed_time_left) - { - if (ed_iter_setup(m_ed_time_left)) - { - nrf_radio_task_trigger(NRF_RADIO_TASK_EDSTART); - } - } - else - { - nrf_drv_radio802154_notify_energy_detected(m_ed_result); - - // In case channel change was requested during energy detection procedure. - channel_set(nrf_drv_radio802154_pib_channel_get()); - - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - } -} - -/// Handler of radio interrupts. -static inline void irq_handler(void) -{ - nrf_fem_control_time_latch(); - - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_IRQ_HANDLER); - - if (nrf_radio_event_get(NRF_RADIO_EVENT_FRAMESTART)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - irq_framestart_state_waiting_rx_frame(); - break; - - case RADIO_STATE_RX_ACK: - irq_framestart_state_rx_ack(); - break; - - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_CCA_BEFORE_TX: // This could happen at the beginning of transmission procedure. - irq_framestart_state_tx_frame(); - break; - - case RADIO_STATE_TX_ACK: - irq_framestart_state_tx_ack(); - break; - - case RADIO_STATE_WAITING_TIMESLOT: - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_FRAMESTART); - } - - // Check MAC frame header. - if (nrf_radio_event_get(NRF_RADIO_EVENT_BCMATCH)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - - switch (m_state) - { - case RADIO_STATE_RX_HEADER: - irq_bcmatch_state_rx_header(); - break; - - case RADIO_STATE_WAITING_RX_FRAME: // Didn't lock mutex - other procedure manages radio. - case RADIO_STATE_WAITING_TIMESLOT: // Radio is out of timeslot now. - assert(m_mutex); - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_BCMATCH); - } - - if (nrf_drv_radio802154_revision_has_phyend_event() && nrf_radio_event_get(NRF_RADIO_EVENT_PHYEND)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - break; - - case RADIO_STATE_TX_ACK: - irq_phyend_state_tx_ack(); - break; - - case RADIO_STATE_CCA_BEFORE_TX: - break; - - case RADIO_STATE_TX_FRAME: - irq_phyend_state_tx_frame(); - break; - - case RADIO_STATE_RX_ACK: - case RADIO_STATE_WAITING_TIMESLOT: - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_PHYEND); - } - - if (nrf_radio_event_get(NRF_RADIO_EVENT_END)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - irq_end_state_waiting_rx_frame(); - break; - - case RADIO_STATE_RX_HEADER: - irq_end_state_rx_header(); - break; - - case RADIO_STATE_RX_FRAME: - irq_end_state_rx_frame(); - break; - - case RADIO_STATE_TX_ACK: - if (!nrf_drv_radio802154_revision_has_phyend_event()) - { - irq_phyend_state_tx_ack(); - } - - break; - - case RADIO_STATE_CCA_BEFORE_TX: // This could happen at the beginning of transmission - // procedure (the procedure already has disabled shorts) - irq_end_state_cca_before_tx(); - break; - - case RADIO_STATE_TX_FRAME: - if (!nrf_drv_radio802154_revision_has_phyend_event()) - { - irq_phyend_state_tx_frame(); - } - - break; - - case RADIO_STATE_RX_ACK: // Ended receiving of ACK. - irq_end_state_rx_ack(); - break; - - case RADIO_STATE_WAITING_TIMESLOT: - // Exit as soon as possible when waiting for timeslot. - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_END); - } - - if (nrf_radio_event_get(NRF_RADIO_EVENT_DISABLED)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_DISABLED); - nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); - - switch (m_state) - { - case RADIO_STATE_DISABLING: - irq_disabled_state_disabling(); - break; - - case RADIO_STATE_WAITING_RX_FRAME: - irq_disabled_state_waiting_rx_frame(); - break; - - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - irq_disabled_state_rx_frame(); - break; - - case RADIO_STATE_TX_ACK: - irq_disabled_state_tx_ack(); - break; - - case RADIO_STATE_CCA_BEFORE_TX: - irq_disabled_state_cca_before_tx(); - break; - - case RADIO_STATE_TX_FRAME: - irq_disabled_state_tx_frame(); - break; - - case RADIO_STATE_RX_ACK: - irq_disabled_state_rx_ack(); - break; - - case RADIO_STATE_ED: - irq_disabled_state_ed(); - break; - - case RADIO_STATE_CCA: - irq_disabled_state_cca(); - break; - - case RADIO_STATE_CONTINUOUS_CARRIER: - irq_disabled_state_continuous_carrier(); - break; - - case RADIO_STATE_WAITING_TIMESLOT: - // Exit as soon as possible when waiting for timeslot. - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_DISABLED); - } - - if (nrf_radio_event_get(NRF_RADIO_EVENT_READY)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - irq_ready_state_waiting_rx_frame(); - break; - - case RADIO_STATE_TX_ACK: - irq_ready_state_tx_ack(); - break; - - case RADIO_STATE_CCA_BEFORE_TX: - irq_ready_state_cca_before_tx(); - break; - - case RADIO_STATE_TX_FRAME: - irq_ready_state_tx_frame(); - break; - - case RADIO_STATE_RX_ACK: - irq_ready_state_rx_ack(); - break; - - case RADIO_STATE_ED: - irq_ready_state_ed(); - break; - - case RADIO_STATE_CCA: - irq_ready_state_cca(); - break; - - case RADIO_STATE_CONTINUOUS_CARRIER: - irq_ready_state_continuous_carrier(); - break; - - case RADIO_STATE_WAITING_TIMESLOT: - // Exit as soon as possible when waiting for timeslot. - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_READY); - } - - if (nrf_radio_event_get(NRF_RADIO_EVENT_CCAIDLE)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_CCAIDLE); - nrf_radio_event_clear(NRF_RADIO_EVENT_CCAIDLE); - - switch (m_state) - { - case RADIO_STATE_TX_FRAME: -#if !NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN - irq_ccaidle_state_tx_frame(); -#else - // nrf_fem_control_time_latch was called at the beginning of the irq handler, - // to capture the time as close to short occurence as possible - nrf_fem_control_pa_set(true, true); -#endif - break; - - case RADIO_STATE_CCA: - irq_ccaidle_state_cca(); - break; - -#if NRF_DRV_RADIO802154_SHORT_CCAIDLE_TXEN - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_ACK: - // If CCAIDLE->TXEN short is enabled, this event may be handled after event END. - break; -#endif - - case RADIO_STATE_WAITING_TIMESLOT: - // Exit as soon as possible when waiting for timeslot. - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CCAIDLE); - } - - if (nrf_radio_event_get(NRF_RADIO_EVENT_CCABUSY)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_CCABUSY); - nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY); - - switch (m_state) - { - case RADIO_STATE_TX_FRAME: - irq_ccabusy_state_tx_frame(); - break; - - case RADIO_STATE_CCA: - irq_ccabusy_state_cca(); - break; - - case RADIO_STATE_WAITING_TIMESLOT: - // Exit as soon as possible when waiting for timeslot. - break; - - default: - assert(false); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CCABUSY); - } - - if (nrf_radio_event_get(NRF_RADIO_EVENT_EDEND)) - { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_EDEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_EDEND); - - irq_edend(); - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_EDEND); - } - - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_IRQ_HANDLER); -} - - -/*************************************************************************************************** - * @section FSM transition request sub-procedures - **************************************************************************************************/ - -/** Abort transmission procedure. - * - * This function is called when MAC layer requests transition from transmit to receive state. - */ -static inline void tx_procedure_abort(radio_state_t state) -{ - shorts_disable(); - - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - assert(m_mutex); - - state_set(state); - - // Stop CCA and clear result. CCA may be performed regardless disabled receiver. - nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTOP); - nrf_radio_event_clear(NRF_RADIO_EVENT_CCAIDLE); - nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY); - - switch (nrf_radio_state_get()) - { - case NRF_RADIO_STATE_TX_DISABLE: - case NRF_RADIO_STATE_RX_DISABLE: - // Do not enabled receiver. It will be enabled in DISABLED handler. - break; - - default: - nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - } - - ack_matching_disable(); - - // Clear events that could have happened in critical section due to receiving frame. - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); -} - - -/*************************************************************************************************** - * @section API functions - **************************************************************************************************/ - -void nrf_drv_radio802154_fsm_init(void) -{ - const uint8_t ack_psdu[] = {0x05, ACK_HEADER_WITH_PENDING, 0x00, 0x00, 0x00, 0x00}; - memcpy(m_ack_psdu, ack_psdu, sizeof(ack_psdu)); - -} - -void nrf_drv_radio802154_fsm_deinit(void) -{ - if (m_state != RADIO_STATE_WAITING_TIMESLOT && - m_state != RADIO_STATE_SLEEP) - { - nrf_radio_reset(); - } - - irq_deinit(); -} - -radio_state_t nrf_drv_radio802154_fsm_state_get(void) -{ - return m_state; -} - -bool nrf_drv_radio802154_fsm_sleep(void) -{ - bool result = false; - - switch (m_state) - { - case RADIO_STATE_WAITING_TIMESLOT: - assert(m_mutex); - - sleep_start(); - result = true; - break; - - case RADIO_STATE_WAITING_RX_FRAME: - if (mutex_lock()) - { - auto_ack_abort(RADIO_STATE_DISABLING); - - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - // Clear events that could have happened in critical section due to receiving frame - // or RX ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - - result = true; - } - - break; - - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - break; - - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - tx_procedure_abort(RADIO_STATE_DISABLING); - result = true; - break; - - default: - assert(false); // This should not happen. - } - - return result; -} - -bool nrf_drv_radio802154_fsm_receive(void) -{ - bool result = false; - - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - result = true; - break; - - case RADIO_STATE_DISABLING: - state_set(RADIO_STATE_WAITING_RX_FRAME); - result = true; - // TASK DISABLE was already triggered. Wait for event DISABLED. - break; - - case RADIO_STATE_SLEEP: - if (mutex_lock()) - { - state_set(RADIO_STATE_WAITING_TIMESLOT); - nrf_raal_continuous_mode_enter(); - - result = true; - } - else - { - assert(false); - } - - break; - - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - tx_procedure_abort(RADIO_STATE_WAITING_RX_FRAME); - result = true; - break; - - case RADIO_STATE_CONTINUOUS_CARRIER: - state_set(RADIO_STATE_WAITING_RX_FRAME); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - result = true; - break; - - case RADIO_STATE_ED: - case RADIO_STATE_CCA: - // Ignore receive function during energy detection or CCA procedure. - break; - - case RADIO_STATE_WAITING_TIMESLOT: - // Ignore receive function in WAITING_TIMESLOT state - the radio will receive when time - // slot starts. - result = true; - break; - - default: - assert(false); - } - - return result; -} - -bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, bool cca) -{ - bool result = false; - mp_tx_data = p_data; - - if (mutex_lock()) - { - if (nrf_raal_timeslot_request(nrf_drv_radio802154_tx_duration_get(p_data[0], - cca, - ack_is_requested(p_data)))) - { - assert(m_state == RADIO_STATE_WAITING_RX_FRAME); - - auto_ack_abort(cca ? RADIO_STATE_CCA_BEFORE_TX : RADIO_STATE_TX_FRAME); - - nrf_radio_tx_power_set(nrf_drv_radio802154_pib_tx_power_get()); - nrf_radio_packet_ptr_set(p_data); - - // Clear events that could have happened in critical section due to receiving frame or RX ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - - // Check 2nd time in case this procedure was interrupted. - if (nrf_raal_timeslot_request( - nrf_drv_radio802154_tx_duration_get(p_data[0], cca, ack_is_requested(p_data)))) - { - result = true; - } - else - { - irq_deinit(); - nrf_radio_reset(); - - state_set(RADIO_STATE_WAITING_TIMESLOT); - } - } - else - { - mutex_unlock(); - } - } - - return result; -} - -bool nrf_drv_radio802154_fsm_energy_detection(uint32_t time_us) -{ - bool result = false; - - switch (m_state) - { - case RADIO_STATE_SLEEP: - if (mutex_lock()) - { - state_set(RADIO_STATE_ED); - m_ed_time_left = time_us; - m_ed_result = 0; - - nrf_raal_continuous_mode_enter(); - - result = true; - } - - break; - - case RADIO_STATE_WAITING_RX_FRAME: - if (mutex_lock()) - { - m_ed_result = 0; - - if (ed_iter_setup(time_us)) - { - auto_ack_abort(RADIO_STATE_ED); - - assert(nrf_radio_shorts_get() == SHORTS_IDLE); - - // Clear events that could have happened in critical section due to receiving - // frame or RX ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - } - else - { - state_set(RADIO_STATE_ED); - } - - result = true; - } - - break; - - case RADIO_STATE_DISABLING: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - case RADIO_STATE_WAITING_TIMESLOT: - break; - - default: - assert(false); // This should not happen. - } - - return result; -} - -bool nrf_drv_radio802154_fsm_cca(void) -{ - bool result = false; - - switch (m_state) - { - case RADIO_STATE_SLEEP: - if (mutex_lock()) - { - state_set(RADIO_STATE_CCA); - - nrf_raal_continuous_mode_enter(); - - result = true; - } - - break; - - case RADIO_STATE_WAITING_RX_FRAME: - if (mutex_lock()) - { - if (nrf_raal_timeslot_request(nrf_drv_radio802154_cca_duration_get())) - { - auto_ack_abort(RADIO_STATE_CCA); - - // Clear events that could have happened in critical section due to receiving - // frame or RX ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - } - else - { - state_set(RADIO_STATE_CCA); - } - - result = true; - } - - break; - - case RADIO_STATE_DISABLING: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - case RADIO_STATE_WAITING_TIMESLOT: - break; - - default: - assert(false); // This should not happen. - } - - return result; -} - -bool nrf_drv_radio802154_fsm_continuous_carrier(void) -{ - bool result = false; - - if (mutex_lock()) - { - assert(m_state == RADIO_STATE_WAITING_RX_FRAME || - m_state == RADIO_STATE_SLEEP); - - auto_ack_abort(RADIO_STATE_CONTINUOUS_CARRIER); - - // Clear events that could have happened in critical section due to receiving frame or RX ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - - result = true; - } - - return result; -} - -void nrf_drv_radio802154_fsm_notify_buffer_free(rx_buffer_t * p_buffer) -{ - p_buffer->free = true; - - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - - switch (nrf_radio_state_get()) - { - case NRF_RADIO_STATE_RX_DISABLE: // This one could happen after receive of broadcast frame. - case NRF_RADIO_STATE_TX_DISABLE: // This one could happen due to stopping ACK. - case NRF_RADIO_STATE_DISABLED: // This one could happen during stopping ACK. - case NRF_RADIO_STATE_RX_RU: // This one could happen during enabling receiver (after sending ACK). - case NRF_RADIO_STATE_RX: // This one could happen if any other buffer is in use. - case NRF_RADIO_STATE_TX_RU: // This one could happen if received a short frame. - case NRF_RADIO_STATE_TX_IDLE: // This one could happen if received a short frame. - break; - - case NRF_RADIO_STATE_RX_IDLE: - // Mutex to make sure Radio State did not change between IRQ and this process. - // Check shorts to make sure RX_IDLE state is due to occupied buffers - not - // during END/DISABLE short. - // If API call changed Radio state leave Radio as it is. - if (mutex_lock() && nrf_radio_shorts_get() == SHORTS_IDLE) - { - shorts_rx_initial_set(); - - rx_buffer_in_use_set(p_buffer); - rx_frame_start(); - - // Clear events that could have happened in critical section due to RX - // ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - - mutex_unlock(); - } - break; - - default: - assert(false); - } - - break; - - default: - // Don't perform any action in any other state (receiver should not be started). - break; - } -} - -void nrf_drv_radio802154_fsm_channel_update(void) -{ - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - if (mutex_lock()) - { - channel_set(nrf_drv_radio802154_pib_channel_get()); - auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); - - // Clear events that could have happened in critical section due to receiving - // frame or RX ramp up. - nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART); - nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); - nrf_radio_event_clear(NRF_RADIO_EVENT_END); - nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND); - nrf_radio_event_clear(NRF_RADIO_EVENT_READY); - } - else - { - assert(false); - } - - break; - - case RADIO_STATE_CONTINUOUS_CARRIER: - channel_set(nrf_drv_radio802154_pib_channel_get()); - nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); - break; - - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - case RADIO_STATE_CCA: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - channel_set(nrf_drv_radio802154_pib_channel_get()); - break; - - case RADIO_STATE_DISABLING: - case RADIO_STATE_SLEEP: - case RADIO_STATE_WAITING_TIMESLOT: - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_ED: - // Don't perform any action in these states (channel will be updated when receiver is - // enabled). - break; - - } -} - -void nrf_drv_radio802154_fsm_cca_cfg_update(void) -{ - switch (m_state) - { - case RADIO_STATE_WAITING_RX_FRAME: - case RADIO_STATE_RX_HEADER: - case RADIO_STATE_RX_FRAME: - case RADIO_STATE_TX_ACK: - case RADIO_STATE_CCA: - case RADIO_STATE_CCA_BEFORE_TX: - case RADIO_STATE_TX_FRAME: - case RADIO_STATE_RX_ACK: - cca_configuration_update(); - break; - - case RADIO_STATE_DISABLING: - case RADIO_STATE_SLEEP: - case RADIO_STATE_WAITING_TIMESLOT: - case RADIO_STATE_ED: - case RADIO_STATE_CONTINUOUS_CARRIER: - // Don't perform any action in these states (CCA configuration will be updated when - // receiver is enabled). - break; - - } -} - -#if NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING -void RADIO_IRQHandler(void) -#else // NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING -void nrf_drv_radio802154_fsm_irq_handler(void) -#endif // NRF_DRV_RADIO802154_INTERNAL_IRQ_HANDLING -{ - irq_handler(); -} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c deleted file mode 100644 index 94b8be246..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements notifications triggered directly by the nrf 802.15.4 radio driver. - * - */ - -#include "nrf_drv_radio802154_notification.h" - -#include -#include - -#include "nrf_drv_radio802154.h" - -void nrf_drv_radio802154_notification_init(void) -{ - // Intentionally empty -} - -void nrf_drv_radio802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi) -{ - nrf_drv_radio802154_received_raw(p_data, power, lqi); -} - -void nrf_drv_radio802154_notify_receive_failed(nrf_drv_radio802154_rx_error_t error) -{ - nrf_drv_radio802154_receive_failed(error); -} - -void nrf_drv_radio802154_notify_transmitted(uint8_t * p_ack, int8_t power, int8_t lqi) -{ - nrf_drv_radio802154_transmitted_raw(p_ack, power, lqi); -} - -void nrf_drv_radio802154_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error) -{ - nrf_drv_radio802154_transmit_failed(error); -} - -void nrf_drv_radio802154_notify_energy_detected(uint8_t result) -{ - nrf_drv_radio802154_energy_detected(result); -} - -void nrf_drv_radio802154_notify_cca(bool is_free) -{ - nrf_drv_radio802154_cca_done(is_free); -} - diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.c deleted file mode 100644 index 5b1ac21cb..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.c +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements storage of PIB attributes in nRF 802.15.4 radio driver. - * - */ - -#include "nrf_drv_radio802154_pib.h" - -#include -#include -#include -#include - -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_const.h" - -#define BROADCAST_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff}) ///< Broadcast Short Address - -typedef struct -{ - int8_t tx_power; ///< Transmit power. - uint8_t pan_id[PAN_ID_SIZE]; ///< Pan Id of this node. - uint8_t short_addr[SHORT_ADDRESS_SIZE]; ///< Short Address of this node. - uint8_t extended_addr[EXTENDED_ADDRESS_SIZE]; ///< Extended Address of this node. - nrf_drv_radio802154_cca_cfg_t cca; ///< CCA mode and thresholds. - bool promiscuous :1; ///< Indicating if radio is in promiscuous mode. - bool auto_ack :1; ///< Indicating if auto ACK procedure is enabled. - uint8_t channel :5; ///< Channel on which the node receives messages. -} nrf_drv_radio802154_pib_data_t; - -static nrf_drv_radio802154_pib_data_t m_data; ///< Buffer containing PIB data. - -void nrf_drv_radio802154_pib_init(void) -{ - m_data.promiscuous = false; - m_data.auto_ack = true; - m_data.channel = 11; - - memset(m_data.pan_id, 0xff, sizeof(m_data.pan_id)); - m_data.short_addr[0] = 0xfe; - m_data.short_addr[1] = 0xff; - memset(m_data.extended_addr, 0, sizeof(m_data.extended_addr)); - - m_data.cca.mode = NRF_DRV_RADIO802154_CCA_MODE_DEFAULT; - m_data.cca.ed_threshold = NRF_DRV_RADIO802154_CCA_ED_THRESHOLD_DEFAULT; - m_data.cca.corr_threshold = NRF_DRV_RADIO802154_CCA_CORR_THRESHOLD_DEFAULT; - m_data.cca.corr_limit = NRF_DRV_RADIO802154_CCA_CORR_LIMIT_DEFAULT; -} - -bool nrf_drv_radio802154_pib_promiscuous_get(void) -{ - return m_data.promiscuous; -} - -void nrf_drv_radio802154_pib_promiscuous_set(bool enabled) -{ - m_data.promiscuous = enabled; -} - -bool nrf_drv_radio802154_pib_auto_ack_get(void) -{ - return m_data.auto_ack; -} - -void nrf_drv_radio802154_pib_auto_ack_set(bool enabled) -{ - m_data.auto_ack = enabled; -} - -uint8_t nrf_drv_radio802154_pib_channel_get(void) -{ - return m_data.channel; -} - -void nrf_drv_radio802154_pib_channel_set(uint8_t channel) -{ - m_data.channel = channel; -} - -int8_t nrf_drv_radio802154_pib_tx_power_get(void) -{ - return m_data.tx_power; -} - -void nrf_drv_radio802154_pib_tx_power_set(int8_t dbm) -{ - const int8_t allowed_values[] = {-40, -20, -16, -12, -8, -4, 0, 2, 3, 4, 5, 6, 7, 8, 9}; - const int8_t highest_value = allowed_values[(sizeof(allowed_values) / sizeof(allowed_values[0])) - 1]; - if (dbm > highest_value) - { - dbm = highest_value; - } - else - { - for (uint32_t i = 0; i < sizeof(allowed_values) / sizeof(allowed_values[0]); i++) - { - if (dbm <= allowed_values[i]) - { - dbm = allowed_values[i]; - break; - } - } - } - - m_data.tx_power = dbm; -} - -void nrf_drv_radio802154_pib_pan_id_set(const uint8_t * p_pan_id) -{ - memcpy(m_data.pan_id, p_pan_id, PAN_ID_SIZE); -} - -void nrf_drv_radio802154_pib_extended_address_set(const uint8_t * p_extended_address) -{ - memcpy(m_data.extended_addr, p_extended_address, EXTENDED_ADDRESS_SIZE); -} - -void nrf_drv_radio802154_pib_short_address_set(const uint8_t * p_short_address) -{ - memcpy(m_data.short_addr, p_short_address, SHORT_ADDRESS_SIZE); -} - -bool nrf_drv_radio802154_pib_dest_addr_matches(const uint8_t * p_psdu) -{ - // Check destination PAN Id. - // Note that +1 in PSDU offset is added because first byte in PSDU is length. - if ((0 != memcmp(&p_psdu[PAN_ID_OFFSET + 1], m_data.pan_id, PAN_ID_SIZE)) && - (0 != memcmp(&p_psdu[PAN_ID_OFFSET + 1], BROADCAST_ADDRESS, PAN_ID_SIZE))) - { - return false; - } - - // Check destination address. - switch (p_psdu[DEST_ADDR_TYPE_OFFSET] & DEST_ADDR_TYPE_MASK) - { - case DEST_ADDR_TYPE_SHORT: - { - // Note that +1 in PSDU offset is added because first byte in PSDU is length. - if ((0 != memcmp(&p_psdu[DEST_ADDR_OFFSET + 1], - m_data.short_addr, - SHORT_ADDRESS_SIZE)) && - (0 != memcmp(&p_psdu[DEST_ADDR_OFFSET + 1], - BROADCAST_ADDRESS, - SHORT_ADDRESS_SIZE))) - { - return false; - } - - break; - } - - case DEST_ADDR_TYPE_EXTENDED: - { - // Note that +1 in PSDU offset is added because first byte in PSDU is length. - if (0 != memcmp(&p_psdu[DEST_ADDR_OFFSET + 1], - m_data.extended_addr, - sizeof(m_data.extended_addr))) - { - return false; - } - - break; - } - - default: - return false; - } - - return true; -} - -void nrf_drv_radio802154_pib_cca_cfg_set(const nrf_drv_radio802154_cca_cfg_t * p_cca_cfg) -{ - switch (p_cca_cfg->mode) - { - case NRF_RADIO_CCA_MODE_ED: - m_data.cca.mode = p_cca_cfg->mode; - m_data.cca.ed_threshold = p_cca_cfg->ed_threshold; - break; - - case NRF_RADIO_CCA_MODE_CARRIER: - m_data.cca.mode = p_cca_cfg->mode; - m_data.cca.corr_threshold = p_cca_cfg->corr_threshold; - m_data.cca.corr_limit = p_cca_cfg->corr_limit; - break; - - case NRF_RADIO_CCA_MODE_CARRIER_AND_ED: - case NRF_RADIO_CCA_MODE_CARRIER_OR_ED: - memcpy(&m_data.cca, p_cca_cfg, sizeof(m_data.cca)); - break; - - default: - assert(false); - } -} - -void nrf_drv_radio802154_pib_cca_cfg_get(nrf_drv_radio802154_cca_cfg_t * p_cca_cfg) -{ - memcpy(p_cca_cfg, &m_data.cca, sizeof(m_data.cca)); -} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_direct.c deleted file mode 100644 index 9484a70d8..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_direct.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements requests to the driver triggered directly by the MAC layer. - * - */ - -#include "nrf_drv_radio802154_request.h" - -#include -#include - -#include "nrf_drv_radio802154_critical_section.h" -#include "nrf_drv_radio802154_fsm.h" -#include "hal/nrf_radio.h" - -#include - -void nrf_drv_radio802154_request_init(void) -{ - // Intentionally empty -} - -bool nrf_drv_radio802154_request_sleep(void) -{ - bool result; - nrf_drv_radio802154_critical_section_enter(); - - result = nrf_drv_radio802154_fsm_sleep(); - - nrf_drv_radio802154_critical_section_exit(); - return result; -} - -bool nrf_drv_radio802154_request_receive(void) -{ - bool result; - nrf_drv_radio802154_critical_section_enter(); - - result = nrf_drv_radio802154_fsm_receive(); - - nrf_drv_radio802154_critical_section_exit(); - return result; -} - -bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, bool cca) -{ - bool result; - nrf_drv_radio802154_critical_section_enter(); - - result = nrf_drv_radio802154_fsm_transmit(p_data, cca); - - nrf_drv_radio802154_critical_section_exit(); - return result; -} - -bool nrf_drv_radio802154_request_energy_detection(uint32_t time_us) -{ - bool result; - nrf_drv_radio802154_critical_section_enter(); - - result = nrf_drv_radio802154_fsm_energy_detection(time_us); - - nrf_drv_radio802154_critical_section_exit(); - return result; -} - -bool nrf_drv_radio802154_request_cca(void) -{ - bool result; - nrf_drv_radio802154_critical_section_enter(); - - result = nrf_drv_radio802154_fsm_cca(); - - nrf_drv_radio802154_critical_section_exit(); - return result; -} - -bool nrf_drv_radio802154_request_continuous_carrier(void) -{ - bool result; - nrf_drv_radio802154_critical_section_enter(); - - result = nrf_drv_radio802154_fsm_continuous_carrier(); - - nrf_drv_radio802154_critical_section_exit(); - return result; -} - -void nrf_drv_radio802154_request_buffer_free(uint8_t * p_data) -{ - nrf_drv_radio802154_critical_section_enter(); - - nrf_drv_radio802154_fsm_notify_buffer_free((rx_buffer_t *)p_data); - - nrf_drv_radio802154_critical_section_exit(); -} - -void nrf_drv_radio802154_request_channel_update(void) -{ - nrf_drv_radio802154_critical_section_enter(); - - nrf_drv_radio802154_fsm_channel_update(); - - nrf_drv_radio802154_critical_section_exit(); -} - -void nrf_drv_radio802154_request_cca_cfg_update(void) -{ - nrf_drv_radio802154_critical_section_enter(); - - nrf_drv_radio802154_fsm_cca_cfg_update(); - - nrf_drv_radio802154_critical_section_exit(); -} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_swi.c deleted file mode 100644 index 9be1994b4..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_swi.c +++ /dev/null @@ -1,236 +0,0 @@ - -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements requests to the driver triggered by the MAC layer through SWI. - * - */ - -#include "nrf_drv_radio802154_request.h" - -#include -#include -#include - -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_critical_section.h" -#include "nrf_drv_radio802154_debug.h" -#include "nrf_drv_radio802154_fsm.h" -#include "nrf_drv_radio802154_rx_buffer.h" -#include "nrf_drv_radio802154_swi.h" -#include "hal/nrf_radio.h" - -#include -#include - -#define CMSIS_IRQ_NUM_VECTACTIVE_DIFF 16 - -/** Check if active vector priority is high enough to call requests directly. - * - * @retval true Active vector priority is greater or equal to SWI priority. - * @retval false Active vector priority is lower than SWI priority. - */ -static bool active_vector_priority_is_high(void) -{ - uint32_t active_vector_id = (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos; - IRQn_Type irq_number; - uint32_t active_priority; - - // Check if this function is called from main thread. - if (active_vector_id == 0) - { - return false; - } - - assert(active_vector_id >= CMSIS_IRQ_NUM_VECTACTIVE_DIFF); - - irq_number = (IRQn_Type)(active_vector_id - CMSIS_IRQ_NUM_VECTACTIVE_DIFF); - active_priority = NVIC_GetPriority(irq_number); - - return active_priority <= NRF_DRV_RADIO802154_NOTIFICATION_SWI_PRIORITY; -} - -void nrf_drv_radio802154_request_init(void) -{ - nrf_drv_radio802154_swi_init(); -} - -bool nrf_drv_radio802154_request_sleep(void) -{ - bool result = false; - - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - result = nrf_drv_radio802154_fsm_sleep(); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_sleep(&result); - } - - return result; -} - -bool nrf_drv_radio802154_request_receive(void) -{ - bool result = false; - - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - result = nrf_drv_radio802154_fsm_receive(); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_receive(&result); - } - - return result; -} - -bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, bool cca) -{ - bool result = false; - - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - result = nrf_drv_radio802154_fsm_transmit(p_data, cca); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_transmit(p_data, cca, &result); - } - - return result; -} - -bool nrf_drv_radio802154_request_energy_detection(uint32_t time_us) -{ - bool result = false; - - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - result = nrf_drv_radio802154_fsm_energy_detection(time_us); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_energy_detection(time_us, &result); - } - - return result; -} - -bool nrf_drv_radio802154_request_cca(void) -{ - bool result = false; - - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - result = nrf_drv_radio802154_fsm_cca(); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_cca(&result); - } - - return result; -} - -bool nrf_drv_radio802154_request_continuous_carrier(void) -{ - bool result = false; - - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - result = nrf_drv_radio802154_fsm_continuous_carrier(); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_continuous_carrier(&result); - } - - return result; -} - -void nrf_drv_radio802154_request_buffer_free(uint8_t * p_data) -{ - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - nrf_drv_radio802154_fsm_notify_buffer_free((rx_buffer_t *)p_data); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_buffer_free(p_data); - } -} - -void nrf_drv_radio802154_request_channel_update(void) -{ - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - nrf_drv_radio802154_fsm_channel_update(); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_channel_update(); - } -} - -void nrf_drv_radio802154_request_cca_cfg_update(void) -{ - if (active_vector_priority_is_high()) - { - nrf_drv_radio802154_critical_section_enter(); - nrf_drv_radio802154_fsm_cca_cfg_update(); - nrf_drv_radio802154_critical_section_exit(); - } - else - { - nrf_drv_radio802154_swi_cca_cfg_update(); - } -} - diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c deleted file mode 100644 index bdc437803..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c +++ /dev/null @@ -1,673 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * This file implements SWI manager for nRF 802.15.4 driver. - * - */ - -#include "nrf_drv_radio802154_swi.h" - -#include -#include -#include - -#include "nrf_drv_radio802154.h" -#include "nrf_drv_radio802154_config.h" -#include "nrf_drv_radio802154_critical_section.h" -#include "nrf_drv_radio802154_fsm.h" -#include "nrf_drv_radio802154_rx_buffer.h" -#include "hal/nrf_egu.h" -#include "raal/nrf_raal_api.h" - -#include - -/** Size of notification queue. - * - * One slot for each receive buffer, one for transmission, one for busy channel and one for energy - * detection. - */ -#define NTF_QUEUE_SIZE (NRF_DRV_RADIO802154_RX_BUFFERS + 3) -/** Size of requests queue. - * - * Two is minimal queue size. It is not expected in current implementation to queue a few requests. - */ -#define REQ_QUEUE_SIZE 2 - -#define SWI_EGU NRF_EGU3 ///< Label of SWI peripheral. -#define SWI_IRQn SWI3_EGU3_IRQn ///< Symbol of SWI IRQ number. -#define SWI_IRQHandler SWI3_EGU3_IRQHandler ///< Symbol of SWI IRQ handler. - -#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt. -#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task. -#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event. - -#define TIMESLOT_EXIT_INT NRF_EGU_INT_TRIGGERED1 ///< Label of timeslot exit interrupt. -#define TIMESLOT_EXIT_TASK NRF_EGU_TASK_TRIGGER1 ///< Label of timeslot exit task. -#define TIMESLOT_EXIT_EVENT NRF_EGU_EVENT_TRIGGERED1 ///< Label of timeslot exit event. - -#define REQ_INT NRF_EGU_INT_TRIGGERED2 ///< Label of request interrupt. -#define REQ_TASK NRF_EGU_TASK_TRIGGER2 ///< Label of request task. -#define REQ_EVENT NRF_EGU_EVENT_TRIGGERED2 ///< Label of request event. - -/// Types of notifications in notification queue. -typedef enum -{ - NTF_TYPE_RECEIVED, ///< Frame received - NTF_TYPE_RECEIVE_FAILED, ///< Frame reception failed - NTF_TYPE_TRANSMITTED, ///< Frame transmitted - NTF_TYPE_TRANSMIT_FAILED, ///< Frame transmission failure - NTF_TYPE_ENERGY_DETECTED, ///< Energy detection procedure ended - NTF_TYPE_CCA, ///< CCA procedure ended -} nrf_drv_radio802154_ntf_type_t; - -/// Notification data in the notification queue. -typedef struct -{ - nrf_drv_radio802154_ntf_type_t type; ///< Notification type. - union - { - struct - { - uint8_t * p_psdu; ///< Pointer to received frame PSDU. - int8_t power; ///< RSSI of received frame. - int8_t lqi; ///< LQI of received frame. - } received; ///< Received frame details. - - struct - { - uint8_t * p_psdu; ///< Pointer to received ACK PSDU or NULL. - int8_t power; ///< RSSI of received ACK or 0. - int8_t lqi; ///< LQI of received ACK or 0. - } transmitted; ///< Transmitted frame details. - - struct - { - nrf_drv_radio802154_tx_error_t error; ///< An error code that indicates reason of the failure. - } transmit_failed; - - struct - { - nrf_drv_radio802154_rx_error_t error; ///< An error code that indicates reason of the failure. - } receive_failed; - - struct - { - int8_t result; ///< Energy detection result. - } energy_detected; ///< Energy detection details. - - struct - { - bool result; ///< CCA result. - } cca; ///< CCA details. - } data; ///< Notification data depending on it's type. -} nrf_drv_radio802154_ntf_data_t; - -/// Type of requests in request queue. -typedef enum -{ - REQ_TYPE_SLEEP, - REQ_TYPE_RECEIVE, - REQ_TYPE_TRANSMIT, - REQ_TYPE_ENERGY_DETECTION, - REQ_TYPE_CCA, - REQ_TYPE_CONTINUOUS_CARRIER, - REQ_TYPE_BUFFER_FREE, - REQ_TYPE_CHANNEL_UPDATE, - REQ_TYPE_CCA_CFG_UPDATE -} nrf_drv_radio802154_req_type_t; - -/// Request data in request queue. -typedef struct -{ - nrf_drv_radio802154_req_type_t type; ///< Type of the request. - union - { - struct - { - bool * p_result; ///< Sleep request result. - } sleep; ///< Sleep request details. - - struct - { - bool * p_result; ///< Receive request result. - } receive; ///< Receive request details. - - struct - { - bool * p_result; ///< Transmit request result. - const uint8_t * p_data; ///< Pointer to PSDU to transmit. - bool cca; ///< If CCA was requested prior to transmission. - } transmit; ///< Transmit request details. - - struct - { - bool * p_result; ///< Energy detection request result. - uint32_t time_us; ///< Requested time of energy detection procedure. - } energy_detection; ///< Energy detection request details. - - struct - { - bool * p_result; ///< CCA request result. - } cca; ///< CCA request details. - - struct - { - bool * p_result; ///< Continuous carrier request result. - } continuous_carrier; ///< Continuous carrier request details. - - struct - { - rx_buffer_t * p_data; ///< Pointer to receive buffer to free. - } buffer_free; ///< Buffer free request details. - } data; ///< Request data depending on it's type. -} nrf_drv_radio802154_req_data_t; - -static nrf_drv_radio802154_ntf_data_t m_ntf_queue[NTF_QUEUE_SIZE]; ///< Notification queue. -static uint8_t m_ntf_r_ptr; ///< Notification queue read index. -static uint8_t m_ntf_w_ptr; ///< Notification queue write index. - -static nrf_drv_radio802154_req_data_t m_req_queue[REQ_QUEUE_SIZE]; ///< Request queue. -static uint8_t m_req_r_ptr; // Request queue read index. -static uint8_t m_req_w_ptr; // Request queue write index. - -/** - * Increment given index for any queue. - * - * @param[inout] p_ptr Index to increment. - * @param[in] queue_size Number of elements in the queue. - */ -static void queue_ptr_increment(uint8_t * p_ptr, uint8_t queue_size) -{ - if (++(*p_ptr) >= queue_size) - { - *p_ptr = 0; - } -} - -/** - * Check if given queue is full. - * - * @param[in] r_ptr Read index associated with given queue. - * @param[in] w_ptr Write index associated with given queue. - * @param[in] queue_size Number of elements in the queue. - * - * @retval true Given queue is full. - * @retval false Given queue is not full. - */ -static bool queue_is_full(uint8_t r_ptr, uint8_t w_ptr, uint8_t queue_size) -{ - if (w_ptr == (r_ptr - 1)) - { - return true; - } - - if ((r_ptr == 0) && (w_ptr == queue_size - 1)) - { - return true; - } - - return false; -} - -/** - * Check if given queue is empty. - * - * @param[in] r_ptr Read index associated with given queue. - * @param[in] w_ptr Write index associated with given queue. - * - * @retval true Given queue is empty. - * @retval false Given queue is not empty. - */ -static bool queue_is_empty(uint8_t r_ptr, uint8_t w_ptr) -{ - return (r_ptr == w_ptr); -} - -/** - * Increment given index associated with notification queue. - * - * @param[inout] p_ptr Pointer to the index to increment. - */ -static void ntf_queue_ptr_increment(uint8_t * p_ptr) -{ - queue_ptr_increment(p_ptr, NTF_QUEUE_SIZE); -} - -/** - * Check if notification queue is full. - * - * @retval true Notification queue is full. - * @retval false Notification queue is not full. - */ -static bool ntf_queue_is_full(void) -{ - return queue_is_full(m_ntf_r_ptr, m_ntf_w_ptr, NTF_QUEUE_SIZE); -} - -/** - * Check if notification queue is empty. - * - * @retval true Notification queue is empty. - * @retval false Notification queue is not empty. - */ -static bool ntf_queue_is_empty(void) -{ - return queue_is_empty(m_ntf_r_ptr, m_ntf_w_ptr); -} - -/** - * Increment given index associated with request queue. - * - * @param[inout] p_ptr Pointer to the index to increment. - */ -static void req_queue_ptr_increment(uint8_t * p_ptr) -{ - queue_ptr_increment(p_ptr, REQ_QUEUE_SIZE); -} - -/** - * Check if request queue is full. - * - * @retval true Request queue is full. - * @retval false Request queue is not full. - */ -static bool req_queue_is_full(void) -{ - return queue_is_full(m_req_r_ptr, m_req_w_ptr, REQ_QUEUE_SIZE); -} - -/** - * Check if request queue is empty. - * - * @retval true Request queue is empty. - * @retval false Request queue is not empty. - */ -static bool req_queue_is_empty(void) -{ - return queue_is_empty(m_req_r_ptr, m_req_w_ptr); -} - -/** - * Enter request block. - * - * This is a helper function used in all request functions to atomically - * find an empty slot in request queue and allow atomic slot update. - * - * @return Pointer to an empty slot in the request queue. - */ -static nrf_drv_radio802154_req_data_t * req_enter(void) -{ - __disable_irq(); - __DSB(); - __ISB(); - - assert(!req_queue_is_full()); - - return &m_req_queue[m_req_w_ptr]; -} - -/** - * Exit request block. - * - * This is a helper function used in all request functions to end atomic slot update - * and trigger SWI to process the request from the slot. - */ -static void req_exit(void) -{ - req_queue_ptr_increment(&m_req_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, REQ_TASK); - - __enable_irq(); - __DSB(); - __ISB(); -} - -void nrf_drv_radio802154_swi_init(void) -{ - m_ntf_r_ptr = 0; - m_ntf_w_ptr = 0; - - nrf_egu_int_enable(SWI_EGU, - NTF_INT | - TIMESLOT_EXIT_INT | - REQ_INT); - - NVIC_SetPriority(SWI_IRQn, NRF_DRV_RADIO802154_NOTIFICATION_SWI_PRIORITY); - NVIC_ClearPendingIRQ(SWI_IRQn); - NVIC_EnableIRQ(SWI_IRQn); -} - -void nrf_drv_radio802154_swi_notify_received(uint8_t * p_data, int8_t power, int8_t lqi) -{ - assert(!ntf_queue_is_full()); - - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - - p_slot->type = NTF_TYPE_RECEIVED; - p_slot->data.received.p_psdu = p_data; - p_slot->data.received.power = power; - p_slot->data.received.lqi = lqi; - - ntf_queue_ptr_increment(&m_ntf_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, NTF_TASK); -} - -void nrf_drv_radio802154_swi_notify_receive_failed(nrf_drv_radio802154_rx_error_t error) -{ - assert(!ntf_queue_is_full()); - - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - - p_slot->type = NTF_TYPE_RECEIVE_FAILED; - p_slot->data.receive_failed.error = error; - - ntf_queue_ptr_increment(&m_ntf_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, NTF_TASK); -} - -void nrf_drv_radio802154_swi_notify_transmitted(uint8_t * p_data, int8_t power, int8_t lqi) -{ - assert(!ntf_queue_is_full()); - - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - - p_slot->type = NTF_TYPE_TRANSMITTED; - p_slot->data.transmitted.p_psdu = p_data; - p_slot->data.transmitted.power = power; - p_slot->data.transmitted.lqi = lqi; - - ntf_queue_ptr_increment(&m_ntf_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, NTF_TASK); -} - -void nrf_drv_radio802154_swi_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error) -{ - assert(!ntf_queue_is_full()); - - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - - p_slot->type = NTF_TYPE_TRANSMIT_FAILED; - p_slot->data.transmit_failed.error = error; - - ntf_queue_ptr_increment(&m_ntf_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, NTF_TASK); -} - -void nrf_drv_radio802154_swi_notify_energy_detected(uint8_t result) -{ - assert(!ntf_queue_is_full()); - - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - - p_slot->type = NTF_TYPE_ENERGY_DETECTED; - p_slot->data.energy_detected.result = result; - - ntf_queue_ptr_increment(&m_ntf_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, NTF_TASK); -} - -void nrf_drv_radio802154_swi_notify_cca(bool channel_free) -{ - assert(!ntf_queue_is_full()); - - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - - p_slot->type = NTF_TYPE_CCA; - p_slot->data.cca.result = channel_free; - - ntf_queue_ptr_increment(&m_ntf_w_ptr); - - nrf_egu_task_trigger(SWI_EGU, NTF_TASK); -} - -void nrf_drv_radio802154_swi_timeslot_exit(void) -{ - assert(!nrf_egu_event_check(SWI_EGU, TIMESLOT_EXIT_EVENT)); - - nrf_egu_task_trigger(SWI_EGU, TIMESLOT_EXIT_TASK); -} - -void nrf_drv_radio802154_swi_sleep(bool * p_result) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_SLEEP; - p_slot->data.sleep.p_result = p_result; - - req_exit(); -} - -void nrf_drv_radio802154_swi_receive(bool * p_result) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_RECEIVE; - p_slot->data.receive.p_result = p_result; - - req_exit(); -} - -void nrf_drv_radio802154_swi_transmit(const uint8_t * p_data, bool cca, bool * p_result) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_TRANSMIT; - p_slot->data.transmit.p_data = p_data; - p_slot->data.transmit.cca = cca; - p_slot->data.transmit.p_result = p_result; - - req_exit(); -} - -void nrf_drv_radio802154_swi_energy_detection(uint32_t time_us, bool * p_result) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_ENERGY_DETECTION; - p_slot->data.energy_detection.time_us = time_us; - p_slot->data.energy_detection.p_result = p_result; - - req_exit(); -} - -void nrf_drv_radio802154_swi_cca(bool * p_result) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_CCA; - p_slot->data.cca.p_result = p_result; - - req_exit(); -} - -void nrf_drv_radio802154_swi_continuous_carrier(bool * p_result) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_CONTINUOUS_CARRIER; - p_slot->data.continuous_carrier.p_result = p_result; - - req_exit(); -} - -void nrf_drv_radio802154_swi_buffer_free(uint8_t * p_data) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_BUFFER_FREE; - p_slot->data.buffer_free.p_data = (rx_buffer_t *)p_data; - - req_exit(); -} - -void nrf_drv_radio802154_swi_channel_update(void) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_CHANNEL_UPDATE; - - req_exit(); -} - -void nrf_drv_radio802154_swi_cca_cfg_update(void) -{ - nrf_drv_radio802154_req_data_t * p_slot = req_enter(); - - p_slot->type = REQ_TYPE_CCA_CFG_UPDATE; - - req_exit(); -} - -void SWI_IRQHandler(void) -{ - if (nrf_egu_event_check(SWI_EGU, NTF_EVENT)) - { - nrf_egu_event_clear(SWI_EGU, NTF_EVENT); - - while (!ntf_queue_is_empty()) - { - nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_r_ptr]; - - switch (p_slot->type) - { - case NTF_TYPE_RECEIVED: - nrf_drv_radio802154_received_raw(p_slot->data.received.p_psdu, - p_slot->data.received.power, - p_slot->data.received.lqi); - break; - - case NTF_TYPE_RECEIVE_FAILED: - nrf_drv_radio802154_receive_failed(p_slot->data.receive_failed.error); - break; - - case NTF_TYPE_TRANSMITTED: - nrf_drv_radio802154_transmitted_raw(p_slot->data.transmitted.p_psdu, - p_slot->data.transmitted.power, - p_slot->data.transmitted.lqi); - break; - - case NTF_TYPE_TRANSMIT_FAILED: - nrf_drv_radio802154_transmit_failed(p_slot->data.transmit_failed.error); - break; - - case NTF_TYPE_ENERGY_DETECTED: - nrf_drv_radio802154_energy_detected(p_slot->data.energy_detected.result); - break; - - case NTF_TYPE_CCA: - nrf_drv_radio802154_cca_done(p_slot->data.cca.result); - break; - - default: - assert(false); - } - - ntf_queue_ptr_increment(&m_ntf_r_ptr); - } - } - - if (nrf_egu_event_check(SWI_EGU, TIMESLOT_EXIT_EVENT)) - { - nrf_raal_continuous_mode_exit(); - - nrf_egu_event_clear(SWI_EGU, TIMESLOT_EXIT_EVENT); - } - - if (nrf_egu_event_check(SWI_EGU, REQ_EVENT)) - { - nrf_egu_event_clear(SWI_EGU, REQ_EVENT); - - while (!req_queue_is_empty()) - { - nrf_drv_radio802154_req_data_t * p_slot = &m_req_queue[m_req_r_ptr]; - - nrf_drv_radio802154_critical_section_enter(); - - switch (p_slot->type) - { - case REQ_TYPE_SLEEP: - *(p_slot->data.sleep.p_result) = nrf_drv_radio802154_fsm_sleep(); - break; - - case REQ_TYPE_RECEIVE: - *(p_slot->data.receive.p_result) = nrf_drv_radio802154_fsm_receive(); - break; - - case REQ_TYPE_TRANSMIT: - *(p_slot->data.transmit.p_result) = nrf_drv_radio802154_fsm_transmit( - p_slot->data.transmit.p_data, - p_slot->data.transmit.cca); - break; - - case REQ_TYPE_ENERGY_DETECTION: - *(p_slot->data.energy_detection.p_result) = - nrf_drv_radio802154_fsm_energy_detection( - p_slot->data.energy_detection.time_us); - break; - - case REQ_TYPE_CCA: - *(p_slot->data.cca.p_result) = nrf_drv_radio802154_fsm_cca(); - break; - - case REQ_TYPE_CONTINUOUS_CARRIER: - *(p_slot->data.continuous_carrier.p_result) = - nrf_drv_radio802154_fsm_continuous_carrier(); - break; - - case REQ_TYPE_BUFFER_FREE: - nrf_drv_radio802154_fsm_notify_buffer_free(p_slot->data.buffer_free.p_data); - break; - - case REQ_TYPE_CHANNEL_UPDATE: - nrf_drv_radio802154_fsm_channel_update(); - break; - - case REQ_TYPE_CCA_CFG_UPDATE: - nrf_drv_radio802154_fsm_cca_cfg_update(); - break; - - default: - assert(false); - } - - nrf_drv_radio802154_critical_section_exit(); - - req_queue_ptr_increment(&m_req_r_ptr); - } - } -} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h deleted file mode 100644 index 2b08180ca..000000000 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NRF_DRIVER_RADIO802154_SWI_H__ -#define NRF_DRIVER_RADIO802154_SWI_H__ - -#include -#include - -#include "nrf_drv_radio802154.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup nrf_driver_radio802154_swi 802.15.4 driver SWI management - * @{ - * @ingroup nrf_driver_radio802154 - * @brief SWI manager for 802.15.4 driver. - */ - -/** - * @brief Initialize SWI module. - */ -void nrf_drv_radio802154_swi_init(void); - -/** - * @brief Notify next higher layer that a frame was received from SWI priority level. - * - * @param[in] p_data Array of bytes containing PSDU. First byte contains frame length, other contain the frame itself. - * @param[in] power RSSI measured during the frame reception. - * @param[in] lqi LQI indicating measured link quality during the frame reception. - */ -void nrf_drv_radio802154_swi_notify_received(uint8_t * p_data, int8_t power, int8_t lqi); - -/** - * @brief Notify next higher layer that reception of a frame failed. - * - * @param[in] error An error code that indicates reason of the failure. - */ -void nrf_drv_radio802154_swi_notify_receive_failed(nrf_drv_radio802154_rx_error_t error); - -/** - * @brief Notify next higher layer that a frame was transmitted from SWI priority level. - * - * @param[in] p_ack Pointer to buffer containing PSDU of ACK frame. NULL if ACK was not requested. - * @param[in] power RSSI of received frame or 0 if ACK was not requested. - * @param[in] lqi LQI of received frame of 0 if ACK was not requested. - */ -void nrf_drv_radio802154_swi_notify_transmitted(uint8_t * p_data, int8_t power, int8_t lqi); - -/** - * @brief Notify next higher layer that a frame was not transmitted from SWI priority level. - * - * @param[in] error Reason of the transmission failure. - */ -void nrf_drv_radio802154_swi_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error); - -/** - * @brief Notify next higher layer that energy detection procedure ended from SWI priority level. - * - * @param[in] result Detected energy level. - */ -void nrf_drv_radio802154_swi_notify_energy_detected(uint8_t result); - -/** - * @brief Notify next higher layer that CCA procedure ended from SWI priority level. - * - * @param[in] channel_free If detected free channel. - */ -void nrf_drv_radio802154_swi_notify_cca(bool channel_free); - -/** - * @brief Request discarding of the timeslot from SWI priority level. - * - * @note This function should be called through notification module to prevent calling it from arbiter context. - */ -void nrf_drv_radio802154_swi_timeslot_exit(void); - -/** - * @brief Request entering sleep state from SWI priority. - * - * @param[out] p_result Result of entering sleep state. - */ -void nrf_drv_radio802154_swi_sleep(bool * p_result); - -/** - * @brief Request entering receive state from SWI priority. - * - * @param[out] p_result Result of entering receive state. - */ -void nrf_drv_radio802154_swi_receive(bool * p_result); - -/** - * @biref Request entering transmit state from SWI priority. - * - * @param[in] p_data Pointer to PSDU of the frame to transmit. - * @param[in] cca If the driver should perform CCA procedure before transmission. - * @param[out] p_result Result of entering transmit state. - */ -void nrf_drv_radio802154_swi_transmit(const uint8_t * p_data, bool cca, bool * p_result); - -/** - * @brief Request entering energy detection state from SWI priority. - * - * @param[in] time_us Requested duration of energy detection procedure. - * @param[out] p_result Result of entering energy detection state. - */ -void nrf_drv_radio802154_swi_energy_detection(uint32_t time_us, bool * p_result); - -/** - * @brief Request entering CCA state from SWI priority. - * - * @param[out] p_result Result of entering CCA state. - */ -void nrf_drv_radio802154_swi_cca(bool * p_result); - -/** - * @brief Request entering continuous carrier state from SWI priority. - * - * @param[out] p_result Result of entering continuous carrier state. - */ -void nrf_drv_radio802154_swi_continuous_carrier(bool * p_result); - -/** - * @brief Notify FSM that given buffer is not used anymore and can be freed. - * - * @param[in] p_data Pointer to the buffer to free. - */ -void nrf_drv_radio802154_swi_buffer_free(uint8_t * p_data); - -/** - * @brief Notify FSM that the next higher layer requested channel change. - */ -void nrf_drv_radio802154_swi_channel_update(void); - -/** - * @brief Notify FSM that the next higher layer requested CCA configuration change. - */ -void nrf_drv_radio802154_swi_cca_cfg_update(void); - -/** - *@} - **/ - -#ifdef __cplusplus -} -#endif - -#endif // NRF_DRIVER_RADIO802154_SWI_H__ diff --git a/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock.h b/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock.h similarity index 77% rename from third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock.h rename to third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock.h index 1e6c8f40e..8c9bf88e6 100644 --- a/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock.h +++ b/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,8 +40,8 @@ * */ -#ifndef NRF_DRV_RADIO802154_CLOCK_H_ -#define NRF_DRV_RADIO802154_CLOCK_H_ +#ifndef NRF_802154_CLOCK_H_ +#define NRF_802154_CLOCK_H_ #include @@ -50,9 +50,9 @@ extern "C" { #endif /** - * @defgroup nrf_drv_radio802154_clock Clock Abstraction Layer for the 802.15.4 driver + * @defgroup nrf_802154_clock Clock Abstraction Layer for the 802.15.4 driver * @{ - * @ingroup nrf_drv_radio802154_clock + * @ingroup nrf_802154_clock * @brief Clock Abstraction Layer interface for the 802.15.4 driver. * */ @@ -60,25 +60,25 @@ extern "C" { /** * @brief Initialize the clock driver. */ -void nrf_drv_radio802154_clock_init(void); +void nrf_802154_clock_init(void); /** * @brief Deinitialize the clock driver. */ -void nrf_drv_radio802154_clock_deinit(void); +void nrf_802154_clock_deinit(void); /** * @brief Start High Frequency Clock. * * This function is asynchronous. It should request ramping up of HF clock and exit. When HF clock - * is ready @sa nrf_drv_radio802154_hfclk_ready() should be called. + * is ready @sa nrf_802154_hfclk_ready() should be called. */ -void nrf_drv_radio802154_clock_hfclk_start(void); +void nrf_802154_clock_hfclk_start(void); /** * @brief Stop High Frequency Clock. */ -void nrf_drv_radio802154_clock_hfclk_stop(void); +void nrf_802154_clock_hfclk_stop(void); /** * @brief Check if High Frequency Clock is running. @@ -86,20 +86,20 @@ void nrf_drv_radio802154_clock_hfclk_stop(void); * @retval true If High Frequency Clock is running. * @retval false If High Frequency Clock is not running. */ -bool nrf_drv_radio802154_clock_hfclk_is_running(void); +bool nrf_802154_clock_hfclk_is_running(void); /** * @brief Start Low Frequency Clock. * * This function is asynchronous. It should request ramping up of LF clock and exit. When LF clock - * is ready @sa nrf_drv_radio802154_lfclk_ready() should be called. + * is ready @sa nrf_802154_lfclk_ready() should be called. */ -void nrf_drv_radio802154_clock_lfclk_start(void); +void nrf_802154_clock_lfclk_start(void); /** * @brief Stop Low Frequency Clock. */ -void nrf_drv_radio802154_clock_lfclk_stop(void); +void nrf_802154_clock_lfclk_stop(void); /** * @brief Check if Low Frequency Clock is running. @@ -107,17 +107,17 @@ void nrf_drv_radio802154_clock_lfclk_stop(void); * @retval true If Low Frequency Clock is running. * @retval false If Low Frequency Clock is not running. */ -bool nrf_drv_radio802154_clock_lfclk_is_running(void); +bool nrf_802154_clock_lfclk_is_running(void); /** * @brief Callback executed when High Frequency Clock is ready. */ -extern void nrf_drv_radio802154_clock_hfclk_ready(void); +extern void nrf_802154_clock_hfclk_ready(void); /** * @brief Callback executed when Low Frequency Clock is ready. */ -extern void nrf_drv_radio802154_clock_lfclk_ready(void); +extern void nrf_802154_clock_lfclk_ready(void); /** *@} @@ -127,4 +127,4 @@ extern void nrf_drv_radio802154_clock_lfclk_ready(void); } #endif -#endif /* NRF_DRV_RADIO802154_CLOCK_H_ */ +#endif /* NRF_802154_CLOCK_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_nodrv.c b/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_nodrv.c similarity index 79% rename from third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_nodrv.c rename to third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_nodrv.c index 2d791128a..33cda54b6 100644 --- a/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_nodrv.c +++ b/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_nodrv.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,16 +35,18 @@ * This implementation uses directly CLOCK hardware registers. */ -#include "nrf_drv_radio802154_clock.h" +#include "nrf_802154_clock.h" #include #include -#include "nrf_drv_radio802154_config.h" +#include "nrf_802154_config.h" -void nrf_drv_radio802154_clock_init(void) +void nrf_802154_clock_init(void) { - NVIC_SetPriority(POWER_CLOCK_IRQn, NRF_DRV_RADIO802154_CLOCK_IRQ_PRIORITY); + nrf_clock_lf_src_set(NRF_802154_CLOCK_LFCLK_SOURCE); + + NVIC_SetPriority(POWER_CLOCK_IRQn, NRF_802154_CLOCK_IRQ_PRIORITY); NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn); NVIC_EnableIRQ(POWER_CLOCK_IRQn); @@ -52,7 +54,7 @@ void nrf_drv_radio802154_clock_init(void) nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK); } -void nrf_drv_radio802154_clock_deinit(void) +void nrf_802154_clock_deinit(void) { NVIC_DisableIRQ(POWER_CLOCK_IRQn); NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn); @@ -61,34 +63,34 @@ void nrf_drv_radio802154_clock_deinit(void) nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK); } -void nrf_drv_radio802154_clock_hfclk_start(void) +void nrf_802154_clock_hfclk_start(void) { nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART); } -void nrf_drv_radio802154_clock_hfclk_stop(void) +void nrf_802154_clock_hfclk_stop(void) { nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP); } -bool nrf_drv_radio802154_clock_hfclk_is_running(void) +bool nrf_802154_clock_hfclk_is_running(void) { return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY); } -void nrf_drv_radio802154_clock_lfclk_start(void) +void nrf_802154_clock_lfclk_start(void) { nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED); nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART); } -void nrf_drv_radio802154_clock_lfclk_stop(void) +void nrf_802154_clock_lfclk_stop(void) { nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP); } -bool nrf_drv_radio802154_clock_lfclk_is_running(void) +bool nrf_802154_clock_lfclk_is_running(void) { return nrf_clock_lf_is_running(); } @@ -99,23 +101,23 @@ void POWER_CLOCK_IRQHandler(void) { nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); - nrf_drv_radio802154_clock_hfclk_ready(); + nrf_802154_clock_hfclk_ready(); } if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED)) { nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED); - nrf_drv_radio802154_clock_lfclk_ready(); + nrf_802154_clock_lfclk_ready(); } } -__WEAK void nrf_drv_radio802154_clock_hfclk_ready(void) +__WEAK void nrf_802154_clock_hfclk_ready(void) { // Intentionally empty. } -__WEAK void nrf_drv_radio802154_clock_lfclk_ready(void) +__WEAK void nrf_802154_clock_lfclk_ready(void) { // Intentionally empty. } diff --git a/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_sdk.c b/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_sdk.c similarity index 79% rename from third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_sdk.c rename to third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_sdk.c index ff23df8b7..de1173fe2 100644 --- a/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_drv_radio802154_clock_sdk.c +++ b/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_sdk.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,7 +35,7 @@ * This implementation uses clock driver implementation from SDK. */ -#include "nrf_drv_radio802154_clock.h" +#include "nrf_802154_clock.h" #include @@ -54,61 +54,61 @@ static void clock_handler(nrf_drv_clock_evt_type_t event) { if (event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) { - nrf_drv_radio802154_clock_hfclk_ready(); + nrf_802154_clock_hfclk_ready(); } if (event == NRF_DRV_CLOCK_EVT_LFCLK_STARTED) { - nrf_drv_radio802154_clock_lfclk_ready(); + nrf_802154_clock_lfclk_ready(); } } -void nrf_drv_radio802154_clock_init(void) +void nrf_802154_clock_init(void) { nrf_drv_clock_init(); } -void nrf_drv_radio802154_clock_deinit(void) +void nrf_802154_clock_deinit(void) { nrf_drv_clock_uninit(); } -void nrf_drv_radio802154_clock_hfclk_start(void) +void nrf_802154_clock_hfclk_start(void) { nrf_drv_clock_hfclk_request(&m_clock_handler); } -void nrf_drv_radio802154_clock_hfclk_stop(void) +void nrf_802154_clock_hfclk_stop(void) { nrf_drv_clock_hfclk_release(); } -bool nrf_drv_radio802154_clock_hfclk_is_running(void) +bool nrf_802154_clock_hfclk_is_running(void) { return nrf_drv_clock_hfclk_is_running(); } -void nrf_drv_radio802154_clock_lfclk_start(void) +void nrf_802154_clock_lfclk_start(void) { nrf_drv_clock_lfclk_request(&m_clock_handler); } -void nrf_drv_radio802154_clock_lfclk_stop(void) +void nrf_802154_clock_lfclk_stop(void) { nrf_drv_clock_lfclk_release(); } -bool nrf_drv_radio802154_clock_lfclk_is_running(void) +bool nrf_802154_clock_lfclk_is_running(void) { return nrf_drv_clock_lfclk_is_running(); } -__WEAK void nrf_drv_radio802154_clock_hfclk_ready(void) +__WEAK void nrf_802154_clock_hfclk_ready(void) { // Intentionally empty. } -__WEAK void nrf_drv_radio802154_clock_lfclk_ready(void) +__WEAK void nrf_802154_clock_lfclk_ready(void) { // Intentionally empty. } diff --git a/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer.h b/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer.h similarity index 71% rename from third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer.h rename to third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer.h index ecd1a90c6..c0ff11e98 100644 --- a/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer.h +++ b/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,8 +33,8 @@ * */ -#ifndef NRF_DRV_RADIO802154_TIMER_API_H_ -#define NRF_DRV_RADIO802154_TIMER_API_H_ +#ifndef NRF_802154_TIMER_API_H_ +#define NRF_802154_TIMER_API_H_ #include #include @@ -44,9 +44,9 @@ extern "C" { #endif /** - * @defgroup nrf_drv_radio802154_timer Timer Abstraction Layer for the 802.15.4 driver + * @defgroup nrf_802154_timer Timer Abstraction Layer for the 802.15.4 driver * @{ - * @ingroup nrf_drv_radio802154_timer + * @ingroup nrf_802154_timer * @brief Timer Abstraction Layer interface for the 802.15.4 driver. * * Timer Abstraction Layer is an abstraction layer of timer that is meant to be used by @@ -61,51 +61,51 @@ extern "C" { * @note Most of Timer Abstraction Layer API should not be called directly by 802.15.4 driver * modules. This API is used by the Timer Scheduler module included in the driver and other * modules should use Timer Scheduler API. Exception from above rule are initialization and - * deinitialization functions @sa nrf_drv_radio802154_timer_init() - * @sa nrf_drv_radio802154_timer_deinit() and critical section management - * @sa nrf_drv_radio802154_timer_critical_section_enter() - * @sa nrf_drv_radio802154_timer_critical_section_exit() as these functions are called from - * nrf_drv_radio802154_critical_section module and from global initialization functions - * @sa nrf_drv_radio802154_init() @sa nrf_drv_radio802154_deinit(). + * deinitialization functions @sa nrf_802154_timer_init() + * @sa nrf_802154_timer_deinit() and critical section management + * @sa nrf_802154_timer_critical_section_enter() + * @sa nrf_802154_timer_critical_section_exit() as these functions are called from + * nrf_802154_critical_section module and from global initialization functions + * @sa nrf_802154_init() @sa nrf_802154_deinit(). */ /** * @brief Initialize Timer. */ -void nrf_drv_radio802154_timer_init(void); +void nrf_802154_timer_init(void); /** * @brief Uninitialize Timer. */ -void nrf_drv_radio802154_timer_deinit(void); +void nrf_802154_timer_deinit(void); /** * @brief Enter critical section of the timer. * - * In critical section timer cannot execute @sa nrf_drv_radio802154_timer_fired() function. + * In critical section timer cannot execute @sa nrf_802154_timer_fired() function. * * @note Critical section cannot be nested. */ -void nrf_drv_radio802154_timer_critical_section_enter(void); +void nrf_802154_timer_critical_section_enter(void); /** * @brief Exit critical section of the timer. * - * In critical section timer cannot execute @sa nrf_drv_radio802154_timer_fired() function. + * In critical section timer cannot execute @sa nrf_802154_timer_fired() function. * * @note Critical section cannot be nested. */ -void nrf_drv_radio802154_timer_critical_section_exit(void); +void nrf_802154_timer_critical_section_exit(void); /** * @brief Get current time. * - * Prior to getting current time, Timer must be initialized @sa nrf_drv_radio802154_timer_init(). + * Prior to getting current time, Timer must be initialized @sa nrf_802154_timer_init(). * There are no other requirements that must be fulfilled before using this function. * * @return Current time in microseconds [us]. */ -uint32_t nrf_drv_radio802154_timer_time_get(void); +uint32_t nrf_802154_timer_time_get(void); /** * @brief Get granularity of currently used timer. @@ -114,7 +114,7 @@ uint32_t nrf_drv_radio802154_timer_time_get(void); * * @return Timer granularity in microseconds [us]. */ -uint32_t nrf_drv_radio802154_timer_granularity_get(void); +uint32_t nrf_802154_timer_granularity_get(void); /** * @brief Start one-shot timer that expires at specified time. @@ -123,18 +123,18 @@ uint32_t nrf_drv_radio802154_timer_granularity_get(void); * If timer is running when this function is called, previously running timer will be stopped * automatically. * - * On timer expiration @sa nrf_drv_radio802154_timer_fired function will be called. + * On timer expiration @sa nrf_802154_timer_fired function will be called. * Timer automatically stops after expiration. * * @param[in] t0 Number of microseconds representing timer start time. * @param[in] dt Time of timer expiration as time elapsed from @p t0 [us]. */ -void nrf_drv_radio802154_timer_start(uint32_t t0, uint32_t dt); +void nrf_802154_timer_start(uint32_t t0, uint32_t dt); /** * @brief Stop currently running timer. */ -void nrf_drv_radio802154_timer_stop(void); +void nrf_802154_timer_stop(void); /** * @brief Check if timer is currently running. @@ -142,12 +142,12 @@ void nrf_drv_radio802154_timer_stop(void); * @retval true Timer is running. * @retval false Timer is not running. */ -bool nrf_drv_radio802154_timer_is_running(void); +bool nrf_802154_timer_is_running(void); /** * @brief Callback executed when timer expires. */ -extern void nrf_drv_radio802154_timer_fired(void); +extern void nrf_802154_timer_fired(void); /** *@} @@ -157,4 +157,4 @@ extern void nrf_drv_radio802154_timer_fired(void); } #endif -#endif /* NRF_DRV_RADIO802154_TIMER_API_H_ */ +#endif /* NRF_802154_TIMER_API_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_nodrv.c b/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_nodrv.c new file mode 100644 index 000000000..d0d76f8b3 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_nodrv.c @@ -0,0 +1,411 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file contains standalone implementation of the nRF 802.15.4 timer abstraction. + * + * This implementation is built on top of the RTC peripheral. + * + */ + +#include "nrf_802154_timer.h" + +#include + +#include +#include + +#include "platform/clock/nrf_802154_clock.h" +#include "nrf_802154_config.h" + +#define RTC_COMPARE_CHANNEL 0 +#define RTC_COMPARE_INT_MASK NRF_RTC_INT_COMPARE0_MASK +#define RTC_COMPARE_EVENT NRF_RTC_EVENT_COMPARE_0 +#define RTC_COMPARE_EVENT_MASK RTC_EVTEN_COMPARE0_Msk + +#define RTC_FREQUENCY 32768ULL + +#define US_PER_S 1000000ULL +#define US_PER_TICK CEIL_DIV(US_PER_S, RTC_FREQUENCY) +#define US_PER_OVERFLOW (512UL * US_PER_S) ///< Time that has passed between overflow events. On full RTC speed, it occurs every 512 s. + +#define FREQUENCY_US_PER_S_GDD_BITS 6 ///< Number of bits to shift RTC_FREQUENCY and US_PER_S to achieve division by greatest common divisor. + +#define CEIL_DIV(A, B) (((A) + (B) - 1) / (B)) + +static volatile uint32_t m_offset_counter; ///< Counter of RTC overflows, incremented by 2 on each OVERFLOW event. +static volatile uint8_t m_mutex; ///< Mutex for write access to @ref m_offset_counter. +static volatile bool m_clock_ready; ///< Information that LFCLK is ready. +static uint64_t m_target_time; ///< Timer fire time [us]. + +static uint32_t overflow_counter_get(void); + +/** @brief Non-blocking mutex for mutual write access to @ref m_offset_counter variable. + * + * @retval true Mutex was acquired. + * @retval false Mutex could not be acquired. + */ +static inline bool mutex_get(void) +{ + do + { + volatile uint8_t mutex_value = __LDREXB(&m_mutex); + + if (mutex_value) + { + __CLREX(); + return false; + } + } + while (__STREXB(1, &m_mutex)); + + // Disable OVERFLOW interrupt to prevent lock-up in interrupt context while mutex is locked from lower priority context + // and OVERFLOW event flag is stil up. + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + __DMB(); + + return true; +} + +/** @brief Release mutex. */ +static inline void mutex_release(void) +{ + // Re-enable OVERFLOW interrupt. + nrf_rtc_int_enable(NRF_802154_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + __DMB(); + m_mutex = 0; +} + +/** @brief Check if timer shall strike. + * + * @param[in] now Current time. + * + * @retval true Timer shall strike now. + * @retval false Timer shall not strike now. + */ +static inline bool shall_strike(uint64_t now) +{ + return now >= m_target_time; +} + +/** @brief Convert time in [us] to RTC ticks. + * + * @param[in] time Time to convert. + * + * @return Time value in RTC ticks. + */ +static inline uint32_t time_to_ticks(uint64_t time) +{ + // Divide the divider and the divident by the greatest common divisor to increase capacity of the multiplication. + return (uint32_t)CEIL_DIV((time * (RTC_FREQUENCY >> FREQUENCY_US_PER_S_GDD_BITS)), + (US_PER_S >> FREQUENCY_US_PER_S_GDD_BITS)) & RTC_CC_COMPARE_Msk; +} + +/** @brief Convert RTC ticks to time in [us]. + * + * @param[in] ticks RTC ticks to convert. + * + * @return Time value in [us]. + */ +static inline uint64_t ticks_to_time(uint32_t ticks) +{ + return CEIL_DIV((US_PER_S * (uint64_t)ticks), RTC_FREQUENCY); +} + +/** @brief Get current time. + * + * @return Current time in [us]. + */ +static uint64_t time_get(void) +{ + uint32_t offset_1 = overflow_counter_get(); + + __DMB(); + + uint32_t rtc_value_1 = nrf_rtc_counter_get(NRF_802154_RTC_INSTANCE); + + __DMB(); + + uint32_t offset_2 = overflow_counter_get(); + + __DMB(); + + uint32_t rtc_value_2 = nrf_rtc_counter_get(NRF_802154_RTC_INSTANCE); + + if (offset_1 == offset_2) + { + return (uint64_t)offset_1 * US_PER_OVERFLOW + ticks_to_time(rtc_value_1); + } + else + { + return (uint64_t)offset_2 * US_PER_OVERFLOW + ticks_to_time(rtc_value_2); + } +} + +/** @brief Get current time plus 2 RTC ticks to prevent RTC compare event miss. + * + * @return Current time with RTC protection in [us]. + */ +static inline uint64_t rtc_protected_time_get(void) +{ + return time_get() + 2 * US_PER_TICK; +} + +/** @brief Get current overflow counter and handle OVERFLOW event if present. + * + * This function returns current value of m_overflow_counter variable. If OVERFLOW event is present + * while calling this function, it is handled within it. + * + * @return Current number of OVERFLOW events since platform start. + */ +static uint32_t overflow_counter_get(void) +{ + uint32_t offset; + + // Get mutual access for writing to m_offset_counter variable. + if (mutex_get()) + { + bool increasing = false; + + // Check if interrupt was handled already. + if (nrf_rtc_event_pending(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) + { + m_offset_counter++; + increasing = true; + + __DMB(); + + // Mark that interrupt was handled. + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + + // Result should be incremented. m_offset_counter will be incremented after mutex is released. + } + else + { + // Either overflow handling is not needed OR we acquired the mutex just after it was released. + // Overflow is handled after mutex is released, but it cannot be assured that m_offset_counter + // was incremented for the second time, so we increment the result here. + } + + offset = (m_offset_counter + 1) / 2; + + mutex_release(); + + if (increasing) + { + // It's virtually impossible that overflow event is pending again before next instruction is performed. It is an error condition. + assert(m_offset_counter & 0x01); + + // Increment the counter for the second time, to alloww instructions from other context get correct value of the counter. + m_offset_counter++; + } + } + else + { + // Failed to acquire mutex. + if (nrf_rtc_event_pending(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW) || (m_offset_counter & 0x01)) + { + // Lower priority context is currently incrementing m_offset_counter variable. + offset = (m_offset_counter + 2) / 2; + } + else + { + // Lower priority context has already incremented m_offset_counter variable or incrementing is not needed now. + offset = m_offset_counter / 2; + } + } + + return offset; +} + +/** @brief Handle COMPARE event. */ +static void handle_compare_match(bool skip_check) +{ + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT); + + // In case the target time was larger than single overflow, + // we should only strike the timer on final compare event. + if (skip_check || shall_strike(time_get())) + { + nrf_rtc_event_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT_MASK); + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); + + nrf_802154_timer_fired(); + } +} + +void nrf_802154_timer_init(void) +{ + m_offset_counter = 0; + m_target_time = 0; + m_clock_ready = false; + + // Setup low frequency clock. + nrf_802154_clock_lfclk_start(); + + while (!m_clock_ready) { } + + // Setup RTC timer. + NVIC_SetPriority(NRF_802154_RTC_IRQN, NRF_802154_RTC_IRQ_PRIORITY); + NVIC_ClearPendingIRQ(NRF_802154_RTC_IRQN); + NVIC_EnableIRQ(NRF_802154_RTC_IRQN); + + nrf_rtc_prescaler_set(NRF_802154_RTC_INSTANCE, 0); + + // Setup RTC events. + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + nrf_rtc_event_enable(NRF_802154_RTC_INSTANCE, RTC_EVTEN_OVRFLW_Msk); + nrf_rtc_int_enable(NRF_802154_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); + nrf_rtc_event_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT_MASK); + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT); + + // Start RTC timer. + nrf_rtc_task_trigger(NRF_802154_RTC_INSTANCE, NRF_RTC_TASK_START); +} + +void nrf_802154_timer_deinit(void) +{ + nrf_rtc_task_trigger(NRF_802154_RTC_INSTANCE, NRF_RTC_TASK_STOP); + + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); + nrf_rtc_event_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT_MASK); + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT); + + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + nrf_rtc_event_disable(NRF_802154_RTC_INSTANCE, RTC_EVTEN_OVRFLW_Msk); + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + + NVIC_DisableIRQ(NRF_802154_RTC_IRQN); + NVIC_ClearPendingIRQ(NRF_802154_RTC_IRQN); + NVIC_SetPriority(NRF_802154_RTC_IRQN, 0); + + nrf_802154_clock_lfclk_stop(); +} + +void nrf_802154_timer_critical_section_enter(void) +{ + NVIC_DisableIRQ(NRF_802154_RTC_IRQN); + __DSB(); + __ISB(); +} + +void nrf_802154_timer_critical_section_exit(void) +{ + NVIC_EnableIRQ(NRF_802154_RTC_IRQN); +} + +uint32_t nrf_802154_timer_time_get(void) +{ + return (uint32_t)time_get(); +} + +uint32_t nrf_802154_timer_granularity_get(void) +{ + return US_PER_TICK; +} + +void nrf_802154_timer_start(uint32_t t0, uint32_t dt) +{ + uint64_t now; + uint32_t target_counter; + + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); + nrf_rtc_event_enable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT_MASK); + + now = time_get(); + + // Check if 32 LSB of `now` overflowed between getting t0 and loading `now` value. + if ((uint32_t)now < t0) + { + now -= 0x0000000100000000; + } + + m_target_time = (now & 0xffffffff00000000) + t0 + dt; + + target_counter = time_to_ticks(m_target_time); + + nrf_rtc_cc_set(NRF_802154_RTC_INSTANCE, RTC_COMPARE_CHANNEL, target_counter); + + now = rtc_protected_time_get(); + + if (shall_strike(now)) + { + handle_compare_match(true); + } + else + { + nrf_rtc_int_enable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); + } +} + +bool nrf_802154_timer_is_running(void) +{ + return nrf_rtc_int_is_enabled(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); +} + +void nrf_802154_timer_stop(void) +{ + nrf_rtc_event_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT_MASK); + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK); + nrf_rtc_event_clear(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT); +} + +void nrf_802154_clock_lfclk_ready(void) +{ + m_clock_ready = true; +} + +void NRF_802154_RTC_IRQ_HANDLER(void) +{ + // Handle overflow. + if (nrf_rtc_event_pending(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) + { + // Disable OVERFLOW interrupt to prevent lock-up in interrupt context while mutex is locked from lower priority context + // and OVERFLOW event flag is stil up. + // OVERFLOW interrupt will be re-enabled when mutex is released - either from this handler, or from lower priority context, + // that locked the mutex. + nrf_rtc_int_disable(NRF_802154_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + // Handle OVERFLOW event by reading current value of overflow counter. + (void)overflow_counter_get(); + } + + // Handle compare match. + if (nrf_rtc_int_is_enabled(NRF_802154_RTC_INSTANCE, RTC_COMPARE_INT_MASK) && + nrf_rtc_event_pending(NRF_802154_RTC_INSTANCE, RTC_COMPARE_EVENT)) + { + handle_compare_match(false); + } +} diff --git a/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer_none.c b/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_none.c similarity index 87% rename from third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer_none.c rename to third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_none.c index 8171d9dc8..dcd5508d7 100644 --- a/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_drv_radio802154_timer_none.c +++ b/third_party/NordicSemiconductor/drivers/radio/platform/timer/nrf_802154_timer_none.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,24 +36,24 @@ * */ -#include "nrf_drv_radio802154_timer.h" +#include "nrf_802154_timer.h" -void nrf_drv_radio802154_timer_init(void) +void nrf_802154_timer_init(void) { // Intentionally empty } -void nrf_drv_radio802154_timer_deinit(void) +void nrf_802154_timer_deinit(void) { // Intentionally empty } -void nrf_drv_radio802154_timer_critical_section_enter(void) +void nrf_802154_timer_critical_section_enter(void) { // Intentionally empty } -void nrf_drv_radio802154_timer_critical_section_exit(void) +void nrf_802154_timer_critical_section_exit(void) { // Intentionally empty } diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h b/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h index c1580cd5b..606ec3091 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h +++ b/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,7 @@ extern "C" { /** * @defgroup nrf_raal Radio Arbiter Abstraction Layer * @{ - * @ingroup nrf_driver_radio802154 + * @ingroup nrf_802154 * @brief Radio Arbiter Abstraction Layer interface. */ @@ -107,6 +107,14 @@ void nrf_raal_continuous_mode_exit(void); */ bool nrf_raal_timeslot_request(uint32_t length_us); +/** + * @brief Check if the 802.15.4 driver is currently in timeslot. + * + * @retval TRUE Timeslot is currently granted. + * @retval FALSE Timeslot is not currently granted. + */ +bool nrf_raal_timeslot_is_granted(void); + /** * @brief Get left time of currently granted timeslot [us]. * @@ -117,7 +125,11 @@ uint32_t nrf_raal_timeslot_us_left_get(void); /** * @brief Enter critical section of the module. * - * When this method is called, the execution of the @nrf_raal_timeslot_ended function is blocked. + * When this method is called, the execution of the @sa nrf_raal_timeslot_started and + * @sa nrf_raal_timeslot_ended function is blocked. + * + * @note This function may be called when RAAL is already in critical section. Ongoing call may + * be interrupted by another call from IRQ with higher priority. * */ void nrf_raal_critical_section_enter(void); @@ -125,9 +137,12 @@ void nrf_raal_critical_section_enter(void); /** * @brief Exit critical section of the module. * - * When this method is called driver has to expect the execution of the @nrf_raal_timeslot_ended + * When this method is called driver has to expect the execution of the + * @sa nrf_raal_timeslot_started or @sa nrf_raal_timeslot_ended * function. * + * @note This function may be called when RAAL has already exited critical section. Ongoing call + * may NOT be interrupted by another call from IRQ with higher priority. */ void nrf_raal_critical_section_exit(void); diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h b/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h index 52d894de0..1da120485 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h +++ b/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,8 +31,8 @@ #ifndef NRF_RAAL_CONFIG_H__ #define NRF_RAAL_CONFIG_H__ -#ifdef NRF_DRV_RADIO802154_PROJECT_CONFIG -#include NRF_DRV_RADIO802154_PROJECT_CONFIG +#ifdef NRF_802154_PROJECT_CONFIG +#include NRF_802154_PROJECT_CONFIG #endif #include @@ -44,7 +44,7 @@ extern "C" { /** * @defgroup nrf_raal_config RAAL configuration * @{ - * @ingroup nrf_driver_radio802154 + * @ingroup nrf_802154 * @brief Configuration of Radio Arbiter Abstraction Layer. */ diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c b/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c index b188c74d4..b0ac7c2fd 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c +++ b/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,7 @@ #include #include -#include "platform/clock/nrf_drv_radio802154_clock.h" +#include "platform/clock/nrf_802154_clock.h" static bool m_continuous; @@ -60,7 +60,7 @@ void nrf_raal_continuous_mode_enter(void) { assert(!m_continuous); - nrf_drv_radio802154_clock_hfclk_start(); + nrf_802154_clock_hfclk_start(); m_continuous = true; } @@ -69,7 +69,7 @@ void nrf_raal_continuous_mode_exit(void) assert(m_continuous); m_continuous = false; - nrf_drv_radio802154_clock_hfclk_stop(); + nrf_802154_clock_hfclk_stop(); } bool nrf_raal_timeslot_request(uint32_t length_us) @@ -81,6 +81,11 @@ bool nrf_raal_timeslot_request(uint32_t length_us) return true; } +bool nrf_raal_timeslot_is_granted(void) +{ + return true; +} + uint32_t nrf_raal_timeslot_us_left_get(void) { return UINT32_MAX; @@ -96,7 +101,7 @@ void nrf_raal_critical_section_exit(void) // Intentionally empty. } -void nrf_drv_radio802154_clock_hfclk_ready(void) +void nrf_802154_clock_hfclk_ready(void) { nrf_raal_timeslot_started(); } diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c b/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c index c9be1799d..23b20b274 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c +++ b/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,9 +44,9 @@ #include #include -#include -#include -#include +#include +#include +#include #if defined(__GNUC__) _Pragma("GCC diagnostic push") @@ -311,7 +311,7 @@ static void timeslot_extend(void) m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND; m_ret_param.params.extend.length_us = m_timeslot_length; - nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ); + nrf_802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ); } else { @@ -324,8 +324,8 @@ static void timer_irq_handle(void) // Safe margin exceeded. if (RAAL_TIMER->EVENTS_COMPARE[TIMER_CC_MARGIN]) { - nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE); - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_MARGIN); + nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_MARGIN); m_in_timeslot = false; @@ -360,13 +360,13 @@ static void timer_irq_handle(void) m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; #endif - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_MARGIN); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_MARGIN); } // Extension margin exceeded. else if (RAAL_TIMER->EVENTS_COMPARE[TIMER_CC_EXTEND]) { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND); nrf_timer_int_disable(RAAL_TIMER, TIMER_CC_EXTEND_INT); nrf_timer_event_clear(RAAL_TIMER, TIMER_CC_EXTEND_EVENT); @@ -375,7 +375,7 @@ static void timer_irq_handle(void) (nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_EXTEND) + m_config.timeslot_length < m_config.timeslot_max_length)) { - nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ); + nrf_802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ); m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND; m_ret_param.params.extend.length_us = m_config.timeslot_length; @@ -387,7 +387,7 @@ static void timer_irq_handle(void) m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; } - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXTEND); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXTEND); } else { @@ -399,15 +399,15 @@ static void timer_irq_handle(void) /**@brief Signal handler. */ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_type) { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_HANDLER); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_HANDLER); // Default response. m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; if (!m_continuous) { - nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE); - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_ENDED); + nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_ENDED); m_pending_event = PENDING_EVENT_NONE; m_in_timeslot = false; @@ -416,8 +416,8 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; timer_reset(); - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_ENDED); - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_HANDLER); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_ENDED); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_HANDLER); return &m_ret_param; } @@ -425,8 +425,8 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t { case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START: /**< This signal indicates the start of the radio timeslot. */ { - nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_ACTIVE); - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_START); + nrf_802154_pin_set(PIN_DBG_TIMESLOT_ACTIVE); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_START); // Ensure HFCLK is running before start is issued. assert(NRF_CLOCK->HFCLKSTAT == (CLOCK_HFCLKSTAT_SRC_Msk | CLOCK_HFCLKSTAT_STATE_Msk)); @@ -460,8 +460,8 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND; m_ret_param.params.extend.length_us = m_timeslot_length; - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_START); - nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_START); + nrf_802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ); break; } @@ -470,14 +470,14 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: /**< This signal indicates the NRF_RADIO interrupt. */ - nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_RADIO_IRQ); - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_RADIO); + nrf_802154_pin_set(PIN_DBG_TIMESLOT_RADIO_IRQ); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_RADIO); if (m_in_timeslot) { if (!timer_is_margin_reached()) { - nrf_drv_radio802154_irq_handler(); + nrf_802154_radio_irq_handler(); } else { @@ -486,23 +486,23 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t } } - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_RADIO); - nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_RADIO_IRQ); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_RADIO); + nrf_802154_pin_clr(PIN_DBG_TIMESLOT_RADIO_IRQ); break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED: /**< This signal indicates extend action failed. */ - nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_EXTEND_REQ); - nrf_drv_radio802154_pin_tgl(PIN_DBG_TIMESLOT_FAILED); - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL); + nrf_802154_pin_clr(PIN_DBG_TIMESLOT_EXTEND_REQ); + nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_FAILED); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL); timeslot_extend(); - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL); break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED: /**< This signal indicates extend action succeeded. */ - nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_EXTEND_REQ); - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS); + nrf_802154_pin_clr(PIN_DBG_TIMESLOT_EXTEND_REQ); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS); timer_extend(); @@ -511,14 +511,14 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t timeslot_extend(); } - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS); break; default: break; } - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_HANDLER); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_HANDLER); return &m_ret_param; } @@ -530,7 +530,7 @@ void nrf_raal_softdevice_soc_evt_handler(uint32_t evt_id) case NRF_EVT_RADIO_BLOCKED: case NRF_EVT_RADIO_CANCELED: { - nrf_drv_radio802154_pin_tgl(PIN_DBG_TIMESLOT_BLOCKED); + nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_BLOCKED); assert(!m_in_timeslot); @@ -554,7 +554,7 @@ void nrf_raal_softdevice_soc_evt_handler(uint32_t evt_id) case NRF_EVT_RADIO_SESSION_IDLE: if (m_continuous) { - nrf_drv_radio802154_pin_tgl(PIN_DBG_TIMESLOT_SESSION_IDLE); + nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_SESSION_IDLE); timeslot_data_init(); timeslot_request(); @@ -609,12 +609,12 @@ void nrf_raal_uninit(void) m_continuous = false; m_in_timeslot = false; - nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE); + nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE); } void nrf_raal_continuous_mode_enter(void) { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CONTINUOUS_ENTER); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CONTINUOUS_ENTER); assert(m_initialize); assert(!m_continuous); @@ -623,14 +623,14 @@ void nrf_raal_continuous_mode_enter(void) m_timeslot_length = m_config.timeslot_length; m_continuous = true; - nrf_drv_radio802154_clock_hfclk_start(); + nrf_802154_clock_hfclk_start(); - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CONTINUOUS_ENTER); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CONTINUOUS_ENTER); } void nrf_raal_continuous_mode_exit(void) { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CONTINUOUS_EXIT); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CONTINUOUS_EXIT); assert(m_initialize); assert(m_continuous); @@ -643,9 +643,9 @@ void nrf_raal_continuous_mode_exit(void) NVIC_SetPendingIRQ(RAAL_TIMER_IRQn); } - nrf_drv_radio802154_clock_hfclk_stop(); + nrf_802154_clock_hfclk_stop(); - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CONTINUOUS_EXIT); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CONTINUOUS_EXIT); } bool nrf_raal_timeslot_request(uint32_t length_us) @@ -658,6 +658,11 @@ bool nrf_raal_timeslot_request(uint32_t length_us) return timer_time_get() + length_us < nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_MARGIN); } +bool nrf_raal_timeslot_is_granted(void) +{ + return (m_continuous && m_in_timeslot); +} + uint32_t nrf_raal_timeslot_us_left_get(void) { if (!m_continuous || !m_in_timeslot) @@ -670,21 +675,19 @@ uint32_t nrf_raal_timeslot_us_left_get(void) void nrf_raal_critical_section_enter(void) { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CRIT_SECT_ENTER); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CRIT_SECT_ENTER); - assert(!m_in_critical_section); m_in_critical_section = true; - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CRIT_SECT_ENTER); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CRIT_SECT_ENTER); } void nrf_raal_critical_section_exit(void) { - nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CRIT_SECT_EXIT); + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_CRIT_SECT_EXIT); timeslot_critical_section_enter(); - assert(m_in_critical_section); m_in_critical_section = false; switch (m_pending_event) @@ -705,10 +708,10 @@ void nrf_raal_critical_section_exit(void) timeslot_critical_section_exit(); - nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CRIT_SECT_EXIT); + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CRIT_SECT_EXIT); } -void nrf_drv_radio802154_clock_hfclk_ready(void) +void nrf_802154_clock_hfclk_ready(void) { if (m_continuous && !m_in_timeslot) { diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h b/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h index 68865419f..a118a2e88 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h +++ b/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Nordic Semiconductor ASA +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.c b/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.c new file mode 100644 index 000000000..46969c1a4 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.c @@ -0,0 +1,405 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file implements timer scheduler for the nRF 802.15.4 driver. + * + * This implementation supports scheduling of multiple timer instances and can be used from different contexts. + * + * @note Timer scheduler is secured against preemption and adding/removing different timers from different contexts, + * it shall not be used for adding/removing the same timer instance from two contexts at the same time. + * + */ + +#include "nrf_802154_timer_sched.h" + +#include +#include +#include +#include + +#include +#include "platform/timer/nrf_802154_timer.h" + +static volatile uint8_t m_mutex; ///< Mutex for starting the timer. +static volatile uint8_t m_queue_changed_cntr; ///< Information that scheduler queue was modified. +static volatile nrf_802154_timer_t * mp_head; ///< Head of the running timers list. + +/** @brief Non-blocking mutex for starting the timer. + * + * @retval true Mutex was acquired. + * @retval false Mutex could not be acquired. + */ +static inline bool mutex_trylock(void) +{ + do + { + volatile uint8_t mutex_value = __LDREXB(&m_mutex); + + if (mutex_value) + { + __CLREX(); + return false; + } + } while (__STREXB(1, &m_mutex)); + + __DMB(); + + return true; +} + +/** @brief Release mutex. */ +static inline void mutex_unlock(void) +{ + __DMB(); + m_mutex = 0; +} + +/** @brief Increment queue counter value to detect changes in the queue. */ +static inline void queue_cntr_bump(void) +{ + volatile uint8_t cntr; + + do + { + cntr = __LDREXB(&m_queue_changed_cntr); + } while (__STREXB(cntr + 1, &m_queue_changed_cntr)); + + __DMB(); +} + +/** + * @brief Check if @p time_1 is before @p time_2. + * + * @param[in] time_1 First time to compare. + * @param[in] time_2 Second time to compare. + * + * @return True if @p time_1 is before @p time_2, false otherwise. + */ +static inline bool is_time_before(uint32_t time_1, uint32_t time_2) +{ + int32_t diff = time_1 - time_2; + + return diff < 0; +} + +/** + * @brief Check if @p p_timer_1 shall strike earlier than @p p_timer_2. + * + * @param[in] p_timer_1 A pointer to first timer to compare. + * @param[in] p_timer_2 A pointer to second timer to compare. + * + * @return True if @p p_timer_1 shall strike earlier than @p p_timer_2, false otherwise. + */ +static inline bool is_timer_prior(const nrf_802154_timer_t * p_timer_1, + const nrf_802154_timer_t * p_timer_2) +{ + return is_time_before(p_timer_1->t0 + p_timer_1->dt, p_timer_2->t0 + p_timer_2->dt); +} + +/** + * @brief Handle operation on timer with mutex protection. + */ +static inline void handle_timer(void) +{ + volatile nrf_802154_timer_t * p_head; + uint8_t queue_cntr; + + do + { + queue_cntr = m_queue_changed_cntr; + p_head = mp_head; + + if (mutex_trylock()) + { + if (p_head == NULL) + { + nrf_802154_timer_stop(); + } + else + { + uint32_t t0 = p_head->t0; + uint32_t dt = p_head->dt; + + // Set the timer only if current HEAD wasn't removed - otherwise t0 and dt might've been modified + // between reading t0 and dt and not be a valid combination. + if (p_head == mp_head) + { + nrf_802154_timer_start(t0, dt); + } + } + + mutex_unlock(); + } + } while (queue_cntr != m_queue_changed_cntr); +} + +/** + * @brief Remove timer from the queue + * + * @param [inout] p_timer Pointer to timer to remove from the queue. + * + * @retval true @sa handle_timer() shall be called by caller of this function. + * @retval false @sa handle_timer() shall not be called by the caller. + */ +static bool timer_remove(nrf_802154_timer_t * p_timer) +{ + assert(p_timer != NULL); + + nrf_802154_timer_t ** pp_item; + nrf_802154_timer_t * volatile p_next; // Volatile pointer to prevent compiler from removing any code related to this variable during optimization (IAR). + nrf_802154_timer_t * p_cur; + uint8_t queue_cntr; + bool timer_start; + bool timer_stop; + + while (true) + { + queue_cntr = m_queue_changed_cntr; + pp_item = (nrf_802154_timer_t **)&mp_head; + p_next = NULL; + p_cur = NULL; + timer_start = false; + timer_stop = false; + + // Find entry to remove + while (true) + { + p_cur = (nrf_802154_timer_t *)__LDREXW((uint32_t *)pp_item); + + if ((p_cur == NULL) || (p_cur == p_timer)) + { + break; + } + + pp_item = &(p_cur->p_next); + } + + if (queue_cntr != m_queue_changed_cntr) + { + // Higher priority modified the queue while iterating, try again. + continue; + } + + if (p_cur == p_timer) + { + // Entry found. + p_next = p_cur->p_next; + + // Restart timer when removing HEAD and other timer instance is pending. + if (p_cur == mp_head) + { + if (p_next != NULL) + { + timer_start = true; + } + else + { + timer_stop = true; + } + } + } + else + { + // Entry not found + __CLREX(); + break; + } + + if (!__STREXW((uint32_t)p_next, (uint32_t *)pp_item)) + { + // Exit, if exclusive access succeeds. + queue_cntr_bump(); + break; + } + } + + // Write to the pointer next on removal to ensure that node removal is detected by + // lower pritority context in case it was going to be used. + if (p_cur != NULL) + { + do + { + // This assignment is used to prevent compiler from removing exclusive load during optimization (IAR). + p_next = (nrf_802154_timer_t *)__LDREXW((uint32_t *)&p_cur->p_next); + } while (__STREXW((uint32_t)NULL, (uint32_t *)&p_cur->p_next)); + } + + return (timer_start || timer_stop); +} + +void nrf_802154_timer_sched_init(void) +{ + mp_head = NULL; + m_mutex = 0; + m_queue_changed_cntr = 0; +} + +void nrf_802154_timer_sched_deinit(void) +{ + nrf_802154_timer_stop(); + + mp_head = NULL; +} + +uint32_t nrf_802154_timer_sched_time_get(void) +{ + return nrf_802154_timer_time_get(); +} + +bool nrf_802154_timer_sched_time_is_in_future(uint32_t now, uint32_t t0, uint32_t dt) +{ + uint32_t target_time = t0 + dt; + int32_t difference = target_time - now; + + return difference > 0; +} + +void nrf_802154_timer_sched_add(nrf_802154_timer_t * p_timer, bool round_up) +{ + assert(p_timer != NULL); + assert(p_timer->callback != NULL); + + if (round_up) + { + p_timer->dt += nrf_802154_timer_granularity_get() - 1; + } + + if (timer_remove(p_timer)) + { + handle_timer(); + } + + nrf_802154_timer_t ** pp_item; + nrf_802154_timer_t * p_next; + uint8_t queue_cntr; + + while (true) + { + queue_cntr = m_queue_changed_cntr; + pp_item = (nrf_802154_timer_t **)&mp_head; + p_next = NULL; + + // Search the current queue to find appropriate position to insert timer. + while (true) + { + nrf_802154_timer_t * p_cur = (nrf_802154_timer_t *)__LDREXW((uint32_t *)pp_item); + + if (p_cur == NULL) + { + // No HEAD or insert at the end. + p_next = NULL; + break; + } + + if (is_timer_prior(p_timer, p_cur)) + { + // Insert at the beginning with existing HEAD or somewhere in the middle. + p_next = p_cur; + break; + } + + pp_item = &(p_cur->p_next); + } + + if (queue_cntr != m_queue_changed_cntr) + { + // Higher priority modified the queue while iterating, try again. + continue; + } + + p_timer->p_next = p_next; + + if (!__STREXW((uint32_t)p_timer, (uint32_t *)pp_item)) + { + // Exit, if exclusive access succeeds. + queue_cntr_bump(); + break; + } + } + + if (mp_head == p_timer) + { + handle_timer(); + } +} + +void nrf_802154_timer_sched_remove(nrf_802154_timer_t * p_timer) +{ + if (timer_remove(p_timer)) + { + handle_timer(); + } +} + +bool nrf_802154_timer_sched_is_running(nrf_802154_timer_t * p_timer) +{ + uint8_t queue_cntr; + bool result; + + do + { + result = false; + queue_cntr = m_queue_changed_cntr; + + for (volatile nrf_802154_timer_t * p_cur = mp_head; + p_cur != NULL; + p_cur = p_cur->p_next) + { + if (p_cur == p_timer) + { + result = true; + break; + } + } + } while (queue_cntr != m_queue_changed_cntr); + + return result; +} + +void nrf_802154_timer_fired(void) +{ + nrf_802154_timer_t * p_timer = (nrf_802154_timer_t *) mp_head; + nrf_802154_timer_callback_t callback = p_timer->callback; + void * p_context = p_timer->p_context; + + if ((p_timer != NULL) && (callback != NULL)) + { + bool timer_shall_be_handled = timer_remove(p_timer); + + callback(p_context); + + if (timer_shall_be_handled) + { + handle_timer(); + } + } +} diff --git a/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.h b/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.h new file mode 100644 index 000000000..944b9d3d4 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.h @@ -0,0 +1,158 @@ +/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @brief This module provides timer scheduling functionality for the 802.15.4 driver. + * + * Timer module should be used to implement strict timing features specified in IEEE 802.15.4 like: + * * CSL, + * * Timing out waiting for ACK frames, + * * CSMA/CA, + * * Inter-frame spacing: SIFS, LIFS (note that AIFS is implemented without using timer module). + * + * @note Current implementation supports only single one-shot timer. It may be extended to support + * timer scheduling and repetitive timers if needed. + */ + +#ifndef NRF_802154_TIMER_SCHED_H_ +#define NRF_802154_TIMER_SCHED_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_802154_timer_sched Timer Scheduler module for the 802.15.4 driver + * @{ + * @ingroup nrf_802154_timer_sched + * @brief Timer Scheduler module for the 802.15.4 driver. + * + */ + +/** + * @brief Type of function called when timer fires. + * + * @param[inout] p_context Pointer to user-defined memory location. May be NULL. + */ +typedef void (* nrf_802154_timer_callback_t)(void * p_context); + +/** + * @brief Type for driver instance. + */ +typedef struct nrf_802154_timer_s nrf_802154_timer_t; + +/** + * @brief Structure containing timer data used by timer module. + */ +struct nrf_802154_timer_s +{ + uint32_t t0; ///< Base time of the timer [us] + uint32_t dt; ///< Timer expiration delta from @p t0 [us] + nrf_802154_timer_callback_t callback; ///< Callback function called when timer expires + void * p_context; ///< User-defined context passed to callback function + nrf_802154_timer_t * p_next; ///< A pointer to the next running timer +}; + +/** + * @brief Initialize the timer scheduler. + */ +void nrf_802154_timer_sched_init(void); + +/** + * @brief Deinitialize the timer scheduler. + */ +void nrf_802154_timer_sched_deinit(void); + +/** + * @brief Get current time. + * + * This function is useful to set base time in @sa nrf_802154_timer_t structure. + * + * @return Current time in microseconds [us]. + */ +uint32_t nrf_802154_timer_sched_time_get(void); + +/** + * @brief Check if given time is in future. + * + * @param[in] now Current time. @sa nrf_802154_timer_sched_time_get() + * @param[in] t0 Base of time compared with @p now. + * @param[in] dt Time delta from @p t0 compared with @p now. + * + * @retval true Given time @p t0 @p dt is in future (compared to given @p now). + * @retval false Given time @p t0 @p dt is not in future (compared to given @p now). + */ +bool nrf_802154_timer_sched_time_is_in_future(uint32_t now, uint32_t t0, uint32_t dt); + +/** + * @brief Start given timer and add it to the scheduler. + * + * @note Fields t0, dt, callback and p_context should be filled in @p p_timer prior to calling this + * function; callback field cannot be NULL. + * + * @note Due to timer granularity the callback function cannot be called exactly at specified time. + * Use @p round_up to specify if given timer should be expired before or after time given in + * the @p p_timer structure. The dt field of the @p p_timer is updated with the rounded up value. + * + * @param[inout] p_timer Pointer to the timer to start and add to the scheduler. + * @param[in] round_up True if timer should expire after specified time, false if it should + * expire before. + */ +void nrf_802154_timer_sched_add(nrf_802154_timer_t * p_timer, bool round_up); + +/** + * @brief Stop given timer and remove it from the scheduler. + * + * @param[inout] p_timer Pointer to the timer to stop and remove from the scheduler. + */ +void nrf_802154_timer_sched_remove(nrf_802154_timer_t * p_timer); + +/** + * @brief Check if given timer is already scheduled. + * + * @param[in] p_timer Pointer to the timer to check. + * + * @retval true Given timer is already scheduled. + * @retval false Given timer is not scheduled. + */ +bool nrf_802154_timer_sched_is_running(nrf_802154_timer_t * p_timer); + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_802154_TIMER_SCHED_H_ */