Hello,
I am trying to use ArrayList for EasyDMA along with PPI but I am not sure whether or not I am configuring it properly to be used with the SPI interface.
So far I have set it up as below, in order to test the transfer I am connecting the MISO pin to ground(through a resistor) to fill the buffer with a null value. However,I never see an interruption from the configured TIMER happening, I mean, I don't see while running a call to timer_event_handler
( I have set a break point on that handler and it seems not to be called...)
Any suggestions of what might be cause not to see that interruption?
Thanks in advance,
#define SPI_INSTANCE 0 /**< SPI instance index. */
#define BUFF_LENGTH 4 /**< Transfer length. */
#define BUFF_RX_LENGTH 100
typedef struct ArrayList{
uint8_t buffer[BUFF_LENGTH];
} ArrayList_type;
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */
static uint8_t m_tx_buf[BUFF_LENGTH]; /**< TX buffer. */
//static uint8_t m_rx_buf[BUFF_LENGTH]; /**< RX buffer. */
ArrayList_type m_rx_buf[BUFF_RX_LENGTH]; /**< RX buffer. */
static volatile bool burst_completed = false;
static volatile bool spi_xfer_done = false; /**< Flag used to indicate that SPI instance completed the transfer. */
// PPI resrources
nrf_ppi_channel_t ppi_channel_spi;
nrf_ppi_channel_t ppi_channel_timer;
// Timer for burst read
const nrf_drv_timer_t timer = NRF_DRV_TIMER_INSTANCE(0);
void imu_select()
{
nrf_gpio_pin_clear(SPIM0_SS_PIN);
}
void imu_deselect()
{
nrf_gpio_pin_set(SPIM0_SS_PIN);
}
void burst_transfer_disable()
{
ret_code_t err_code;
// Configure short between spi end event and spi start task
nrf_spim_shorts_disable(spi.p_registers, NRF_SPIM_SHORT_END_START_MASK);
err_code = nrf_drv_ppi_channel_disable(ppi_channel_spi);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_disable(ppi_channel_timer);
APP_ERROR_CHECK(err_code);
nrf_drv_timer_disable(&timer);
imu_deselect();
burst_completed = true;
}
void timer_event_handler(nrf_timer_event_t event_type, void* p_context)
{
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
burst_transfer_disable();
break;
default:
//Do nothing.
break;
}
}
static void burst_setup()
{
uint32_t spi_end_evt;
uint32_t timer_count_task;
uint32_t timer_cc_event;
ret_code_t err_code;
//Configure timer
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
timer_cfg.mode = NRF_TIMER_MODE_COUNTER;
err_code = nrf_drv_timer_init(&timer, &timer_cfg, timer_event_handler);
APP_ERROR_CHECK(err_code);
// Compare event after 4 transmissions
nrf_drv_timer_extended_compare(&timer, NRF_TIMER_CC_CHANNEL0, 1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
timer_count_task = nrf_drv_timer_task_address_get(&timer, NRF_TIMER_TASK_COUNT);
timer_cc_event = nrf_drv_timer_event_address_get(&timer, NRF_TIMER_EVENT_COMPARE0);
NRF_LOG_INFO("timer configured\n");
// allocate PPI channels for hardware
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_spi);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_timer);
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("ppi allocated\n");
spi_end_evt = nrf_drv_spi_end_event_get(&spi);
// Configure the PPI to count the trasnsactions on the TIMER
err_code = nrf_drv_ppi_channel_assign(ppi_channel_spi, spi_end_evt, timer_count_task);
APP_ERROR_CHECK(err_code);
// Configure another PPI to stop the SPI when 4 transactions have been completed
err_code = nrf_drv_ppi_channel_assign(ppi_channel_timer, timer_cc_event, NRF_SPIM_TASK_STOP);
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("ppi configured\n");
}
static void burst_transfer_enable()
{
ret_code_t err_code;
burst_completed = false;
err_code = nrf_drv_ppi_channel_enable(ppi_channel_spi);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(ppi_channel_timer);
APP_ERROR_CHECK(err_code);
nrf_drv_timer_enable(&timer);
// Configure short between spi end event and spi start task
nrf_spim_shorts_enable(spi.p_registers, NRF_SPIM_SHORT_END_START_MASK);
imu_select();
}
void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
{
if(p_event->type == NRF_DRV_SPI_EVENT_DONE)
{
spi_xfer_done = true;
}
else
{
NRF_LOG_ERROR("Wrong Event\n");
// Something is wrong
}
}
int8_t bmi160_bus_burst_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint32_t cnt)
{
// m_tx_buf[0] = reg_addr | READ_MASK;
nrf_drv_spi_xfer_desc_t xfer = NRF_DRV_SPI_XFER_RX(m_rx_buf, 1);
uint32_t flags = NRF_DRV_SPI_FLAG_HOLD_XFER |
NRF_DRV_SPI_FLAG_REPEATED_XFER |
NRF_DRV_SPI_FLAG_RX_POSTINC |
NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER;
nrf_drv_spi_xfer(&spi, &xfer, flags);
burst_transfer_enable();
nrf_spim_task_trigger(spi.p_registers, NRF_SPIM_TASK_START);
while(!burst_completed){
NRF_LOG_INFO("wating for interruption\n");
// __WFE();
}
spi_xfer_done = false;
burst_completed = false;
return NRF_SUCCESS;
}
int8_t spi_init(void)
{
ret_code_t err_code;
nrf_gpio_cfg_output(SPIM0_SS_PIN);
imu_deselect();
err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("ppi initialised\n");
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; //I control the CS pin
spi_config.miso_pin = SPIM0_MISO_PIN;
spi_config.mosi_pin = SPIM0_MOSI_PIN;
spi_config.sck_pin = SPIM0_SCK_PIN;
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));
NRF_LOG_INFO("SPI1 Master initialised.\r\n");
NRF_SPIM0->RXD.PTR = m_rx_buf;
NRF_SPIM0->RXD.MAXCNT = BUFF_LENGTH;
// Reset rx buffer and transfer done flag
memset(m_rx_buf, 0x05, sizeof(ArrayList_type)*BUFF_RX_LENGTH);
spi_xfer_done = false;
// // To read the Device ID (0xD1)
// uint8_t data = 0;
// bmi160_bus_read(0, 0x0, &data, 1);
// NRF_LOG_INFO("DEVICE ID (0xD1): %#01x\r\n", data);
return NRF_SUCCESS;
}
/**
* @brief Function for application main entry.
*/
int main(void)
{
burst_setup();
spi_init();
while (true)
{
bmi160_bus_burst_read(NULL,NULL,NULL,NULL);
}
// bmi160_bus_burst_read(NULL,NULL,NULL,NULL);
}