1#ifndef BLUETOE_BINDINGS_NRF52_HPP
2#define BLUETOE_BINDINGS_NRF52_HPP
4#include <bluetoe/link_layer.hpp>
5#include <bluetoe/nrf.hpp>
7#include <bluetoe/ll_data_pdu_buffer.hpp>
8#include <bluetoe/security_tool_box.hpp>
9#include <bluetoe/connection_events.hpp>
46 namespace nrf52_details
48 static constexpr std::uint8_t maximum_advertising_pdu_size = 0x3f;
50 static constexpr unsigned connect_addr_offset = 2 + 6;
54 static constexpr std::uint32_t adv_reponse_timeout_us = 152 + 42 * 8 + 20;
55 static constexpr unsigned us_radio_rx_startup_time = 140;
56 static constexpr unsigned us_radio_tx_startup_time = 130;
63 static constexpr std::uint32_t setup_connection_event_limit_us =
64 50 + std::max( us_radio_rx_startup_time, us_radio_tx_startup_time ) + 31 + 31;
66 static constexpr std::uint8_t more_data_flag = 0x10;
67 static constexpr std::size_t encryption_mic_size = 4;
80 void copy_to( std::uint8_t* target )
const;
88 class radio_hardware_without_crypto_support
91 static int pdu_gap_required_by_encryption()
96 static void init(
void (*isr)(
void* ),
void* that );
101 static void configure_radio_channel(
107 static void configure_transmit_train(
113 static void configure_final_transmit(
120 static void configure_receive_train(
123 static void stop_radio();
128 static void store_timer_anchor(
int offset_us );
138 static std::tuple< bool, bool, bool > received_pdu();
145 static std::uint32_t now();
151 static std::pair< bool, link_layer::delta_time > can_stop_connection_event_timer( std::uint32_t safety_margin_us );
153 static void setup_identity_resolving(
154 const std::uint8_t* )
158 static bool resolving_address_invalid()
164 bluetoe::link_layer::details::phy_ll_encoding::phy_ll_encoding_t receiving_encoding,
165 bluetoe::link_layer::details::phy_ll_encoding::phy_ll_encoding_t transmiting_c_encoding );
172 static bool schedule_advertisment_event_timer(
174 std::uint32_t timeout_us,
175 std::uint32_t start_hfxo_offset );
177 static void schedule_connection_event_timer(
178 std::uint32_t begin_us,
179 std::uint32_t end_us,
180 std::uint32_t start_hfxo_offset );
182 static bool schedule_user_timer(
183 void (*isr)(
void* ),
184 std::uint32_t time_us,
185 std::uint32_t max_cb_runtimer_ms );
187 static bool stop_user_timer();
191 static void stop_timeout_timer();
193 static std::uint32_t static_random_address_seed();
195 static void set_access_address_and_crc_init( std::uint32_t access_address, std::uint32_t crc_init );
197 static void debug_toggle();
203 static bool user_timer_anchor_moved();
210 : context_( __get_PRIMASK() )
217 __set_PRIMASK( context_ );
220 lock_guard(
const lock_guard& ) =
delete;
221 lock_guard& operator=(
const lock_guard& ) =
delete;
223 const std::uint32_t context_;
228 static bool receive_2mbit_;
229 static bool transmit_2mbit_;
235 volatile static int hf_connection_event_anchor_;
236 volatile static std::uint32_t lf_connection_event_anchor_;
241 volatile static bool user_timer_anchor_moved_;
250 class radio_hardware_with_crypto_support :
public radio_hardware_without_crypto_support
253 static int pdu_gap_required_by_encryption()
258 using radio_hardware_without_crypto_support::init;
259 static void init( std::uint8_t* encrypted_area,
void (*isr)(
void* ),
void* that );
261 static void configure_transmit_train(
264 static void configure_final_transmit(
267 static void configure_receive_train(
270 static void store_timer_anchor(
int offset_us );
272 static std::tuple< bool, bool, bool > received_pdu();
274 static void configure_encryption(
bool receive,
bool transmit );
276 static std::pair< std::uint64_t, std::uint32_t > setup_encryption( bluetoe::details::uint128_t key, std::uint64_t skdm, std::uint32_t ivm );
278 static void increment_receive_packet_counter()
280 receive_counter_.increment();
283 static void increment_transmit_packet_counter()
285 transmit_counter_.increment();
291 static void setup_identity_resolving_address(
292 const std::uint8_t* address );
297 static void set_identity_resolving_key(
298 const details::identity_resolving_key_t& irk );
303 static bool resolving_address_invalid();
306 static volatile bool receive_encrypted_;
307 static volatile bool transmit_encrypted_;
308 static std::uint8_t* encrypted_area_;
309 static counter receive_counter_;
310 static counter transmit_counter_;
311 static bool identity_resolving_enabled_;
314 template <
typename ... Options >
317 using result =
typename bluetoe::details::find_all_by_meta_type<
323 template <
typename ... Options >
324 struct link_layer_options
326 using result =
typename bluetoe::details::find_all_by_not_meta_type<
327 bluetoe::details::binding_option_meta_type,
332 template <
class CallBacks,
class Hardware,
class Buffer,
typename ... RadioOptions >
333 class nrf52_radio_base :
public Buffer
338 low_frequency_clock_t::start_clocks();
339 Hardware::init( [](
void* that ){
340 static_cast< nrf52_radio_base*
>( that )->radio_interrupt_handler();
344 nrf52_radio_base( std::uint8_t* receive_buffer )
346 low_frequency_clock_t::start_clocks();
347 Hardware::init( receive_buffer, [](
void* that ){
348 static_cast< nrf52_radio_base*
>( that )->radio_interrupt_handler();
352 void schedule_advertisment(
359 assert( !adv_received_ );
360 assert( !adv_timeout_ );
361 assert( state_ == state::idle );
362 assert( receive.
buffer && receive.
size >= 2u );
365 advertising.
size = std::min< std::uint8_t >( advertising.
size, maximum_advertising_pdu_size );
367 response_data_ = response_data;
368 receive_buffer_ = receive;
369 receive_buffer_.
size = std::min< std::size_t >( receive.
size, maximum_advertising_pdu_size );
371 Hardware::configure_radio_channel( channel );
372 Hardware::configure_transmit_train( advertising );
374 Hardware::setup_identity_resolving( receive_buffer_.buffer + connect_addr_offset );
377 const std::uint32_t read_timeout = ( advertising.
size + 2 + 1 + 4 + 3 ) * 8 + adv_reponse_timeout_us;
379 state_ = state::adv_transmitting;
381 if ( Hardware::schedule_advertisment_event_timer( when, read_timeout, hfxo_startup_value ) )
382 low_frequency_clock_t::stop_high_frequency_crystal_oscilator();
385 link_layer::delta_time schedule_connection_event(
392 assert( state_ == state::idle );
393 assert( start_receive < end_receive );
398 return connection_interval;
404 const std::uint32_t start_event = start_receive.
usec();
407 const std::uint32_t end_event = end_receive.
usec() + 500;
409 const auto now = Hardware::now();
410 if ( now + start_event_safety_margin_us > start_event )
413 return connection_interval;
416 receive_buffer_ = receive_buffer();
417 state_ = state::evt_wait_connect;
419 Hardware::configure_radio_channel( channel );
420 Hardware::configure_receive_train( receive_buffer_ );
422 Hardware::schedule_connection_event_timer( start_event, end_event, hfxo_startup_value );
423 low_frequency_clock_t::stop_high_frequency_crystal_oscilator();
425 return link_layer::delta_time( connection_interval.
usec() - now );
428 std::pair< bool, link_layer::delta_time > disarm_connection_event()
432 const auto result = Hardware::can_stop_connection_event_timer( start_event_safety_margin_us );
436 Hardware::stop_radio();
437 state_ = state::idle;
443 bool schedule_synchronized_user_timer(
447 return Hardware::schedule_user_timer( [](
void* that ){
448 const auto this_ =
static_cast< nrf52_radio_base*
>( that );
449 const auto callbacks =
static_cast< CallBacks*
>( this_ );
451 callbacks->user_timer( Hardware::user_timer_anchor_moved() );
453 }, timer.
usec(), max_cb_runtime.
usec() );
456 bool cancel_synchronized_user_timer()
458 return Hardware::stop_user_timer();
461 void set_access_address_and_crc_init( std::uint32_t access_address, std::uint32_t crc_init )
463 Hardware::set_access_address_and_crc_init( access_address, crc_init );
468 static constexpr bool single_wfi = bluetoe::details::has_option<
469 nrf::leave_run_on_interrupt, RadioOptions... >::value;
471 while ( !single_wfi && !adv_received_ && !adv_timeout_ && !evt_timeout_ && !end_evt_ && wake_up_ == 0 )
478 assert( state_ == state::idle );
479 assert(
reinterpret_cast< std::uint8_t*
>( NRF_RADIO->PACKETPTR ) == receive_buffer_.buffer );
481 receive_buffer_.size = std::min< std::size_t >(
482 receive_buffer_.size,
483 ( receive_buffer_.buffer[ 1 ] & 0x3f ) + 2 + Hardware::pdu_gap_required_by_encryption()
485 adv_received_ =
false;
487 static_cast< CallBacks*
>( this )->adv_received( receive_buffer_ );
492 assert( state_ == state::idle );
493 adv_timeout_ =
false;
494 static_cast< CallBacks*
>( this )->adv_timeout();
499 assert( state_ == state::idle );
500 evt_timeout_ =
false;
501 static_cast< CallBacks*
>( this )->timeout();
506 assert( state_ == state::idle );
508 static_cast< CallBacks*
>( this )->end_event( events_ );
510 events_ = link_layer::connection_event_events();
513 if ( request_event_cancelation_ )
515 request_event_cancelation_ =
false;
516 static_cast< CallBacks*
>( this )->try_event_cancelation();
530 void request_event_cancelation()
532 request_event_cancelation_ =
true;
536 std::uint32_t static_random_address_seed()
const
538 return Hardware::static_random_address_seed();
541 void nrf_flash_memory_access_begin()
545 Hardware::stop_radio();
546 low_frequency_clock_t::stop_high_frequency_crystal_oscilator();
547 state_ = state::idle;
550 void nrf_flash_memory_access_end()
554 assert( state_ == state::idle );
557 evt_timeout_ = !end_evt_;
561 bluetoe::link_layer::details::phy_ll_encoding::phy_ll_encoding_t receiving_encoding,
562 bluetoe::link_layer::details::phy_ll_encoding::phy_ll_encoding_t transmiting_c_encoding )
564 Hardware::set_phy( receiving_encoding, transmiting_c_encoding );
567 using lock_guard =
typename Hardware::lock_guard;
570 static constexpr std::size_t radio_maximum_white_list_entries = 0;
575 static constexpr bool hardware_supports_2mbit =
true;
580 static constexpr bool hardware_supports_synchronized_user_timer =
true;
582 static constexpr unsigned connection_event_setup_time_us = nrf52_radio_base::start_event_safety_margin_us;
585 using low_frequency_clock_t =
typename bluetoe::details::find_by_meta_type<
586 nrf::nrf_details::sleep_clock_source_meta_type,
590 using hfxo_startup_time_t =
typename bluetoe::details::find_by_meta_type<
591 nrf::nrf_details::hfxo_startup_time_meta_type,
598 static constexpr std::uint32_t hfxo_startup_value =
599 ( hfxo_startup_time_t::value + 1000000 / nrf::lfxo_clk_freq ) * nrf::lfxo_clk_freq / 1000000;
604 static constexpr std::uint32_t hfxo_startup_time = hfxo_startup_value * 1000000 / nrf::lfxo_clk_freq;
609 static constexpr std::uint32_t start_event_safety_margin_us = setup_connection_event_limit_us + hfxo_startup_time;
612 link_layer::read_buffer receive_buffer()
614 link_layer::read_buffer result = this->allocate_receive_buffer();
615 if ( result.empty() )
616 result = link_layer::read_buffer{ &empty_receive_[ 0 ],
sizeof( empty_receive_ ) };
621 void radio_interrupt_handler()
623 if ( state_ == state::adv_transmitting )
627 Hardware::configure_receive_train( receive_buffer_ );
628 state_ = state::adv_receiving;
630 else if ( state_ == state::adv_receiving )
632 bool valid_anchor, valid_pdu, valid_crc;
633 std::tie( valid_anchor, valid_pdu, valid_crc ) = Hardware::received_pdu();
635 if ( valid_anchor && valid_pdu && valid_crc )
637 Hardware::stop_timeout_timer();
639 if ( is_valid_scan_request() )
641 Hardware::configure_final_transmit( response_data_ );
642 state_ = state::adv_transmitting_response;
647 adv_received_ =
true;
651 Hardware::store_timer_anchor( 0 );
658 Hardware::stop_radio();
660 state_ = state::idle;
662 else if ( state_ == state::adv_transmitting_response )
664 Hardware::stop_radio();
666 state_ = state::idle;
669 else if ( state_ == state::evt_wait_connect )
671 bool valid_anchor, valid_pdu, valid_crc;
672 std::tie( valid_anchor, valid_pdu, valid_crc ) = Hardware::received_pdu();
674 if ( valid_anchor && ( valid_pdu || valid_crc ) )
677 const auto trans = ( receive_buffer_.buffer == &empty_receive_[ 0 ] || !valid_crc )
678 ? this->next_transmit()
680 ? this->received( receive_buffer_ )
681 : this->acknowledge( receive_buffer_ ) );
686 const_cast< std::uint8_t*
>( trans.buffer )[ 0 ] = trans.buffer[ 0 ] & ~more_data_flag;
688 if ( trans.buffer[ 1 ] != 0 )
689 events_.last_transmitted_not_empty =
true;
691 Hardware::configure_final_transmit( trans );
692 state_ = state::evt_transmiting_closing;
696 Hardware::stop_radio();
697 events_.error_occured =
true;
699 state_ = state::idle;
702 else if ( state_ == state::evt_transmiting_closing )
708 static constexpr std::size_t ll_pdu_overhead = 1 + 4 + 2 + 3;
709 const int total_pdu_length = ( receive_buffer_.buffer[ 1 ] + ll_pdu_overhead ) * 8;
713 Hardware::store_timer_anchor( -total_pdu_length );
715 if ( receive_buffer_.buffer[ 1 ] != 0 )
716 events_.last_received_not_empty =
true;
718 if ( receive_buffer_.buffer[ 0 ] & more_data_flag )
719 events_.last_received_had_more_data =
true;
721 Hardware::stop_radio();
722 state_ = state::idle;
727 assert(!
"Invalid state");
731 bool is_valid_scan_request()
const
733 static constexpr std::uint8_t scan_request_size = 12;
734 static constexpr std::uint8_t scan_request_pdu_type = 0x03;
735 static constexpr std::uint8_t pdu_type_mask = 0x0F;
736 static constexpr int pdu_header_size = 2;
737 static constexpr int addr_size = 6;
738 static constexpr std::uint8_t tx_add_mask = 0x40;
739 static constexpr std::uint8_t rx_add_mask = 0x80;
742 if ( !response_data_.buffer )
745 if ( Hardware::resolving_address_invalid() )
748 if ( receive_buffer_.buffer[ 1 ] != scan_request_size )
751 if ( ( receive_buffer_.buffer[ 0 ] & pdu_type_mask ) != scan_request_pdu_type )
754 const int pdu_gap = Hardware::pdu_gap_required_by_encryption();
756 if ( !std::equal( &receive_buffer_.buffer[ pdu_header_size + addr_size + pdu_gap ], &receive_buffer_.buffer[ pdu_header_size + 2 * addr_size + pdu_gap ],
757 &response_data_.buffer[ pdu_header_size + pdu_gap ] ) )
762 const bool scanner_addres_is_random = response_data_.buffer[ 0 ] & tx_add_mask;
763 if ( !
static_cast< bool >( receive_buffer_.buffer[ 0 ] & rx_add_mask ) == scanner_addres_is_random )
766 const link_layer::device_address scanner( &receive_buffer_.buffer[ pdu_header_size + pdu_gap ], scanner_addres_is_random );
768 return static_cast< const CallBacks*
>( this )->is_scan_request_in_filter( scanner );
771 volatile bool adv_timeout_;
772 volatile bool adv_received_;
773 volatile bool evt_timeout_;
774 volatile bool end_evt_;
775 volatile bool request_event_cancelation_;
776 volatile int wake_up_;
783 adv_transmitting_response,
784 adv_shutting_down_radio,
787 evt_transmiting_closing,
790 volatile state state_;
792 link_layer::read_buffer receive_buffer_;
793 link_layer::write_buffer response_data_;
794 std::uint8_t empty_receive_[ 3 ];
795 link_layer::connection_event_events events_;
799 std::size_t TransmitSize,
800 std::size_t ReceiveSize,
801 bool EnabledEncryption,
804 typename ... RadioOptions
809 std::size_t TransmitSize,
810 std::size_t ReceiveSize,
813 typename ... RadioOptions
815 class nrf52_radio< TransmitSize, ReceiveSize, false, CallBacks, Hardware, RadioOptions... > :
816 public nrf52_radio_base< CallBacks, Hardware, bluetoe::link_layer::ll_data_pdu_buffer< TransmitSize, ReceiveSize, nrf52_radio< TransmitSize, ReceiveSize, false, CallBacks, Hardware, RadioOptions... > >,
820 static constexpr bool hardware_supports_encryption =
false;
822 void increment_receive_packet_counter() {}
823 void increment_transmit_packet_counter() {}
827 std::size_t TransmitSize,
828 std::size_t ReceiveSize,
831 typename ... RadioOptions
833 class nrf52_radio< TransmitSize, ReceiveSize, true, CallBacks, Hardware, RadioOptions... > :
834 public nrf52_radio_base<
837 bluetoe::link_layer::ll_data_pdu_buffer< TransmitSize, ReceiveSize,
838 nrf52_radio< TransmitSize, ReceiveSize, true, CallBacks, Hardware, RadioOptions... > >,
840 public security_tool_box
843 static constexpr bool hardware_supports_lesc_pairing =
true;
844 static constexpr bool hardware_supports_legacy_pairing =
true;
845 static constexpr bool hardware_supports_encryption = hardware_supports_lesc_pairing || hardware_supports_legacy_pairing;
847 using radio_base_t = nrf52_radio_base<
851 nrf52_radio< TransmitSize, ReceiveSize,
true, CallBacks, Hardware, RadioOptions... > >,
854 nrf52_radio() : radio_base_t( encrypted_message_.data )
858 std::pair< std::uint64_t, std::uint32_t > setup_encryption( bluetoe::details::uint128_t key, std::uint64_t skdm, std::uint32_t ivm )
860 return Hardware::setup_encryption( key, skdm, ivm );
866 void start_receive_encrypted()
868 Hardware::configure_encryption(
true,
false );
874 void start_transmit_encrypted()
876 Hardware::configure_encryption(
true,
true );
882 void stop_receive_encrypted()
884 Hardware::configure_encryption(
false,
true );
890 void stop_transmit_encrypted()
892 Hardware::configure_encryption(
false,
false );
895 void increment_receive_packet_counter()
897 Hardware::increment_receive_packet_counter();
900 void increment_transmit_packet_counter()
902 Hardware::increment_transmit_packet_counter();
911 void set_identity_resolving_key(
const details::identity_resolving_key_t& irk )
913 Hardware::set_identity_resolving_key( irk );
920 struct alignas( 4 ) encrypted_message_t {
921 std::uint8_t data[ 260 ];
922 } encrypted_message_;
925 template <
typename Server,
bool EnabledEncryption,
typename RadioOptions,
typename LinkLayerOptions >
926 struct link_layer_factory;
928 template <
typename Server,
bool EnabledEncryption,
typename ... RadioOptions,
typename ... LinkLayerOptions >
929 struct link_layer_factory< Server, EnabledEncryption, std::tuple< RadioOptions... >, std::tuple< LinkLayerOptions... > >
931 using radio_hardware_t =
typename details::select_type<
933 radio_hardware_with_crypto_support,
934 radio_hardware_without_crypto_support >::type;
937 std::size_t TransmitSize,
938 std::size_t ReceiveSize,
941 using radio_t = nrf52_radio< TransmitSize, ReceiveSize, EnabledEncryption, CallBacks, radio_hardware_t, RadioOptions... >;
947 namespace link_layer {
955 std::size_t TransmitSize,
956 std::size_t ReceiveSize,
959 typename ... RadioOptions
961 struct pdu_layout_by_radio<
962 nrf52_details::nrf52_radio< TransmitSize, ReceiveSize, true, CallBacks, Hardware, RadioOptions... > >
968 using pdu_layout = bluetoe::nrf_details::encrypted_pdu_layout;
982 template <
class Server,
typename ... Options >
983 using nrf52 =
typename nrf52_details::link_layer_factory<
985 details::requires_encryption_support_t< Server >::value,
986 typename nrf52_details::radio_options< Options... >::result,
987 typename nrf52_details::link_layer_options< Options... >::result
positiv time quantum used to express distance in time.
Definition: delta_time.hpp:14
static delta_time usec(std::uint32_t usec)
creates a delta_time from a positive number of µs (Microseconds).
link layer implementation
Definition: link_layer.hpp:489
ring buffers for ingoing and outgoing LL Data PDUs
Definition: ll_data_pdu_buffer.hpp:38
typename nrf52_details::link_layer_factory< Server, details::requires_encryption_support_t< Server >::value, typename nrf52_details::radio_options< Options... >::result, typename nrf52_details::link_layer_options< Options... >::result >::link_layer nrf52
binding for nRF52 microcontrollers
Definition: nrf52.hpp:988
default_pdu_layout pdu_layout
the layout to be applied when Radio is used
Definition: default_pdu_layout.hpp:108
type suitable to store the location and size of a chunk of memory that can be used to receive from th...
Definition: buffer.hpp:18
std::uint8_t * buffer
Definition: buffer.hpp:24
std::size_t size
Definition: buffer.hpp:30
type suitable to store the location and size of a chunk of memory that can be used to transmit to the...
Definition: buffer.hpp:85
std::size_t size
Definition: buffer.hpp:90
configure the low frequency clock to run from the RC oscilator.
Definition: nrf.hpp:163
configure the high frequency crystal oscillator startup time
Definition: nrf.hpp:203