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

NRF51822 Interrupt Service Routine handling

Hello, I was using wiringPiSPI() to connect via SPI and so i was using wiringPiISR function to create an interupt handler that will do callback to the user suplied function. Now I moved to module with NRF architecture. How can I handle interuptions the way i was doing it on the Raspberry PI? I'm using spi_master.h to connect via SPI. Is there any ready to use ISR handle the way it was made on Raspberry?

  • @Krzysiek: Have you tried our SDK ? In our SDK we provide the library and driver for SPI. You can have a look here.

    But I don't really get it of what you mean by ISR handle, on SPI communication, it's always the master that initiate the data transmission.

  • I have spi_master.h so I am using your SDK that provide SPI connection. To create my SPI connection i was using the same website as you sent. Yes, master always initiate the data transmission, but slave can make interrupts and I don't know exactly how coordinate the data transmission. Maybe there are funtions that in SDK that would be helpful to me?

  • Krzysiek: It's not covered in the SPI protocol, so you would need to either use the SPI Master to poll or implement an extra GPIO interrupt so that the slave can trigger the interrupt when there is data he wants to send. You can think of using the GPIOTE driver.

  • Comment field is a little to small so I will paste it here as a new post.

    I started to use GPIOTE and managed to sucesfully get interupt from external device. Next problem I have is, that when IRQHandler kicks in, whole system freezes (with APP_IRQ_PRIORITY_HIGH) or program isn't executed correctly (with APP_IRQ_PRIORITY_LOW)

    isr() function read and write to device through SPI (And here I'm not so sure what happens with concurrent SPI transmission)

    void GPIOTE_initirq()
    {
    	
    NVIC_DisableIRQ(GPIOTE_IRQn);
    	NVIC_ClearPendingIRQ(GPIOTE_IRQn);
    	NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_LOW); //Here is the problem
    
    
    NRF_GPIOTE->CONFIG[0] =  (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
    					   | (0x10 << GPIOTE_CONFIG_PSEL_Pos)   //
    					   | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
    NRF_GPIOTE->INTENSET  = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;
    
     __NOP();
     __NOP();
     __NOP();
    
     NRF_GPIOTE->EVENTS_IN[0] = 0;
     NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Enabled << GPIOTE_INTENSET_IN0_Pos;
     NVIC_EnableIRQ(GPIOTE_IRQn);
    
    }
    
    void GPIOTE_IRQHandler(void)
    {
    		process_irq();
    		NRF_GPIOTE->EVENTS_IN[0] = 0;
    }
    
    process_irq()
    {
    	do
    	{
    		isr();
    	}while(nrf_gpio_pin_read(IRQ) == 1)
    }
    

    On Raspberry Pi the following code was executed to handle interruptions:

        //port_EnableIRQ(); 
        //enable ScenSor IRQ before starting
    	// set Pin 24 generate an interrupt on high-to-low transitions
    	// and attach process_deca_irq() to the interrupt
    
    if ( wiringPiISR (IRQ_PIN, INT_EDGE_RISING, &process_deca_irq) < 0 ) {
      printf("Unable to setup ISR\r\n");
    }
    
  • I don't think it's a good idea to handle everything in a IRQ handler and stay there until the pin is released. Don't think you gonna receive the SPI interrupt if you already in a highest level priority context.

    My suggestion for you is to set a flag when in IRQHandler, and execute the SPI transmission when you are back to the main loop.

    When you mentioned you are using APP_IRQ_PRIORITY_LOW and APP_IRQ_PRIORITY_HIGH, do you have the softdevice also running ?

Related