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

nRF52832 SPI master read on external interrupt

Hello,

I would like to implement an interface with an external SPI ADC using the nRF52832. The ADC has a RDY (ready) signal that goes low every time a new sample is ready to be read.

What I planned to do was to tie the RDY pin to an interrupt and use an event handler to issue an SPI read transaction every time the interrupt fires. Preferably, EasyDMA should also be used so the CPU overhead would be minimal.

However, the BLE is active, and I read a post that states that hardware interrupts should not be used while the BLE is active so as not to disturb the BLE. (I realize that this is regarding the nRF51822 so maybe this isn't relevant to the nRF52832?)

How would you recommend addressing this issue? I would like this to happen with the least CPU overhead possible.

Thanks, Michael.

  • Hi,

    Real time events that require high priorities in the CPU is a hurdle, since the SoftDevice uses the highest priorities. However, your issue can be done almost completely without using CPU.

    You can set this up using PPI, which is a hardware short between peripherals, to trigger on the input event from the ADC on a pin configured with GPIOTE. Using PPI you can trigger a SPI with EasyDMA task which will transfer directly to RAM. Then you can set a low priority interrupt flag and automatically deal with the data (if needed) when you have time.

    A very simple PPI example is provided below. The example gives a 8 MHz output on pin 18 using the capture compare event from the TIMER to trigger toggling of a GPIOTE output via PPI.

    int main(void)
    {
        // Set up GPIO as output
        nrf_gpio_range_cfg_output(17, 18);
        nrf_gpio_pin_clear(17); // Light LED 1 to indicate that the code is running
    
        // Start high frequency clock
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
        {
            // Wait for clock to start
        }
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    
        // Configure GPIOTE to toggle pin 18 
        NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
                                GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
                                18 << GPIOTE_CONFIG_PSEL_Pos | 
                                GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos;
    
        // Set up timer
        NRF_TIMER1->PRESCALER = 0;
        NRF_TIMER1->CC[0] = 2; // 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;
    
        // Set up PPI to connect the timer compare event with the GPIOTE toggle task
        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;
    
        while (true)
        {
    
        }
    }
    

    Make sure that you read the module descriptions thoroughly, also consult the SoftDevice specification, especially the part on which hardware peripherals have restricted access.

    Best regards,

    Øyvind

  • Thanks! I believe this is enough for me to get started.

Related