nRF52840 BLE DTM on custom board with Zephyr/NCS + LoRA radio

We have a design in EVT and we're preparing for FCC testing. It's a dual radio board with nRF52840 and a Semtech LR1110. Therefore, we need both to be active and transmitting during the test.

Is there a way to incorporate DTM code into an NCS 2.5.0 project while maintaining our only connection to the outside world -- a USB CDC device? We cannot use only HCI, we need our own CLI to be able to control both radios.

Thanks.

Parents
  • Hi Peter, 

    We don't have an example on how you can integrate DTM into your code. But the source code is available and you are free to modify it for your need. I assume you will need to have some code to convert the CLI command to be HCI command and send to the DTM code. 

    Another option which I think is easier is to use the radio_test sample, it's designed with CLI interface instead of HCI. It should be easier to integrate into your code. The configuration is slightly different compare to DTM (for example the default addresses) but many of our customers use this for FCC. 

Reply
  • Hi Peter, 

    We don't have an example on how you can integrate DTM into your code. But the source code is available and you are free to modify it for your need. I assume you will need to have some code to convert the CLI command to be HCI command and send to the DTM code. 

    Another option which I think is easier is to use the radio_test sample, it's designed with CLI interface instead of HCI. It should be easier to integrate into your code. The configuration is slightly different compare to DTM (for example the default addresses) but many of our customers use this for FCC. 

Children
  • Over the weekend I was able to integrate DTM code into the project but we ran into a huge problem with USB. Since this is an NCS 2.5.0, it appears that the USB driver is not aware of the low level radio activity and takes away the 32MHz crystal as soon as it loses VBUS. This causes DTM to fail or the frequency to shift significantly. I had to devise a sequence where TX is started on LR1110 first, then DTM is configured on the nRF, then USB stops and DTM starts. This is the only way to test a device right now.

    Is there a way take control of the HF crystal away from the USB driver?

  • Hi Peter, 
    As far as I know the clock will be handled by our onoff manager and USB driver shouldn't be able to turn off the HFCLK if the DTM is using it. 
    Could you check if clock_init() is called in the dtm code ? 
    Make sure you have CONFIG_CLOCK_CONTROL=y in the project config. 
    Please check if onoff_request() is called and if it's return 0. As far as I know if the module request clock, the onoff_release from the USB module won't be able to turn it off. 

    You can take a look at the usb_dc_nrfx.c to see how the clock release is called after the USB is detached (see usbd_work_process_pwr_events() ) 

  • Here is what we have to do to make it work:

      /**
       * The USB peripheral commandeers the HFXO and/or some other peripheral power domains and takes them down as soon as VBUS disappears. 
       * This makes concurrent USB and DTM operation impossible. The only way for DTM to work is to disable USB right now and re-start the HFXO right after.
       */
      usb_disable();
      k_msleep(100);
    
      // Start and validate HFXO
      NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
      NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
      int timeout = 10000;
      while (!NRF_CLOCK->EVENTS_HFCLKSTARTED && --timeout)
      {
        k_busy_wait(1);
      }
      k_msleep(5);
    
      led_set(LED_YELLOW_MASK);
      led_set_brightness(LED_YELLOW_MASK, 40);
    
      radio_tx_start(channel, phy, payload, txpower_dbm);
    

    The actual TX function looks like this:

    void radio_tx_start(uint8_t channel, uint8_t phy, enum ble_payload_type payload, int txpower_dbm)
    {
      uint8_t frequency = ble_channel_to_frequency(channel);
    
      /* Disable RADIO before reconfiguring */
      NRF_RADIO->TASKS_DISABLE = 1;
      while (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled)
      {
      }
    
      /* Set frequency */
      NRF_RADIO->FREQUENCY = frequency;
    
      /* Set TX power */
      switch (txpower_dbm)
      {
      case -40:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg40dBm;
        break;
      case -20:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg20dBm;
        break;
      case -4:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg4dBm;
        break;
      case 0:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm;
        break;
      case 3:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos3dBm;
        break;
      case 4:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos4dBm;
        break;
      case 8:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos8dBm;
        break;
      default:
        NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm;
        break;
      }
    
      /* Set PHY */
      if (phy == 0x01)
      {
        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
      }
      else if (phy == 0x02)
      {
        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit;
      }
      else if (phy == 0x03)
      {
        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit;
      }
      else
      {
        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
      }
    
      if (payload == PAYLOAD_CARRIER)
      {
        /* Carrier only: no packet fields */
        NRF_RADIO->PCNF0 = 0;
        NRF_RADIO->PCNF1 = 0;
        NRF_RADIO->BASE0 = 0;
        NRF_RADIO->PREFIX0 = 0;
        NRF_RADIO->PACKETPTR = 0;
        NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk;
      }
      else
      {
        /* Normal modulated packet */
        static uint8_t dummy_packet[40];
        generate_payload(dummy_packet, sizeof(dummy_packet), payload);
        NRF_RADIO->PACKETPTR = (uint32_t)dummy_packet;
    
        NRF_RADIO->PCNF0 = (8 << RADIO_PCNF0_LFLEN_Pos);
        NRF_RADIO->PCNF1 = (37 << RADIO_PCNF1_MAXLEN_Pos) |
                           (3 << RADIO_PCNF1_BALEN_Pos) |
                           (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos);
    
        NRF_RADIO->BASE0 = 0x89BED600;
        NRF_RADIO->PREFIX0 = 0x8E;
        NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_START_Msk;
      }
    
      /* Start radio TX */
      NRF_RADIO->TASKS_TXEN = 1;
    }
    

  • Additional data and evidence:

    The HFXO is disabled as soon as VBUS is lost and this also affects operation of the NOR flash during OTA. So we need to address this somehow.

    Loss of VBUS *does not affect* normal BLE stack operation. I can place the device in a shield box and I see it advertising at all the correct frequencies.

Related