nRF5340 clock sources

Hello !

It is not so clear default clock sources on nRF5340 app and net cores.

1.

As zephyr clock sources, SYSTICK timers are in use in both cores and timer clocking from external 32kHz XTAL oscillator.

Is this so ?

Should I specify  CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y in prj.conf this line and for what core ?

2. RTCx timers is not used by default.

if I need to use those ( RTC0 on app core, RTC1 on net core), I should specify CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y on both core's configuration ?

3. App core CPU clock is 128Mhz by default.

How to be sure if it clocked from XTAL oscillator ?

How to change clock to 64Mhz ?

4. Net core CPU clock is 64 Mhz by default.

How I be sure if it clocked from crystal oscillator ?

I can see clock_init() what use

clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
Should I use this code for app core as well or only on net core ?
On net core I use NRF_TIMER2 and RADIO and they need to be clocked form HF XTAL.
Regards,
Eugene

Parents
  • Hi,

    It's best to specify for each core what clock source they should run at. 

    The RTC is not a viable clock source for the Low Frequency Controller. 

    The documentation states:

    Each core has a number of low frequency clock (LFCLK) control instances. Each instance distributes one or more clocks to the core.

    The LFCLK control instance in each core distributes the 32.768 kHz PCLK32KI peripheral clock to its corresponding core. The LFCLK clock is sourced from the power and clock subsystem to each LFCLK control instance.

    In order to generate the LFCLK clock, the LFCLK controller uses the following LFCLK sources:
    32.768 kHz RC oscillator (LFRC)
    32.768 kHz crystal oscillator (LFXO)
    32.768 kHz synthesized from HFCLK (LFSYNT)

    The RTC will run off the LFCLK.

    When started, the RTC will automatically request the LFCLK source with RC oscillator if the LFCLK is not already running.

    You can check what clock source the LFCLK is running at by checking the LFCLKSTAT register.

    regards

    Jared 

  • Hi Jared !

    But what about HFLK XTAL. Should I do some enabling of it ?

    Some radio samples requiest it by _nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);

    other not.

    Regards,

    Eugene

  • Hi Jared !

    I'm not using Sofdevice. Net core have one IPC channel with app core ( Like in sample). And after that own radio, timer2 and DPPI channels. nrf and nfrx API and direct access to registers in use.

    What is right way for wakeup HFXO  ?

    Regards,

    Eugene

  • Hi Eugene

    Jared is currently out of office, and I will help you out in the mean time. 

    As it happens the proprietary ESB protocol also require you to start the HFXO manually, and you can see how the samples do it here

    If you are doing something proprietary I would recommend having a look at the ESB protocol, as it handles a lot of the low level radio management for you. 

    Best regards
    Torbjørn 

  • Hi Torbjørn  !

    I have printed few registers on netcore :

    [00:00:00.007,049] <inf> xxx: NRF_CLOCK->HFCLKSRC : 0x00000001
    [00:00:00.007,049] <inf> xxx: NRF_CLOCK->HFCLKSTAT : 0x00010001
    [00:00:00.007,080] <inf> xxx: NRF_CLOCK->LFCLKSRC : 0x00000002
    [00:00:00.007,080] <inf> xxx: NRF_CLOCK->LFCLKSTAT : 0x00010002

    Looks like both oscillators start properly,

    Do you have idea if any extra clocks need to be enabled in case of DPP usage ?

    They dosn't work in way like in your radio drivers and may be Zephyr or others have enabled extra configurations ?

    Regards,

    Eugene

     

  • Hi Eugene

    Hiihtaja said:
    Do you have idea if any extra clocks need to be enabled in case of DPP usage ?

    I assume you mean DPPI?

    The DPPI controller will request a high frequency clock source whenever it needs to send a signal from one peripheral to another. 

    The DPPI does not need to use external crystal for the HF clock. If the HFXO is running it will use it, otherwise it will simply use the internal RC oscillator (which starts up much quicker). 

    Are you having problems getting your DPPI channels to work?

    Best regards
    Torbjørn

  • Hi Torbjørn !

    Yes . I have problem with DPPI.

    in nRF52 I have used

    TIMERX is TIMER2

    /* Ready Event */
    NRF_PPI->CH[RADIO_READY_CH].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY;
    NRF_PPI->CH[RADIO_READY_CH].TEP = (uint32_t)&NRF_TIMERX->TASKS_CAPTURE[TIMESTAMP_REG];
     
    /* Address Event */
    NRF_PPI->CH[RADIO_ADDRESS_CH].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
    NRF_PPI->CH[RADIO_ADDRESS_CH].TEP = (uint32_t)&NRF_TIMERX->TASKS_CAPTURE[TIMESTAMP_REG];
    NRF_PPI->CHENSET = (1UL << RADIO_READY_CH) | (1UL << RADIO_ADDRESS_CH) | (1UL << RADIO_END_CH);

    /* Configure PPI for RADIO TX/RX */
    NRF_PPI->CH[RADIO_TXEN_CH].EEP = (uint32_t)&NRF_TIMERX->EVENTS_COMPARE[SCHEDULE_REG];
    NRF_PPI->CH[RADIO_TXEN_CH].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
    NRF_PPI->CH[RADIO_RXEN_CH].EEP = (uint32_t)&NRF_TIMERX->EVENTS_COMPARE[SCHEDULE_REG];
    NRF_PPI->CH[RADIO_RXEN_CH].TEP = (uint32_t)&NRF_RADIO->TASKS_RXEN;
    And RX/TX I have enabled when need.
    in nRF53 I have created channels and configure those and enable when need.
    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_READY, ppi_radio_events_ready);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_ready);

    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, ppi_radio_events_address);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_address);
     

    nrf_timer_publish_set(NRF_TIMERX, NRF_TIMER_EVENT_COMPARE2, ppi_radio_tx_enable);
    nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, ppi_radio_tx_enable);

    nrf_timer_publish_set(NRF_TIMERX, NRF_TIMER_EVENT_COMPARE2, ppi_radio_rx_enable);
    nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, ppi_radio_rx_enable);
    And events are not generated. I can see  code samples when EGU in use also.
    But can I be sure if my DPPI channels configured properly and I just enable/disable those when need ?
    Or those pairs need some EGU proxy or the need to be cleaned after each event or something else.
    I think channel can pass any amount of events and I just need to clean target in time for avoid lost of next one.
    Regards,
    Eugene
