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

How to properly configure periodic SPI transfers with PPI and TIMER?

I'm working on a BLE application based on the Zephyr RTOS. I need to read a SPI device at fixed time intervals and, as already suggested me here at point 3, I'm trying to implement a PPI channel that connects the TIMER0 event to the SPI task. I wrote a simple code just to test this feature but it' doesn't work, sure cause I lost something:

#include <zephyr.h>
#include <logging/log.h>

#define LOG_MODULE_NAME main
LOG_MODULE_REGISTER( LOG_MODULE_NAME );

#define SCK_PIN                    0x04
#define MISO_PIN                   0x1D
#define MOSI_PIN                   0x1C
#define CS_PIN                     0x03

static const nrfx_timer_t timerInst = NRFX_TIMER_INSTANCE( 0 );
static const nrfx_spim_t spiInst = NRFX_SPIM_INSTANCE( 0 );
static const nrfx_spim_config_t spiConfig = NRFX_SPIM_DEFAULT_CONFIG( SCK_PIN, MOSI_PIN, MISO_PIN, CS_PIN );
nrf_ppi_channel_t readingPpiChan;
static uint32_t readingTaskAddr;
static uint32_t readingEventAddr;
static uint8_t tempBuff[ 2 ];
static uint8_t tempReg;

void Timer_Handler( nrf_timer_event_t event_type, void *p_context )
{
    
}

nrfx_err_t Spi_Timer_Ppi_Init( void )
{
    nrfx_err_t err; 

    err = nrfx_spim_init( &spiInst, &spiConfig, NULL, NULL );

    if ( err != NRFX_SUCCESS )
    {
        LOG_ERR( "nrfx_spim_init error: %08X", err );
        return err;
    }

    tempReg = 0x80;
    nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TRX( &tempReg, 1, tempBuff, 2 );
    uint32_t flags = NRFX_SPIM_FLAG_HOLD_XFER | NRFX_SPIM_FLAG_RX_POSTINC | NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER | NRFX_SPIM_FLAG_REPEATED_XFER;
    err = nrfx_spim_xfer( &spiInst, &xfer, flags );

    if ( err == NRFX_SUCCESS )
    {
        readingTaskAddr = nrfx_spim_start_task_get( &spiInst );
    }

    nrfx_timer_config_t timerConfig = NRFX_TIMER_DEFAULT_CONFIG;
    timerConfig.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err = nrfx_timer_init( &timerInst, &timerConfig, Timer_Handler );

    if ( err != NRFX_SUCCESS )
    {
        LOG_ERR( "nrfx_timer_init error: %08X", err );
        return err;
    }

    nrfx_timer_compare( &timerInst, NRF_TIMER_CC_CHANNEL0, nrfx_timer_ms_to_ticks( &timerInst, 1000 ), false );
    nrfx_timer_enable( &timerInst );

    err = nrfx_ppi_channel_alloc( &readingPpiChan );

    if ( err != NRFX_SUCCESS )
    {
        LOG_ERR( "nrfx_ppi_channel_alloc error: %08X", err );
        return err;
    }

    readingEventAddr = nrfx_timer_compare_event_address_get( &timerInst, readingPpiChan );
    err = nrfx_ppi_channel_assign( readingPpiChan, readingEventAddr, readingTaskAddr );

    if ( err != NRFX_SUCCESS )
    {
        LOG_ERR( "nrfx_ppi_channel_assign error: %08X", err );
        return err;
    }

    err = nrfx_ppi_channel_enable( readingPpiChan );

    if ( err != NRFX_SUCCESS )
    {
        LOG_ERR( "nrfx_ppi_channel_enable error: %08X", err );
        return;
    }

    return NRFX_SUCCESS;
}

void main( void )
{
    Spi_Timer_Ppi_Init();

    while ( 1 )
    {
        
    }
}

I have some doubts:

1) Here it describes that if I wanto to use the NRFX_SPIM_FLAG_HOLD_XFER flag I must to set the chip select pin as NRFX_SPIM_PIN_NOT_USED and manage it outside the driver. How I should do it if the tranfers are supposed to be autonomous?

2) To generate the TIMER0 event in the PPI can I set false the enable_int parameter in the nrfx_timer_compare function or I have to set it as true? Because if I enable the interrupt, the Zephyr OS crash and restart the chip.

What am I doing wrong? Can you help me?

Related