I am writing drivers for external ADC and I need to write my own SPIM driver using hal
of NRF52 SPIM. However, after trying for a day I am not able to see my waveform in my Oscilloscope.
#define SPI_MODULE (NRF_SPIM_Type *)NRF_SPIM0
#define TIMER_MODULE NRF_TIMER2
#define CCD_STOP_COUNTER_MODULE NRF_TIMER4
#define SPI_CS_PIN 10 // 0
#define SPI_SDO_PIN 8 // 1
#define SPI_SCK_PIN 9 // 2
#define SPI_SDI_PIN 7 // 3 => Useless pin
#define CS_PIN_PPI_NDX 0
uint16_t buffer[SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t mGpioteSetTimerCCPPI;
static nrf_ppi_channel_t mSpiEndStartPPI;
static nrf_ppi_channel_t mSpiEndTimerStartPPI;
static nrf_ppi_channel_t mSpiEndGpioteClearPPI;
static nrf_ppi_channel_t mCounterTimerStopPPI;
static nrf_ppi_channel_t mCounterCompSpiStopPPI;
static nrf_ppi_channel_t mSpiEndCountCountPPI;
static ret_code_t ccd_ppi_init(void)
{
ret_code_t err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mGpioteSetTimerCCPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mSpiEndStartPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mSpiEndTimerStartPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mSpiEndGpioteClearPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mCounterTimerStopPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mCounterCompSpiStopPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_alloc(&mSpiEndCountCountPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mSpiEndStartPPI,
nrf_spim_event_address_get(SPI_MODULE, NRF_SPIM_EVENT_END),
nrf_spim_task_address_get(SPI_MODULE, NRF_SPIM_TASK_START));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mSpiEndTimerStartPPI,
nrf_spim_event_address_get(SPI_MODULE, NRF_SPIM_EVENT_END),
(uint32_t)nrf_timer_task_address_get(TIMER_MODULE, NRF_TIMER_TASK_START));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mGpioteSetTimerCCPPI,
(uint32_t)nrf_timer_event_address_get(TIMER_MODULE, NRF_TIMER_EVENT_COMPARE0),
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_SET_0));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mSpiEndGpioteClearPPI,
nrf_spim_event_address_get(SPI_MODULE, NRF_SPIM_EVENT_END),
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_CLR_0));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mCounterTimerStopPPI,
(uint32_t)nrf_timer_event_address_get(CCD_STOP_COUNTER_MODULE, NRF_TIMER_EVENT_COMPARE0),
(uint32_t)nrf_timer_task_address_get(TIMER_MODULE, NRF_TIMER_TASK_STOP));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mCounterCompSpiStopPPI,
(uint32_t)nrf_timer_event_address_get(CCD_STOP_COUNTER_MODULE, NRF_TIMER_EVENT_COMPARE0),
nrf_spim_task_address_get(SPI_MODULE, NRF_SPIM_TASK_STOP));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(mSpiEndCountCountPPI,
nrf_spim_event_address_get(SPI_MODULE, NRF_SPIM_EVENT_END),
(uint32_t)nrf_timer_task_address_get(CCD_STOP_COUNTER_MODULE, NRF_TIMER_TASK_COUNT));
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mSpiEndStartPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mSpiEndTimerStartPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mGpioteSetTimerCCPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mSpiEndGpioteClearPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mCounterTimerStopPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mCounterCompSpiStopPPI);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(mSpiEndCountCountPPI);
APP_ERROR_CHECK(err_code);
return 0;
}
void ccd_init(void)
{
// Configure SPI Master to communicate with External ADC
nrf_spim_disable(SPI_MODULE);
nrf_spim_configure(SPI_MODULE, NRF_SPIM_MODE_3, NRF_SPIM_BIT_ORDER_MSB_FIRST);
nrf_spim_pins_set(SPI_MODULE, SPI_SCK_PIN, NRF_SPIM_PIN_NOT_CONNECTED, SPI_SDO_PIN);
nrf_spim_frequency_set(SPI_MODULE, NRF_SPI_FREQ_8M);
gpio_output_cfg(SPI_SCK_PIN);
gpio_input_cfg(SPI_SDO_PIN);
gpio_output_cfg(SPI_CS_PIN);
// // Configure Timer to generate CS Pulses
// nrf_timer_mode_set(TIMER_MODULE, NRF_TIMER_MODE_TIMER);
// nrf_timer_bit_width_set(TIMER_MODULE, NRF_TIMER_BIT_WIDTH_32);
// nrf_timer_frequency_set(TIMER_MODULE, NRF_TIMER_FREQ_16MHz);
// nrf_timer_event_clear(TIMER_MODULE, NRF_TIMER_EVENT_COMPARE0);
// nrf_timer_task_trigger(TIMER_MODULE, NRF_TIMER_TASK_CLEAR);
// nrf_timer_shorts_enable(TIMER_MODULE, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK);
// nrf_timer_shorts_enable(TIMER_MODULE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
// // Counter to stop CCD
// nrf_timer_mode_set(CCD_STOP_COUNTER_MODULE, NRF_TIMER_MODE_COUNTER);
// nrf_timer_bit_width_set(CCD_STOP_COUNTER_MODULE, NRF_TIMER_BIT_WIDTH_32);
// nrf_timer_shorts_enable(CCD_STOP_COUNTER_MODULE, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK);
// nrf_timer_event_clear(CCD_STOP_COUNTER_MODULE, NRF_TIMER_EVENT_COMPARE0);
// nrf_timer_task_trigger(CCD_STOP_COUNTER_MODULE, NRF_TIMER_TASK_CLEAR);
// // GPIOTE to control CS pin pulse
// nrf_gpiote_task_configure(CS_PIN_PPI_NDX, SPI_CS_PIN, NRF_GPIOTE_POLARITY_LOTOHI, NRF_GPIOTE_INITIAL_VALUE_HIGH);
// nrf_gpiote_task_enable(CS_PIN_PPI_NDX);
// ccd_ppi_init();
}
int ccd_run(int runs)
{
// printf("Hello world\r\n");
uint32_t lowTicks = 29; // 3625 us => 14.5 SPI 8MHz clock periods
// nrf_gpiote_task_set(NRF_GPIOTE_TASKS_SET_0);
// nrf_timer_task_trigger(TIMER_MODULE, NRF_TIMER_TASK_STOP);
nrf_spim_disable(SPI_MODULE);
nrf_spim_rx_buffer_set(SPI_MODULE, (uint8_t *)buffer, 2);
nrf_spim_rx_list_enable(SPI_MODULE);
nrf_spim_tx_list_disable(SPI_MODULE);
nrf_spim_shorts_enable(SPI_MODULE, NRF_SPIM_SHORT_END_START_MASK);
nrf_spim_int_enable(SPI_MODULE, NRF_SPIM_INT_ENDTX_MASK);
nrf_drv_common_irq_enable(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 2);
// nrf_timer_int_enable(CCD_STOP_COUNTER_MODULE, NRF_TIMER_INT_COMPARE0_MASK);
// nrf_drv_common_irq_enable(TIMER4_IRQn, 2);
nrf_spim_enable(SPI_MODULE);
// nrf_timer_event_clear(TIMER_MODULE, NRF_TIMER_EVENT_COMPARE0);
// nrf_timer_task_trigger(TIMER_MODULE, NRF_TIMER_TASK_CLEAR);
// nrf_timer_event_clear(CCD_STOP_COUNTER_MODULE, NRF_TIMER_EVENT_COMPARE0);
// nrf_timer_task_trigger(CCD_STOP_COUNTER_MODULE, NRF_TIMER_TASK_CLEAR);
// nrf_timer_cc_write(TIMER_MODULE, NRF_TIMER_CC_CHANNEL0, lowTicks);
// nrf_timer_cc_write(CCD_STOP_COUNTER_MODULE, NRF_TIMER_CC_CHANNEL0, SAMPLES_IN_BUFFER);
// // Lets start
// nrf_gpiote_task_set(NRF_GPIOTE_TASKS_CLR_0);
nrf_spim_task_trigger(SPI_MODULE, NRF_SPIM_TASK_START);
// nrf_timer_task_trigger(TIMER_MODULE, NRF_TIMER_TASK_START);
return 0;
}
int ccd_stop(void)
{
// TODO: Stop everything
return 0;
}
void ccd_write(int from, int to, int jump)
{
for (; from <= to; from += jump)
uart_putuint16_unlocked(buffer[SAMPLES_IN_BUFFER - from] * 10);
}
void ccd_print(int from, int to, int jump)
{
for (; from <= to; from += jump)
printf("Buffer %d: %d\r\n", from, (unsigned)buffer[from - 1] * 10);
}
#ifdef __cplusplus
extern "C" {
#endif
void TIMER4_IRQHandler(void)
{
printf("Done Timer\r\n");
// while (1);
nrf_timer_event_clear(CCD_STOP_COUNTER_MODULE, NRF_TIMER_EVENT_COMPARE0);
}
void SPI0_TWI0_IRQHandler(void)
{
printf("Done SPI\r\n");
nrf_spim_event_clear(SPI_MODULE, NRF_SPIM_EVENT_ENDTX);
}
I want to use arrayList for SPIM. I have enabled rx SPIM arraylist
.However, I am not able to get any interrupt due to NRF_SPIM_EVENT_ENDRX
event. If I enable ENDTX interrupt, then interrupt gets executed. The code below is just testing code. I know RAM buffer will be overflowed because of short
in SPIM (NRF_SPIM_SHORT_END_START_MASK
) but my goal was to check the waveform. But it looks like I am not getting any waveform. Also, I am not able to understand why I am not getting any interrupt on NRF_SPIM_EVENT_ENDRX
(if I enable it with nrf_spim_int_enable(SPI_MODULE, NRF_SPIM_INT_ENDTX_MASK)
).