From 13e727742dc759bb12285291ec9c19d7e083b74c Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Tue, 22 Oct 2024 22:55:40 +0300 Subject: [PATCH 1/2] nuttx/SPI: Add SPI chip select to first clock edge delay Add a new macro, which can be defined to set a minimum delay within the SPI driver to delay the transfer start. Some drivers require minimum delay from the CS assertion to the start of the transfer. If the macro is not defined by the board config or nuttx, use px4_udelay to implement the delay. Signed-off-by: Jukka Laitinen --- src/lib/drivers/device/nuttx/SPI.cpp | 6 ++++++ src/lib/drivers/device/nuttx/SPI.hpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/lib/drivers/device/nuttx/SPI.cpp b/src/lib/drivers/device/nuttx/SPI.cpp index a6a205f19b26..e82a525bdf8a 100644 --- a/src/lib/drivers/device/nuttx/SPI.cpp +++ b/src/lib/drivers/device/nuttx/SPI.cpp @@ -50,6 +50,10 @@ # error This driver requires CONFIG_SPI_EXCHANGE #endif +#ifndef SPI_CS_TO_SCK_DELAY +#define SPI_CS_TO_SCK_DELAY(dev, dly_ns) if (dly_ns) px4_udelay(((dly_ns) + 999) / 1000) +#endif + namespace device { @@ -169,6 +173,7 @@ SPI::_transfer(uint8_t *send, uint8_t *recv, unsigned len) SPI_SETMODE(_dev, _mode); SPI_SETBITS(_dev, 8); SPI_SELECT(_dev, _device, true); + SPI_CS_TO_SCK_DELAY(_dev, _cs_to_sck_ns); /* do the transfer */ SPI_EXCHANGE(_dev, send, recv, len); @@ -221,6 +226,7 @@ SPI::_transferhword(uint16_t *send, uint16_t *recv, unsigned len) SPI_SETMODE(_dev, _mode); SPI_SETBITS(_dev, 16); /* 16 bit transfer */ SPI_SELECT(_dev, _device, true); + SPI_CS_TO_SCK_DELAY(_dev, _cs_to_sck_ns); /* do the transfer */ SPI_EXCHANGE(_dev, send, recv, len); diff --git a/src/lib/drivers/device/nuttx/SPI.hpp b/src/lib/drivers/device/nuttx/SPI.hpp index 32f5f7d6bf4b..dfdde109a461 100644 --- a/src/lib/drivers/device/nuttx/SPI.hpp +++ b/src/lib/drivers/device/nuttx/SPI.hpp @@ -161,10 +161,12 @@ class __EXPORT SPI : public CDev */ void set_lockmode(enum LockMode mode) { _locking_mode = mode; } + void set_cs_to_sck_delay(uint32_t delay_ns) { _cs_to_sck_ns = delay_ns; } private: uint32_t _device; enum spi_mode_e _mode; uint32_t _frequency; + uint32_t _cs_to_sck_ns {0}; struct spi_dev_s *_dev {nullptr}; LockMode _locking_mode{LOCK_THREADS}; /**< selected locking mode */ From 8adb663cd17b9ae4e9f4bfd4cd21c70c9128ff77 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Tue, 22 Oct 2024 23:01:57 +0300 Subject: [PATCH 2/2] imu/ADIS16470: Add minimum delay of 200ns from CS assertion to transfer start This is required by the datasheet, and the delay is too short causing errors on some platforms Signed-off-by: Jukka Laitinen --- src/drivers/imu/analog_devices/adis16470/ADIS16470.cpp | 2 ++ .../adis16470/Analog_Devices_ADIS16470_registers.hpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/drivers/imu/analog_devices/adis16470/ADIS16470.cpp b/src/drivers/imu/analog_devices/adis16470/ADIS16470.cpp index 1e73a9d9f7b5..a345aaf23002 100644 --- a/src/drivers/imu/analog_devices/adis16470/ADIS16470.cpp +++ b/src/drivers/imu/analog_devices/adis16470/ADIS16470.cpp @@ -50,6 +50,8 @@ ADIS16470::ADIS16470(const I2CSPIDriverConfig &config) : if (_drdy_gpio != 0) { _drdy_missed_perf = perf_alloc(PC_COUNT, MODULE_NAME": DRDY missed"); } + + set_cs_to_sck_delay(SPI_CS_TO_SCK_PERIOD_NS); } ADIS16470::~ADIS16470() diff --git a/src/drivers/imu/analog_devices/adis16470/Analog_Devices_ADIS16470_registers.hpp b/src/drivers/imu/analog_devices/adis16470/Analog_Devices_ADIS16470_registers.hpp index 6cab0b1b080e..9f3830832ec3 100644 --- a/src/drivers/imu/analog_devices/adis16470/Analog_Devices_ADIS16470_registers.hpp +++ b/src/drivers/imu/analog_devices/adis16470/Analog_Devices_ADIS16470_registers.hpp @@ -67,6 +67,8 @@ static constexpr uint32_t SPI_SPEED_BURST = 1 * 1000 * 1000; // 1 MHz SPI serial static constexpr uint32_t SPI_STALL_PERIOD = 16; // 16 us Stall period between data +static constexpr uint32_t SPI_CS_TO_SCK_PERIOD_NS = 200; // 200 ns delay from CS to SCK edge + static constexpr uint16_t DIR_WRITE = 0x80; static constexpr uint16_t Product_identification = 0x4056;