Reply
  • Hi Torbjørn !

    Yes . I have problem with DPPI.

    in nRF52 I have used

    TIMERX is TIMER2

    /* Ready Event */
    NRF_PPI->CH[RADIO_READY_CH].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY;
    NRF_PPI->CH[RADIO_READY_CH].TEP = (uint32_t)&NRF_TIMERX->TASKS_CAPTURE[TIMESTAMP_REG];
     
    /* Address Event */
    NRF_PPI->CH[RADIO_ADDRESS_CH].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
    NRF_PPI->CH[RADIO_ADDRESS_CH].TEP = (uint32_t)&NRF_TIMERX->TASKS_CAPTURE[TIMESTAMP_REG];
    NRF_PPI->CHENSET = (1UL << RADIO_READY_CH) | (1UL << RADIO_ADDRESS_CH) | (1UL << RADIO_END_CH);

    /* Configure PPI for RADIO TX/RX */
    NRF_PPI->CH[RADIO_TXEN_CH].EEP = (uint32_t)&NRF_TIMERX->EVENTS_COMPARE[SCHEDULE_REG];
    NRF_PPI->CH[RADIO_TXEN_CH].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
    NRF_PPI->CH[RADIO_RXEN_CH].EEP = (uint32_t)&NRF_TIMERX->EVENTS_COMPARE[SCHEDULE_REG];
    NRF_PPI->CH[RADIO_RXEN_CH].TEP = (uint32_t)&NRF_RADIO->TASKS_RXEN;
    And RX/TX I have enabled when need.
    in nRF53 I have created channels and configure those and enable when need.
    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_READY, ppi_radio_events_ready);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_ready);

    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, ppi_radio_events_address);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_address);
     

    nrf_timer_publish_set(NRF_TIMERX, NRF_TIMER_EVENT_COMPARE2, ppi_radio_tx_enable);
    nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, ppi_radio_tx_enable);

    nrf_timer_publish_set(NRF_TIMERX, NRF_TIMER_EVENT_COMPARE2, ppi_radio_rx_enable);
    nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, ppi_radio_rx_enable);
    And events are not generated. I can see  code samples when EGU in use also.
    But can I be sure if my DPPI channels configured properly and I just enable/disable those when need ?
    Or those pairs need some EGU proxy or the need to be cleaned after each event or something else.
    I think channel can pass any amount of events and I just need to clean target in time for avoid lost of next one.
    Regards,
    Eugene
