This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Sending a single BLE advertising package fails

I am trying to create an application which would send data once a minute. The application is based on BLE advertising packages, because it should be the most simple method. It seems that the radio is running and the radio sends something, but I cannot find anything with nRF Connect. As a consequence, I am pretty sure that there is something wrong with the settings.

#include <stdint.h>
#include <string.h>

#include "nrf_delay.h"
#include "nrf.h"
#include "nrf_gpio.h"

#define LED_1 17
#define LED_2 18
#define LED_3 19
#define LED_4 20

#define LED_ON  0
#define LED_OFF 1

void ett_led_init (void)
{
    nrf_gpio_range_cfg_output(LED_1,LED_4);

    nrf_gpio_pin_write(LED_1, LED_OFF);
    nrf_gpio_pin_write(LED_2, LED_OFF);
    nrf_gpio_pin_write(LED_3, LED_OFF);
    nrf_gpio_pin_write(LED_4, LED_OFF);
}

void ett_led (uint8_t led_id,uint8_t state)
{
    nrf_gpio_pin_write(led_id,state);
}

// Start HFCLK, it is needed by the radio
void ett_system_init (void)
{
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;

    NRF_CLOCK->TASKS_HFCLKSTART = 1;

    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { }
}

// Init the radio, apply the minimal settings
void ett_radio_init (uint32_t * pdu)
{
    NRF_RADIO->PACKETPTR = pdu;             // Header and payload
    
    NRF_RADIO->MODE      = 0x00000003;      //  BLE 1 Mbps

    NRF_RADIO->PCNF1     = (0x03 << 16) +   // The length of the base address is three (3) bytes
                            0x10;           // The maximum length of the payload is 16 bytes, to be defined!

    NRF_RADIO->BASE0     = 0x8E89BE00;      // BLE advertising 
    NRF_RADIO->PREFIX0   = 0x000000D6;      // BLE advertising
    
    // NRF_RADIO->CRCPOLY   = 0x0100065B;      // BLE polynomial
}

// Transmit a single packet
void ett_radio_transmit ()
{
    NRF_RADIO->EVENTS_READY = 0;                  // Clear the event

    NRF_RADIO->TASKS_TXEN = 1;                    // Enable the TX

    while (NRF_RADIO->EVENTS_READY == 0) { }      // Wait until the ready
    NRF_RADIO->EVENTS_READY = 1;                  // Clear the event

    NRF_RADIO->EVENTS_END = 0;                    // Clear the event

    NRF_RADIO->TASKS_START = 1;                   // Start the TX

    while (NRF_RADIO->EVENTS_END == 0) { }        // Wait until the end
    NRF_RADIO->EVENTS_END = 0;                    // Clear the event

    NRF_RADIO->EVENTS_DISABLED = 0;               // Clear the event

    NRF_RADIO->TASKS_DISABLE = 1;                 // Disable the TX

    while (NRF_RADIO->EVENTS_DISABLED == 0) { }   // Wait until the disabled
    NRF_RADIO->EVENTS_DISABLED = 0;               // Clear the event
}

void main (void)
{
    // Auxiliary variables
    uint32_t * pdu;     // The PDU including the header and the payload

    uint8_t raw [13];   // Raw data

    // Create the raw data and the PDU
    raw[0] = (0x02 << 4) +   // Advertising nonconnectable indirect (minimal beacon)
             (0x00 << 2) +   // RFU
             (0x01 << 1) +   // TX address, random
              0x01;          // RX address, random
 
    raw[1] = (0x0B << 2) +   // The length of the payload excluding the header
              0x00;          // RFU

    raw[2]  = 0x02; // Length
    raw[3]  = 0x01; // Flags
    raw[4]  = 0x00; // No flags

    raw[5]  = 0x03; // Length
    raw[6]  = 0x03; // Service type
    raw[7]  = 0x1A; // Environmental sensing
    raw[8]  = 0x18; // Environmental sensing

    raw[9]  = 0x03; // Length
    raw[10] = 0xFF; // Manufacturer specific data
    raw[11] = 0x09; // Random data
    raw[12] = 0xC4; // Random data

    pdu = raw;      // Assign the 32-bit pointer for the packet

    // Init
    ett_led_init();        // init the leds of nRF52 DK
    ett_system_init();     // Start the HF clock
    ett_radio_init(pdu);   // Init and start the radio

    ett_led(LED_1,LED_ON);    // Turn ON led 1

    // Eternal loop, send the same packet every two seconds
    // Flash leds to indicate if a packet has been sent
    while (1) {
        nrf_delay_ms(1000);

        ett_radio_transmit();    // Transmit BLE packet

        ett_led(LED_2,LED_ON);   // Turn ON led 2

        nrf_delay_ms(1000);

        ett_led(LED_2,LED_OFF);
        ett_led(LED_3,LED_OFF);
        ett_led(LED_4,LED_OFF);
    }
}

The settings of the radio are set in lines 44-52. I am using the BLE mode (1Mbps) and the address has been set to the BLE advertising (base 0x8E89BE and prefix 0xD6). The length of the payload is 11 bytes excluding the header and therefore I have set the maximum length to 16 bytes. The CRC polynomial has been set to 0x0100065B. However, I am not sure if it is required when the BLE mode has been set and therefore it has been commented.

The PDU is create in lines 90-112. The problem might be related to the PDU as well, especially to the header, because I am pretty sure that the payload is correct. The length has been set to 11 bytes (excluding the header) and the TX and RX addresses have been set to random.

I have tested the example with nRF52 DK. The example has been implemented with nRF5 (16.0.0) and SES. I am quite sure that I am very close to a solution, but something is either missing or settings are incorrect. I am not sure if the endianness of the settings is correct.

I have tried to find a similar example, but without any success. I found some examples and I have fixed some issues, but something is still wrong. Please let me know if there is another example where a single BLE advertising package is sent.

Related