Output HFCLK with PPI while SoftDevice is enabled

Using 52840, I would like to drive an external device at 800Khz

Works well without enabling the SoftDevice

// works well without SD enabled
void output_800KHz_noSD()
{
#define PIN 43
  nrf_gpio_cfg_output  (PIN); 

  NRF_CLOCK->TASKS_HFCLKSTART = 1; // Start high frequency clock
  while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    {
      // Wait for HFCLK to start
    }
  NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; // Clear event

  // Configure GPIOTE to toggle pin 
  unsigned long mask = 
      GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
      GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
      PIN << GPIOTE_CONFIG_PSEL_Pos |
      GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos;

  NRF_GPIOTE->CONFIG[0] = mask;


  // Configure timer
  NRF_TIMER1->PRESCALER = 0;
  NRF_TIMER1->CC[0] = 10; // Adjust the output frequency by adjusting the CC.
  NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled
                       << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
  //NRF_TIMER1->TASKS_START = 1;

  // Configure PPI
  NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
  NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];

  NRF_PPI->CHENSET = PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;

  NRF_TIMER1->TASKS_START = 1;
  
  for(;;) __WFE();
}

But once the SD is enabled - this does not work

// does not work with SD enabled - 0Hz
void output_800KHz()
{
#define PIN 43

  nrf_gpio_cfg_output (PIN);

  sd_clock_hfclk_request();
  uint32_t crystal_is_running = 0;
  while(!crystal_is_running)
  {
    sd_clock_hfclk_is_running(&crystal_is_running);
  } 

  NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Task       << GPIOTE_CONFIG_MODE_Pos)     | \
                          (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) | \
                          (PIN                           << GPIOTE_CONFIG_PSEL_Pos)     | \
                          (GPIOTE_CONFIG_OUTINIT_Low     << GPIOTE_CONFIG_OUTINIT_Pos);    

  // Configure timer
  NRF_TIMER1->PRESCALER = 0; 
  NRF_TIMER1->CC[0] = 10;     //  800KHz
  NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos; 

  // Configure PPI
  sd_ppi_channel_assign(0,&NRF_TIMER1->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[0]); 

  sd_ppi_channel_enable_set(1 << 0);

  NRF_TIMER1->TASKS_START = 1;

}

void stop_800KHz()
{
  NRF_TIMER1->TASKS_STOP = 1;
}  

Ideas?

Parents Reply Children
  • There are two come snippets above.

    1. The first one works when SD is not enabled.

    2. The second one is adapted to use SD functions, but is basically the same code - it does NOT work when the SD is enabled.

    I need any version/solution that works (output 800KHz on a SIO) while SD is running

    Thanks

  • The project starts from ble_app_interactive example, but have many changes to support various peripherals outside the chip

    (ble_cenrtral_and_peripheral -> experimental -> ble_app_interactive)

    Thanks

  • Hello,

    have you called the function 'output_800KHz()' after ble stack function? For ble_app_interactive example, you can call the function ''output_800KHz()'' after ''ble_m_init()'' under the main function.  It should work accordingly. 

    int main(void)
    {
    power_management_init();
    log_init();
    timer_init();
    // Console start
    cli_uart_cfg();
    cli_uart_start();
    #if NRF_MODULE_ENABLED(CLI_RTT)
    cli_rtt_start();
    #endif // CLI_RTT
    ble_m_init();
    output_800KHz();
    peer_manager_init();
    nfc_pairing_init();
    #if NRF_MODULE_ENABLED(ADAFRUIT_SHIELD)
    nfc_central_init();
    #endif // ADAFRUIT_SHIELD
    bond_get();
    
    NRF_LOG_RAW_INFO("BLE app with command line interface example started.\r\n");
    NRF_LOG_RAW_INFO("Press Tab to view all available commands.\r\n");
    
    for (;;)
    {
    idle_state_handler();
    }
    }

    Thanks.

    Best Regards,

    Kazi Afroza Sultana

Related