Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Nrf52 simple Baremetal timer function, CPU reset if interrupt enabled.

Trying to use the basic baremetal mode as my application is very simple and dont want to go through RTOS stuff.

I tried with Timer and RTC, both case if I enable the interrupt then the cpu gets rebooted.
Following is the code, not sure if it is the way I am building the code or some other parameter is messing things up.

This example if basically "..\..\sdk\nRF5_SDK_17.1.0_ddde560\examples\peripheral\timer"
I will try to upload the zip of the full project. Different peripheral works except the Interrupt part.

#include <stdio.h>
#include <nrf.h>

#define PIN_LED1 (17UL) // nrf52-dk
volatile bool bLED1Set= false;
int main(void)
{
// Start LFCLK (32kHz) crystal oscillator. If you don't have crystal on your board, choose RCOSC instead.
NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos;
NRF_CLOCK->TASKS_LFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;


// 32kHz timer period
NRF_RTC0->PRESCALER = 0;

// 30.5ms us compare value, generates EVENTS_COMPARE[0]
NRF_RTC0->CC[0] = 1000;

// Enable EVENTS_COMPARE[0] generation
NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Enabled << RTC_EVTENSET_COMPARE0_Pos;
// Enable IRQ on EVENTS_COMPARE[0]
NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE0_Enabled << RTC_INTENSET_COMPARE0_Pos;

// Enable RTC IRQ and start the RTC
NVIC_EnableIRQ(RTC0_IRQn);
NRF_RTC0->TASKS_START = 1;

// Configure GPIO pin as output with standard drive strength.
NRF_GPIO->PIN_CNF[PIN_LED1] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) |
(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
(GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);

while (1)
{
// __WFE();
if(bLED1Set){
NRF_GPIO->OUTCLR = (1UL << PIN_LED1);
bLED1Set = false;
}else{
NRF_GPIO->OUTSET = (1UL << PIN_LED1);
bLED1Set = true;
}

}
}

// This IRQ handler will trigger every 30.5 ms
void RTC0_IRQHandler(void)
{
volatile uint32_t dummy;
if (NRF_RTC0->EVENTS_COMPARE[0] == 1)
{
NRF_RTC0->EVENTS_COMPARE[0] = 0;

// Increment compare value with 30.5 ms from current time.
NRF_RTC0->CC[0] = NRF_RTC0->COUNTER + 1000;

// Read back event register so ensure we have cleared it before exiting IRQ handler.
dummy = NRF_RTC0->EVENTS_COMPARE[0];
dummy;
}
}

Parents
  • Hi Abir

    If you don't use a SoftDevice I don't know why this code would cause a crash. 

    Can you let me know what kind of hardware you are testing on?

    Is it a standard DK, or some other kind of board?

    If you can upload the entire project that would be great, then I can easily test it here. It should be enough to drag drop a file into your reply if you want to attach files. 

    Best regards
    Torbjørn

  • Try this and also init the i/o pin before enabling the timer:

    / This IRQ handler will trigger every 30.5 ms
    void RTC0_IRQHandler(void)
    {
      if (NRF_RTC0->EVENTS_COMPARE[0] == 1)
      {
        NRF_RTC0->EVENTS_COMPARE[0] = 0;
        // COUNTER and COMPARE[n] registers are all 24-bit. It seems an intermediate sampled
        // value must be used as pRTC->CC[IDX_SYS_TICK] += N; does not work for some reason,
        // maybe requires so many cycles to read back and CountValue must be synchronous (unchanging)
        //  - COUNTER register read takes a fixed 5 x PCLK16M clock cycles
        volatile uint32_t CountValue = NRF_RTC0->COUNTER;
        // Increment compare value with 30.5 ms from current time.
        NRF_RTC0->CC[0] = CountValue + 1000;
        // Data Synchronization Barrier: completes when all explicit memory accesses before
        // last instruction completes to avoid spurious interrupt
        __DSB();
      }
    }

Reply
  • Try this and also init the i/o pin before enabling the timer:

    / This IRQ handler will trigger every 30.5 ms
    void RTC0_IRQHandler(void)
    {
      if (NRF_RTC0->EVENTS_COMPARE[0] == 1)
      {
        NRF_RTC0->EVENTS_COMPARE[0] = 0;
        // COUNTER and COMPARE[n] registers are all 24-bit. It seems an intermediate sampled
        // value must be used as pRTC->CC[IDX_SYS_TICK] += N; does not work for some reason,
        // maybe requires so many cycles to read back and CountValue must be synchronous (unchanging)
        //  - COUNTER register read takes a fixed 5 x PCLK16M clock cycles
        volatile uint32_t CountValue = NRF_RTC0->COUNTER;
        // Increment compare value with 30.5 ms from current time.
        NRF_RTC0->CC[0] = CountValue + 1000;
        // Data Synchronization Barrier: completes when all explicit memory accesses before
        // last instruction completes to avoid spurious interrupt
        __DSB();
      }
    }

Children
  • Thanks for the reply both ovrebekk and hmlesworth. I will try this changes too.
    But I think it is more of a project setup issue.

    I tried similar code on uVision and working fine. I am using Vscode and used an example Zphyre project as templete. So My guess is some components/config from Zphyre is conflicting with my attempt to make project baremetal. Thats why added the project here.

    Thanks

  • Thanks for the reply both ovrebekk and hmlesworth. I will try this changes too.
    But I think it is more of a project setup issue.

    I tried similar code on uVision and working fine. I am using Vscode and used an example Zphyre project as templete. So My guess is some components/config from Zphyre is conflicting with my attempt to make project baremetal. Thats why added the project here.

    Thanks

Related