From 1f450fe42cef43d9f6c6d9513f5f80640719c06a Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 19 Mar 2016 22:19:21 +0100 Subject: [PATCH 1/8] nrf5x: add blocking retarget impl --- port/nrf5x/pca10028/armgcc/Makefile | 2 +- .../nrf5x/{retarget.c => retarget_blocking.c} | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) rename port/nrf5x/{retarget.c => retarget_blocking.c} (77%) diff --git a/port/nrf5x/pca10028/armgcc/Makefile b/port/nrf5x/pca10028/armgcc/Makefile index e65a797d9..64d8d81b6 100755 --- a/port/nrf5x/pca10028/armgcc/Makefile +++ b/port/nrf5x/pca10028/armgcc/Makefile @@ -71,7 +71,7 @@ INC_PATHS += -I$(abspath ../../../../../components/toolchain/gcc) # BTstack territory BTSTACK_ROOT = ../../../../../components/btstack C_SOURCE_FILES += $(abspath $(BTSTACK_ROOT)/port/nrf5x/main.c) -C_SOURCE_FILES += $(abspath $(BTSTACK_ROOT)/port/retarget.c) +C_SOURCE_FILES += $(abspath $(BTSTACK_ROOT)/port/retarget_blocking.c) C_SOURCE_FILES += $(abspath $(BTSTACK_ROOT)/platform/embedded/btstack_run_loop_embedded.c) C_SOURCE_FILES += $(abspath $(BTSTACK_ROOT)/src/ble/ad_parser.c) C_SOURCE_FILES += $(abspath $(BTSTACK_ROOT)/src/btstack_linked_list.c) diff --git a/port/nrf5x/retarget.c b/port/nrf5x/retarget_blocking.c similarity index 77% rename from port/nrf5x/retarget.c rename to port/nrf5x/retarget_blocking.c index 91462b94a..c77def4d5 100755 --- a/port/nrf5x/retarget.c +++ b/port/nrf5x/retarget_blocking.c @@ -10,6 +10,8 @@ * */ +// BTstack patch: block on full outgoing buffer + #if !defined(NRF_LOG_USES_RTT) || NRF_LOG_USES_RTT != 1 #include @@ -45,7 +47,11 @@ int fputc(int ch, FILE * p_file) { UNUSED_PARAMETER(p_file); - UNUSED_VARIABLE(app_uart_put((uint8_t)ch)); + int res; + do { + res = app_uart_put((uint8_t)ch); + } while (res); + return ch; } @@ -60,7 +66,11 @@ int _write(int file, const char * p_char, int len) for (i = 0; i < len; i++) { - UNUSED_VARIABLE(app_uart_put(*p_char++)); + int res; + do { + res = app_uart_put((uint8_t)*p_char); + } while (res); + p_char++; } return len; @@ -89,7 +99,11 @@ __ATTRIBUTES size_t __write(int file, const unsigned char * p_char, size_t len) for (i = 0; i < len; i++) { - UNUSED_VARIABLE(app_uart_put(*p_char++)); + int res; + do { + res = app_uart_put((uint8_t)*p_char); + } while (res); + p_char++; } return len; From 211c43a022b66a54396161f30d9fc28894138ccb Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 19 Mar 2016 22:35:30 +0100 Subject: [PATCH 2/8] nrf5x: use radio end event irq to process adv pdu --- port/nrf5x/main.c | 64 +++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/port/nrf5x/main.c b/port/nrf5x/main.c index b1b277a22..0c3ad2be1 100755 --- a/port/nrf5x/main.c +++ b/port/nrf5x/main.c @@ -194,6 +194,9 @@ static void radio_init(void){ // Shorts: // - READY->START NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos; + + // Disable all interrrupts + NRF_RADIO->INTENCLR = 0xffffffff; } @@ -226,6 +229,9 @@ void radio_receive_on_channel(int channel){ // ramp up receiver NRF_RADIO->TASKS_RXEN = 1; + + // enable IRQ for END event + NRF_RADIO->INTENSET = RADIO_INTENSET_END_Enabled << RADIO_INTENSET_END_Pos; } // static @@ -251,7 +257,31 @@ void radio_dump_packet(void){ } void RADIO_IRQHandler(void){ - // packet received? + + if (ll_state == LL_STATE_SCANNING && NRF_RADIO->EVENTS_END){ + // adv received + + // check if outgoing buffer available + if (hci_outgoing_event_ready){ + // ... for now, we just throw the adv away and try to receive the next one + } else { + int len = rx_adv_buffer[1] & 0x3f; + hci_outgoing_event[0] = HCI_EVENT_LE_META; + hci_outgoing_event[1] = 11 + len - 6; + hci_outgoing_event[2] = HCI_SUBEVENT_LE_ADVERTISING_REPORT; + hci_outgoing_event[3] = 1; + hci_outgoing_event[4] = rx_adv_buffer[0] & 0x0f; + hci_outgoing_event[5] = (rx_adv_buffer[0] & 0x40) ? 1 : 0; + memcpy(&hci_outgoing_event[6], &rx_adv_buffer[2], 6); + hci_outgoing_event[12] = len - 6; // rest after bd addr + memcpy(&hci_outgoing_event[13], &rx_adv_buffer[8], len - 6); + hci_outgoing_event[13 + len - 6] = 0; // TODO: measure RSSI and set here + hci_outgoing_event_ready = 1; + } + // restart receiving + NRF_RADIO->TASKS_START = 1; + } + NRF_RADIO->EVENTS_END = 0; } static uint8_t random_generator_next(void){ @@ -333,33 +363,12 @@ uint8_t ll_set_scan_enable(uint8_t le_scan_enable, uint8_t filter_duplicates){ static int transport_run(btstack_data_source_t * ds){ - - // ad-hoc way to trigger stuff + // deliver hci packet on main thread if (hci_outgoing_event_ready){ hci_outgoing_event_ready = 0; packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, hci_outgoing_event[1]+2); return 0; } - - if (ll_state == LL_STATE_SCANNING && NRF_RADIO->EVENTS_END){ - // adv received - int len = rx_adv_buffer[1] & 0x3f; - hci_outgoing_event[0] = HCI_EVENT_LE_META; - hci_outgoing_event[1] = 11 + len - 6; - hci_outgoing_event[2] = HCI_SUBEVENT_LE_ADVERTISING_REPORT; - hci_outgoing_event[3] = 1; - hci_outgoing_event[4] = rx_adv_buffer[0] & 0x0f; - hci_outgoing_event[5] = (rx_adv_buffer[0] & 0x40) ? 1 : 0; - memcpy(&hci_outgoing_event[6], &rx_adv_buffer[2], 6); - hci_outgoing_event[12] = len - 6; // rest after bd addr - memcpy(&hci_outgoing_event[13], &rx_adv_buffer[8], len - 6); - hci_outgoing_event[13 + len - 6] = 0; // TODO: measure RSSI and set here - hci_outgoing_event_ready = 1; - packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, hci_outgoing_event[1]+2); - // restart receiving - NRF_RADIO->TASKS_START = 1; - return 0; - } return 0; } @@ -473,6 +482,11 @@ int main(void) init_timer(); radio_init(); + // enable Radio IRQs + NVIC_SetPriority( RADIO_IRQn, 0 ); + NVIC_ClearPendingIRQ( RADIO_IRQn ); + NVIC_EnableIRQ( RADIO_IRQn ); + // Bring up BTstack printf("BTstack on Nordic nRF5 SDK\n"); @@ -505,10 +519,6 @@ int main(void) while (1){}; #if 0 - // enable Radio IRQs - // NVIC_SetPriority( RADIO_IRQn, 0 ); - // NVIC_ClearPendingIRQ( RADIO_IRQn ); - // NVIC_EnableIRQ( RADIO_IRQn ); // start listening radio_receive_on_channel(37); From 666f0f1a25588ff2e2cec563f3ee1a0262b4d6a1 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 19 Mar 2016 22:48:24 +0100 Subject: [PATCH 3/8] nrf5x: use mutex to protect outgoing event buffer --- port/nrf5x/main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/port/nrf5x/main.c b/port/nrf5x/main.c index 0c3ad2be1..ae5568998 100755 --- a/port/nrf5x/main.c +++ b/port/nrf5x/main.c @@ -57,7 +57,8 @@ static uint8_t rx_adv_buffer[2 + MAXLEN]; static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); static hci_transport_t hci_transport; static uint8_t hci_outgoing_event[258]; -static uint8_t hci_outgoing_event_ready; +static volatile uint8_t hci_outgoing_event_ready; +static volatile uint8_t hci_outgoing_event_free; static btstack_data_source_t hci_transport_data_source; // Link Layer State @@ -258,13 +259,14 @@ void radio_dump_packet(void){ void RADIO_IRQHandler(void){ - if (ll_state == LL_STATE_SCANNING && NRF_RADIO->EVENTS_END){ + // IRQ only triggered on EVENTS_END so far + NRF_RADIO->EVENTS_END = 0; + + if (ll_state == LL_STATE_SCANNING){ // adv received // check if outgoing buffer available - if (hci_outgoing_event_ready){ - // ... for now, we just throw the adv away and try to receive the next one - } else { + if (hci_outgoing_event_free){ int len = rx_adv_buffer[1] & 0x3f; hci_outgoing_event[0] = HCI_EVENT_LE_META; hci_outgoing_event[1] = 11 + len - 6; @@ -277,11 +279,12 @@ void RADIO_IRQHandler(void){ memcpy(&hci_outgoing_event[13], &rx_adv_buffer[8], len - 6); hci_outgoing_event[13 + len - 6] = 0; // TODO: measure RSSI and set here hci_outgoing_event_ready = 1; + } else { + // ... for now, we just throw the adv away and try to receive the next one } // restart receiving NRF_RADIO->TASKS_START = 1; } - NRF_RADIO->EVENTS_END = 0; } static uint8_t random_generator_next(void){ @@ -367,6 +370,7 @@ static int transport_run(btstack_data_source_t * ds){ if (hci_outgoing_event_ready){ hci_outgoing_event_ready = 0; packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, hci_outgoing_event[1]+2); + hci_outgoing_event_free = 1; return 0; } return 0; @@ -481,6 +485,7 @@ int main(void) init_timer(); radio_init(); + hci_outgoing_event_free = 1; // enable Radio IRQs NVIC_SetPriority( RADIO_IRQn, 0 ); From f0c05fddac5113352f3423b777a5f0398fdf59eb Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 19 Mar 2016 23:05:51 +0100 Subject: [PATCH 4/8] nrf5x: hunting deadlock --- port/nrf5x/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/port/nrf5x/main.c b/port/nrf5x/main.c index ae5568998..801184ee3 100755 --- a/port/nrf5x/main.c +++ b/port/nrf5x/main.c @@ -267,6 +267,7 @@ void RADIO_IRQHandler(void){ // check if outgoing buffer available if (hci_outgoing_event_free){ + hci_outgoing_event_free = 0; int len = rx_adv_buffer[1] & 0x3f; hci_outgoing_event[0] = HCI_EVENT_LE_META; hci_outgoing_event[1] = 11 + len - 6; @@ -282,9 +283,9 @@ void RADIO_IRQHandler(void){ } else { // ... for now, we just throw the adv away and try to receive the next one } - // restart receiving - NRF_RADIO->TASKS_START = 1; } + // restart receiving + NRF_RADIO->TASKS_START = 1; } static uint8_t random_generator_next(void){ From 5c34373d6d184253c514d9a299442dd541cc7d1c Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 20 Mar 2016 21:13:27 +0100 Subject: [PATCH 5/8] nrf5x: drop advs with crc error, avoids bug in ad_parser --- port/nrf5x/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/port/nrf5x/main.c b/port/nrf5x/main.c index 801184ee3..697809b78 100755 --- a/port/nrf5x/main.c +++ b/port/nrf5x/main.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "app_uart.h" #include "app_error.h" @@ -263,10 +264,10 @@ void RADIO_IRQHandler(void){ NRF_RADIO->EVENTS_END = 0; if (ll_state == LL_STATE_SCANNING){ - // adv received - // check if outgoing buffer available - if (hci_outgoing_event_free){ + // check if outgoing buffer available and if CRC was ok + if (hci_outgoing_event_free && + ((NRF_RADIO->CRCSTATUS & RADIO_CRCSTATUS_CRCSTATUS_Msk) == (RADIO_CRCSTATUS_CRCSTATUS_CRCOk << RADIO_CRCSTATUS_CRCSTATUS_Pos))){ hci_outgoing_event_free = 0; int len = rx_adv_buffer[1] & 0x3f; hci_outgoing_event[0] = HCI_EVENT_LE_META; @@ -365,7 +366,6 @@ uint8_t ll_set_scan_enable(uint8_t le_scan_enable, uint8_t filter_duplicates){ } } - static int transport_run(btstack_data_source_t * ds){ // deliver hci packet on main thread if (hci_outgoing_event_ready){ From 89fd9aef67fe62116fd20e967dcb1c32486106d7 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 20 Mar 2016 21:24:43 +0100 Subject: [PATCH 6/8] example: gap_le_advertismens - RSSI is signed int --- example/gap_le_advertisements.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/gap_le_advertisements.c b/example/gap_le_advertisements.c index ad15f802a..eeee0bded 100644 --- a/example/gap_le_advertisements.c +++ b/example/gap_le_advertisements.c @@ -248,11 +248,11 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe bd_addr_t address; reverse_bd_addr(&packet[pos], address); pos += 6; - uint8_t rssi = packet[pos++]; + int8_t rssi = (int8_t) packet[pos++]; uint8_t length = packet[pos++]; uint8_t * data = &packet[pos]; - printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %u, data[%u] ", event_type, + printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type, address_type, bd_addr_to_str(address), rssi, length); printf_hexdump(data, length); dump_advertisement_data(data, length); From aedec01ab059eeb67eaa577b0050996626f6902f Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 20 Mar 2016 21:25:05 +0100 Subject: [PATCH 7/8] nrf5x: read RSSI for adv pdus --- port/nrf5x/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/port/nrf5x/main.c b/port/nrf5x/main.c index 697809b78..978b893d0 100755 --- a/port/nrf5x/main.c +++ b/port/nrf5x/main.c @@ -195,7 +195,9 @@ static void radio_init(void){ // Shorts: // - READY->START - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos; + // - ADDRESS0>RSSISTART + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos + | RADIO_SHORTS_ADDRESS_RSSISTART_Enabled << RADIO_SHORTS_ADDRESS_RSSISTART_Pos; // Disable all interrrupts NRF_RADIO->INTENCLR = 0xffffffff; @@ -279,7 +281,7 @@ void RADIO_IRQHandler(void){ memcpy(&hci_outgoing_event[6], &rx_adv_buffer[2], 6); hci_outgoing_event[12] = len - 6; // rest after bd addr memcpy(&hci_outgoing_event[13], &rx_adv_buffer[8], len - 6); - hci_outgoing_event[13 + len - 6] = 0; // TODO: measure RSSI and set here + hci_outgoing_event[13 + len - 6] = -NRF_RADIO->RSSISAMPLE; // RSSI is stored without sign but is negative hci_outgoing_event_ready = 1; } else { // ... for now, we just throw the adv away and try to receive the next one From a0a93727326e80e743e0f732077e1d0a79de133c Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 20 Mar 2016 22:11:17 +0100 Subject: [PATCH 8/8] ad_parser: avoid infinite loop on (illegal) chunk len of 0xff --- src/ble/ad_parser.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ble/ad_parser.c b/src/ble/ad_parser.c index 1a3abfc71..eb74ad918 100644 --- a/src/ble/ad_parser.c +++ b/src/ble/ad_parser.c @@ -72,8 +72,13 @@ int ad_iterator_has_more(ad_context_t * context){ } void ad_iterator_next(ad_context_t * context){ - uint8_t chunk_len = context->data[context->offset]; - context->offset += 1 + chunk_len; + int chunk_len = context->data[context->offset]; + int new_offset = context->offset + 1 + chunk_len; + // avoid uint8_t overrun + if (new_offset > 0xff){ + new_offset = 0xff; + } + context->offset = new_offset; } uint8_t ad_iterator_get_data_len(ad_context_t * context){