Children
  • Hi Eugene

    Do you remember to allocate and enable the DPPI channels that you are using? 

    You should allocate them first (like shown here), then configure the publish and subscribe registers, before ensuring to enable the channels you need (like shown here).

    Best regards
    Torbjørn 

  • Hi Torbjørn !

    Yes,

    I allocate and specify publish/subscribe pairs.

    After that after each disable period

    nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
    I have enabled  required channels, enable RX or TX task.
    and  disable all channels after RX/TX transaction or timeout.
    So I can just enable/disable channels and clearing source of event if need.
    No need to refresh publish/subscribe pairs and clean/enable something else ?
    Looks like in my scheme only timer can cause problems if event is not generated.
    Regards,
    Eugene
  • Hi Eugene

    Once configured a PPI or DPPI channel will just operate in the background without needing any upkeep, refresh etc. 

    Even if the event register is not cleared, or you don't have interrupts enabled for certain events, they will still be available through the DPPI and trigger tasks whenever they occur. 

    If the channels don't appear to work it's typically caused by a configuration issue, by forgetting to enable the channels, or that the receiving peripheral gets the task at the wrong time (when it is not in a state to process that task for instance). 

    Is it intentional that you have two different events connected to the same capture register (CAPTURE1), and that you use the same compare register to trigger both TXEN and RXEN (COMPARE2) ?

    Best regards
    Torbjørn

  • Hi Torbjørn !

    Yes TX and RX is not enabled at the same time.

    I can see difference between nRF52 and nRF53 only in case that  DPPI channel need to be allocated from pool once and used after that.

    Channels should be usable all the time.

    TX/RX need to be enabled/disabled only when mode change from TX to RX and vise versa.

    Channels publish and subscribe can be reconfigured with the same values multiple times.

    If channel enabled, it should conduct event from source to target . (  Timer's event ISR can be enabled or not )

    All DPPI operations can be done in ISR context.

    If radio disabled for a while, no need to refresh public/subscribe pairs.

    When radio disabled, all DPPI channels are also disabled.

    But something else exist what do DPPI not working as expected.

    I need to write more simple radio for be sure if all pairs works as expected.

    Regards,

    Eugene

  • Hi Torbjørn !

    I found difference.

    It is not possible to specify beforehand pairs where the same subscribe is used ( even channel is different)

    Internally it make last subscribe active only. Even channels are disabled and freed every TX loop.

    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_READY, ppi_radio_events_ready);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_ready);

    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, ppi_radio_events_address);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_address);

    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_END, ppi_radio_events_end);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_end);

     I need to to do sequentially if would like to collect all events
    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_READY, ppi_radio_events_ready);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_ready);
    enable
    Get interrupt for READY
    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, ppi_radio_events_address);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_address);
    enable
    Get interrupt for ADDRESS
    nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_END, ppi_radio_events_end);
    nrf_timer_subscribe_set(NRF_TIMERX, NRF_TIMER_TASK_CAPTURE1, ppi_radio_events_end);
    enable
    Get interrupt for END
    In this way it works.
    Have it sense for DPPI ?
    Regards,
    Eugene
Related