Hello,
I am trying to send and receive data from an external slave sensor using the NRF5340. For debugging purposes, I have connected the NRF5340 to my PC via UART.
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/gpio.h> // Include GPIO header file
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h> // Include for byte order conversion functions (if necessary)
#include <stdio.h> // printk can be used via stdio.h or zephyr/sys/printk.h
/* Get SPI device from Devicetree */
#define SPI_DEVICE_NODE DT_ALIAS(spi4_basic) // Set to the DT alias of the actual SPI controller being used
static const struct device *spi_dev = DEVICE_DT_GET(SPI_DEVICE_NODE);
// It's just getting it in two steps instead of all at once. Ultimately, it gets spi_dev.
/* Get UART device from Devicetree (uses the same UART as printk) */
static const struct device *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
/* Get Chip Select pin configuration from Devicetree */
static const struct spi_cs_control cs_ctrl = SPI_CS_GPIOS_DT_SPEC_GET(SPI_DEVICE_NODE);
/* RHD2000 SPI Configuration */
// RHD2000 uses SPI Mode 0 (CPOL=0, CPHA=0)
// Data is 16-bit, MSB first
static struct spi_config spi_cfg = {
.frequency = 560000, // SPI frequency
.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(16) | SPI_TRANSFER_MSB, // Default settings: CPOL=0, CPHA=0
.slave = 0,
.cs = cs_ctrl,
};
/* 16-bit SPI Communication Helper Function */
static int rhd_spi_transfer(uint16_t tx_command, uint16_t *rx_data)
{
uint16_t mosi_word = tx_command;
uint16_t miso_word = 0;
struct spi_buf tx_buf = { .buf = &mosi_word, .len = sizeof(mosi_word) };
const struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; // count: Information on how many parts it will be divided into
struct spi_buf rx_buf = { .buf = &miso_word, .len = sizeof(miso_word) };
const struct spi_buf_set rx_bufs = { .buffers = &rx_buf, .count = 1 };
int err;
// spi_dev itself is an address. Others (spi_cfg, etc.) are structs.
printk("Calling spi_transceive()\n");
err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs);
printk("spi_transceive() completed\n");
if (err) {
printk("spi_transceive() failed with error %d\n", err);
return err;
}
if (rx_data) {
*rx_data = miso_word;
}
return 0;
}
/* RHD2132 Initialization Function */
int main(void)
{
uint16_t miso_val;
int err;
printk("Executing initialization function.\n");
k_msleep(1000); // Wait for 1000 milliseconds (1 second)
// According to the RHD2000 datasheet, a dummy SPI transaction may be required for initialization
rhd_spi_transfer(RHD_CMD_DUMMY_READ, &miso_val); // transfer
printk("Dummy1.\n");
return 0;
}
To get to the point, the problem I'm facing is that the spi_transceive() function seems to be stuck in an infinite loop.
The message "Calling spi_transceive()" is printed, but there is no response after that.
I suspect there might be an issue with how the CS pin is being handled, but I'm not sure what the exact problem is.
I have also attached the .conf and .overlay files I am using.
CONFIG_UART_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_PRINTK=y
# Kernel
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SPI=y
CONFIG_GPIO=y
CONFIG_GPIO_NRFX=y
/ {
chosen {
zephyr,console = &uart0;
zephyr,shell-uart = &uart0;
};
aliases {
spi4-basic = &spi4;
};
};
&uart0 {
status = "okay";
current-speed = <1000000>;
};
&pinctrl {
spi4_custom_pins: spi4_custom_pins {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
<NRF_PSEL(SPIM_MOSI, 1, 14)>,
<NRF_PSEL(SPIM_MISO, 1, 13)>;
};
};
spi4_custom_pins_sleep: spi4_custom_pins_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
<NRF_PSEL(SPIM_MOSI, 1, 14)>,
<NRF_PSEL(SPIM_MISO, 1, 13)>;
low-power-enable;
};
};
};
&spi4 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi4_custom_pins>;
pinctrl-1 = <&spi4_custom_pins_sleep>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
};
Thank you.
Best regards, Minseok Kim