Hello,
I have a question regarding 1. debugging SPI and 2. implementing SPI + PPI + FORK. It would be really appreciated if anyone could help me with this.
Debugging SPI
In order to connect SPI and PPI, I need to use nrfx library. I have a working example that is using zephyr library. There is a sample from devZone that is using nrfx library. I made an adjustment (SCK, MISO, MOSI, CS pins) but seems like it's not working.
-- In zephyr +overlay version, I could set those pins to "gpio1" and pin 4,5,6,7 in overlay. But in nrfx version, I could only set pin numbers to 4,5,6,7. Is there any way I could set it to gpio1 specifically?
-- Since I would like to do "read" operation, I am checking "m_rx_buf" in nrfx version. But the buffer is always filled with 0. With zephyr version, I can read the number I expect.
Please let me know if there is anything I am missing.
Below are overlay file, zephyr and nrfx code.
1. nRF Connect SDK and toolchain version: v.2.3.0
2. Build configuration:
- Board: nrf5340dk_nrf5340_cpuapp
- Overlay:
&spi4 { status = "okay"; cs-gpios = <&gpio1 0x7 GPIO_ACTIVE_LOW>; pinctrl-0 = <&spi4_default>; pinctrl-1 = <&spi4_sleep>; pinctrl-names = "default", "sleep"; ads8866: [email protected] { compatible = "vnd,spi-device"; reg = <0>; spi-max-frequency = <16000000>; label = "ads8866_convst"; }; }; &pinctrl { spi4_default: spi4_default { group1 { psels = <NRF_PSEL(SPIM_SCK, 1, 5)>, <NRF_PSEL(SPIM_MISO, 1, 6)>, <NRF_PSEL(SPIM_MOSI, 1, 4)>; }; }; spi4_sleep: spi4_sleep { group1 { psels = <NRF_PSEL(SPIM_SCK, 1, 5)>, <NRF_PSEL(SPIM_MISO, 1, 6)>, <NRF_PSEL(SPIM_MOSI, 1, 4)>; low-power-enable; }; }; };
3. Code
// Working version using zephyr library
#define SPI_OP SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_FULL_DUPLEX | SPI_FRAME_FORMAT_MOTOROLA
const struct spi_dt_spec ads8866_dev = SPI_DT_SPEC_GET(DT_NODELABEL(ads8866), SPI_OP, 0);
static const struct gpio_dt_spec ads8866_cs = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(ads8866));
void ADS8866_get_data(char* filename)
{
int ret;
gpio_pin_set_dt(&ads8866_cs, 1);
gpio_pin_set_dt(&ads8866_cs, 0);
uint8_t ads_buffer[2] = {0};
struct spi_buf ads_spi_buffer[1];
ads_spi_buffer[0].buf = ads_buffer;
ads_spi_buffer[0].len = 2;
const struct spi_buf_set rx_buff = { ads_spi_buffer, 1 };
if (spi_is_ready_dt(&ads8866_dev))
{
printk("ADS8866 device ready\n");
}
ret = spi_read_dt(&ads8866_dev, &rx_buff);
if (ret == 0)
{
uint16_t ads_data = ads_buffer[0] << 8 | ads_buffer[1];
// printk("spi_read status: %d\n", ads_data);
}
}
//main on SPI master
#include <zephyr/kernel.h>
#include "nrf.h"
#include <nrfx_spim.h>
#include <nrfx_gpiote.h>
#include <drivers/nrfx_errors.h>
#include <zephyr/sys/printk.h>
#include <string.h>
#define SPI_INSTANCE 1
static const nrfx_spim_t spim = NRFX_SPIM_INSTANCE(SPI_INSTANCE);
#define APP_SPIM_CS_PIN (0x07)
#define APP_SPIM_SCK_PIN (0x05)
#define APP_SPIM_MISO_PIN (0x06)
#define APP_SPIM_MOSI_PIN (0x04)
#define NRFX_CUSTOM_ERROR_CODES 0 //used in nrfx_errors.h
static nrfx_spim_config_t spim_config =
NRFX_SPIM_DEFAULT_CONFIG(APP_SPIM_SCK_PIN, APP_SPIM_MOSI_PIN, APP_SPIM_MISO_PIN, APP_SPIM_CS_PIN);
#define TEST_STRING "1234567890"
static uint8_t m_tx_buf[] = TEST_STRING;
static uint8_t m_rx_buf[sizeof(TEST_STRING) + 1];
static const uint8_t m_length = sizeof(m_tx_buf);
static volatile bool
spim_xfer_done; /**< Flag used to indicate that SPIM instance completed the transfer. */
static void manual_isr_setup()
{
#ifdef NRF9160_XXAA
IRQ_DIRECT_CONNECT(UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQn, 0,
nrfx_spim_1_irq_handler, 0);
irq_enable(UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQn);
#else
// IRQ_CONNECT( DT_IRQN( DT_NODELABEL( spi1 ) ), DT_IRQ( DT_NODELABEL( spi1 ), priority ), nrfx_isr, nrfx_spim_1_irq_handler, 0 );
// irq_enable(DT_IRQN( DT_NODELABEL( spi1 ) ));
IRQ_DIRECT_CONNECT(SPIM1_SPIS1_TWIM1_TWIS1_UARTE1_IRQn, 0,
nrfx_spim_1_irq_handler, 0);
irq_enable(SPIM1_SPIS1_TWIM1_TWIS1_UARTE1_IRQn);
#endif
}
void spim_event_handler(nrfx_spim_evt_t const *p_event, void *p_context)
{
printk("IRQ: %d\n", p_event->type);
if (p_event->type == NRFX_SPIM_EVENT_DONE) {
spim_xfer_done = true;
printk("Transfer completed\n");
}
if (m_rx_buf[0] != 0)
{
printk("Received: ");
for(int i = 0; i < sizeof(m_rx_buf); i++) {
printk("%x ", m_rx_buf[i]);
}
printk("\n");
}
}
void main(void)
{
printk("SPIM example\n");
nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(NULL, m_length, m_rx_buf, m_length);
if (NRFX_SUCCESS !=
nrfx_spim_init(&spim, &spim_config, spim_event_handler, NULL)) {
printk("Init Failed\n");
return;
}
manual_isr_setup();
while(1) {
memset(m_rx_buf, 0, m_length);
spim_xfer_done = false;
nrfx_err_t err_code = nrfx_spim_xfer(&spim, &xfer_desc, 0);
if (err_code == NRFX_ERROR_BUSY) {
printk("SPI busy\n");
}
else if (err_code != NRFX_SUCCESS){
printk("Error code = %d\n", err_code);
}
while (!spim_xfer_done) {
__WFE();
}
m_tx_buf[0]++;
if (m_tx_buf[0] > '9') {
m_tx_buf[0] = '0';
}
k_sleep(K_MSEC(1000));
}
}
Implementing SPI + PPI + FORK
I found in order to connect SPI and PPI, I need to set NRFX_SPIM_FLAG_HOLD_XFER flag for SPI and configure CS to NRFX_SPIM_PIN_NOT_USED and manage it outside the driver. This suggests using fork. Is there any example code I can follow for this?
Thank you,