I am trying to communicate with a SPI peripheral acting slave to the nRF52 master. I am using v0.9.1 of the SDK, the example is called spi_master, with the uVision project named spi_master_pca10036.uvprojx
One thing I now know, is that the settings indicated at: infocenter.nordicsemi.com/.../hardware_driver_spi_master.html , namely:
#define SPI0_CONFIG_SCK_PIN 2/*4*/
#define SPI0_CONFIG_MOSI_PIN 3/*29*/
#define SPI0_CONFIG_MISO_PIN 4/*28*/
#define SPI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
Are all wrong - in that that they actually don't do anything in this example. Rather, the file pca10036.h contains settings that actually do something. The settings below, in the file pca10036.h need to be changed to match your connection:
#define SPIM0_SCK_PIN 4 /*29*/ // SPI clock GPIO pin number.
#define SPIM0_MOSI_PIN 29 /*25*/ // SPI Master Out Slave In GPIO pin number.
#define SPIM0_MISO_PIN 28 // SPI Master In Slave Out GPIO pin number.
#define SPIM0_SS_PIN 30 /*12*/ // SPI Slave Select GPIO pin number.
So I have verified with an oscilloscope that the clock signal is actually being output, and that pin, 4 in my case, and that the MOSI is sending the correct data on pin 29. It is the MISO that is not working. I thought at first it was that the pin was not configured as an input, so I did so, but the data edges are not correct in that they don't go high enough as seen on the scope trace below (top signal is CLK, bottom is MISO):
I have tried various configurations of the input pin (NOPULL, PULLUP, PULLDOWN), same result.
I have used the example project, but removed the loopback features of it as I want to communicate with a peripheral, not a loopback.
I need help understanding two things:
1) Why does the MISO seem to not work, electrically AND
2) Why does the program persistently create an error condition. It does the first nrf_drv_spi_transfer() call okay, but trying another call creates an error condition that halts to program.
My main function looks like:
int main(void)
{
// Setup bsp module.
bsp_configuration();
unsigned char reg = 0x3F; //IC Identity Register
nrf_gpio_cfg_output(30); //for the CS pin
nrf_gpio_cfg_input(SPIM0_MISO_PIN,NRF_GPIO_PIN_NOPULL);
nrf_drv_gpiote_out_clear(30); //This should assert the CS for the SPI peripheral
spi_master_init( &m_spi_master_0, false);
m_tx_data_spi[0] = reg | AS3911_READ_MODE;
m_tx_data_spi[1] = 0x00;
m_rx_data_spi[0] = 0x00;
m_rx_data_spi[1] = 0x00;
nrf_drv_spi_transfer(&m_spi_master_0,m_tx_data_spi, 2, m_rx_data_spi, 2);
nrf_drv_spi_transfer(&m_spi_master_0,m_tx_data_spi, 2, m_rx_data_spi, 2); //code reaches here
nrf_drv_spi_transfer(&m_spi_master_0,m_tx_data_spi, 2, m_rx_data_spi, 2); //code always creates a fault before getting here
nrf_drv_spi_transfer(&m_spi_master_0,m_tx_data_spi, 2, m_rx_data_spi, 2);
}
With the function implementations being:
void bsp_configuration()
{
uint32_t err_code = NRF_SUCCESS;
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
NRF_CLOCK->TASKS_LFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
{
// Do nothing.
}
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, NULL);
err_code = bsp_init(BSP_INIT_LED, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), NULL);
APP_ERROR_CHECK(err_code);
}
static void spi_master_init(nrf_drv_spi_t const * p_instance, bool lsb)
{
uint32_t err_code = NRF_SUCCESS;
nrf_drv_spi_config_t config =
{
.ss_pin = NRF_DRV_SPI_PIN_NOT_USED,
.irq_priority = APP_IRQ_PRIORITY_LOW,
.orc = 0xCC,
.frequency = NRF_DRV_SPI_FREQ_1M,
.mode = NRF_DRV_SPI_MODE_0,
.bit_order = (lsb ?
NRF_DRV_SPI_BIT_ORDER_LSB_FIRST : NRF_DRV_SPI_BIT_ORDER_MSB_FIRST),
};
#if (SPI0_ENABLED == 1)
if (p_instance == &m_spi_master_0)
{
config.sck_pin = SPIM0_SCK_PIN;
config.mosi_pin = SPIM0_MOSI_PIN;
config.miso_pin = SPIM0_MISO_PIN;
err_code = nrf_drv_spi_init(p_instance, &config,
spi_master_0_event_handler);
}
else
#endif // (SPI0_ENABLED == 1)
#if (SPI1_ENABLED == 1)
if (p_instance == &m_spi_master_1)
{
config.sck_pin = SPIM1_SCK_PIN;
config.mosi_pin = SPIM1_MOSI_PIN;
config.miso_pin = SPIM1_MISO_PIN;
err_code = nrf_drv_spi_init(p_instance, &config,
spi_master_1_event_handler);
}
else
#endif // (SPI1_ENABLED == 1)
#if (SPI2_ENABLED == 1)
if (p_instance == &m_spi_master_2)
{
config.sck_pin = SPIM2_SCK_PIN;
config.mosi_pin = SPIM2_MOSI_PIN;
config.miso_pin = SPIM2_MISO_PIN;
err_code = nrf_drv_spi_init(p_instance, &config,
spi_master_2_event_handler);
}
else
#endif // (SPI2_ENABLED == 1)
{}
APP_ERROR_CHECK(err_code);
}
My nrf_drv_config.h SPI section looks like:
/* SPI */
#define SPI0_ENABLED 1
#if (SPI0_ENABLED == 1)
#define SPI0_USE_EASY_DMA 0
//for DK w/ AS3911 Dev Kit -
/*THESE DO NOTHING IN THIS EXAMPLE EVEN THOUGH NORDIC DOCUMENTATION POINTS YOU HERE, THE ACTUAL SETTINGS ARE IN pca10036.h*/
#define SPI0_CONFIG_SCK_PIN 2/*4*/
#define SPI0_CONFIG_MOSI_PIN 3/*29*/
#define SPI0_CONFIG_MISO_PIN 4/*28*/
#define SPI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
#define SPI0_INSTANCE_INDEX 0
#endif
#define SPI1_ENABLED 0
#if (SPI1_ENABLED == 1)
#define SPI1_USE_EASY_DMA 0
#define SPI1_CONFIG_SCK_PIN 2
#define SPI1_CONFIG_MOSI_PIN 3
#define SPI1_CONFIG_MISO_PIN 4
#define SPI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
#define SPI1_INSTANCE_INDEX (SPI0_ENABLED)
#endif
#define SPI2_ENABLED 0
#if (SPI2_ENABLED == 1)
#define SPI2_USE_EASY_DMA 0
#define SPI2_CONFIG_SCK_PIN 2
#define SPI2_CONFIG_MOSI_PIN 3
#define SPI2_CONFIG_MISO_PIN 4
#define SPI2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
#define SPI2_INSTANCE_INDEX (SPI0_ENABLED + SPI1_ENABLED)
#endif
#define SPI_COUNT (SPI0_ENABLED + SPI1_ENABLED + SPI2_ENABLED)