From 6354a440b24d9a0b157c8c5571403f09dd04c245 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sun, 2 Mar 2025 21:16:35 -0700 Subject: libhw: Update comments and asserts about clock rate --- libhw/rp2040_include/libhw/rp2040_hwspi.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'libhw/rp2040_include') diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h index 76e0709..a1d85d4 100644 --- a/libhw/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h @@ -48,12 +48,22 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) * the CPU. This is because the PL022 has a maximum of 16-bit frames, * but we need to be able to do *at least* 32-bit frames (and ideally, * much larger). By managing it ourselves, we can just keep CS pulled - * low extra-long, making the frame extra-long. However, this means - * that we can't SPI so fast that the CPU can't do things in time; - * experimentally much faster than 60MHz seems to be when I start - * getting mangled messages. We wouldn't have this speed limit with a - * PIO-based SPI driver, because it could toggle CLK and CS in - * lock-step with receiving data from the FIFO. + * low extra-long, making the frame extra-long. + * + * Restrictions on baudrate: + * + * - The PL022 requires that the baudrate is an even-number fraction + * of clk_peri. + * + This implies that the maximum baudrate is clk_peri/2. + * + Pico-SDK' default clk_peri is 125MHz, max is 200MHz. + * - The CS-from-GPIO hack above means that that we can't go so fast + * that the CPU can't do things in time. + * + Experimentally: + * | clk_sys=125MHz | baud=31.25MHz | works OK | + * | clk_sys=125MHz | baud=62.5 MHz | messages get shifted right a bit | + * + * Both of these restrictions aught to be avoidable by using a + * PIO-based SPI driver instead of this PLL02-based driver. */ #define rp2040_hwspi_init(self, name, \ inst_num, mode, baudrate_hz, \ -- cgit v1.2.3-2-g168b From fb73355711c99003c559df48164a1ce6db93cff9 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Tue, 4 Mar 2025 00:05:35 -0700 Subject: libhw: rp2040_hwspi: Add more config knobs --- libhw/rp2040_include/libhw/rp2040_hwspi.h | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'libhw/rp2040_include') diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h index a1d85d4..fef1dbd 100644 --- a/libhw/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h @@ -20,9 +20,14 @@ enum rp2040_hwspi_instance { struct rp2040_hwspi { BEGIN_PRIVATE(LIBHW_RP2040_HWSPI_H) + /* const */ LM_IF(IS_IMPLEMENTATION_FOR(LIBHW_RP2040_HWSPI_H))(spi_inst_t)(void) *inst; + uint64_t min_delay_ns; + uint8_t bogus_data; + uint pin_cs; - uint pin_cs; + /* mutable */ + uint64_t dead_until_ns; END_PRIVATE(LIBHW_RP2040_HWSPI_H) }; LO_IMPLEMENTATION_H(io_duplex_readwriter, struct rp2040_hwspi, rp2040_hwspi) @@ -31,14 +36,17 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) /** * Initialize an instance of `struct rp2040_hwspi`. * - * @param self : struct rp2040_hwspi : the structure to initialize - * @param name : char * : a name for the SPI port; to include in the bininfo - * @param inst_num : enum rp2040_hwspi_instance : the PL220 instance number; RP2040_HWSPI_{0,1} - * @param mode : enum spi_mode : the SPI mode; SPI_MODE_{0..3} - * @param pin_miso : uint : pin number; 0, 4, 16, or 20 for _HWSPI_0; 8, 12, 24, or 28 for _HWSPI_1 - * @param pin_mosi : uint : pin number; 3, 7, 19, or 23 for _HWSPI_0; 11, 15, or 27 for _HWSPI_1 - * @param pin_clk : uint : pin number; 2, 6, 18, or 22 for _HWSPI_0; 10, 14, or 26 for _HWSPI_1 - * @param pin_cs : uint : pin number; any unused GPIO pin + * @param self : struct rp2040_hwspi : the structure to initialize + * @param name : char * : a name for the SPI port; to include in the bininfo + * @param inst_num : enum rp2040_hwspi_instance : the PL220 instance number; RP2040_HWSPI_{0,1} + * @param mode : enum spi_mode : the SPI mode; SPI_MODE_{0..3} + * @param baudrate_hz : uint : baudrate in Hz + * @param min_delay_ns: uint64_t : minimum time for pin_cs to be high between messages + * @param bogus_data : uint8_t : bogus data to write when .iov_write_src is NULL + * @param pin_miso : uint : pin number; 0, 4, 16, or 20 for _HWSPI_0; 8, 12, 24, or 28 for _HWSPI_1 + * @param pin_mosi : uint : pin number; 3, 7, 19, or 23 for _HWSPI_0; 11, 15, or 27 for _HWSPI_1 + * @param pin_clk : uint : pin number; 2, 6, 18, or 22 for _HWSPI_0; 10, 14, or 26 for _HWSPI_1 + * @param pin_cs : uint : pin number; any unused GPIO pin * * There is no bit-order argument; the RP2040's hardware SPI always * uses MSB-first bit order. @@ -67,6 +75,7 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) */ #define rp2040_hwspi_init(self, name, \ inst_num, mode, baudrate_hz, \ + min_delay_ns, bogus_data, \ pin_miso, pin_mosi, pin_clk, pin_cs) \ do { \ bi_decl(bi_4pins_with_names(pin_miso, name" SPI MISO", \ @@ -75,12 +84,15 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) pin_mosi, name" SPI CS")); \ _rp2040_hwspi_init(self, \ inst_num, mode, baudrate_hz, \ + min_delay_ns, bogus_data, \ pin_miso, pin_mosi, pin_clk, pin_cs); \ } while(0) void _rp2040_hwspi_init(struct rp2040_hwspi *self, enum rp2040_hwspi_instance inst_num, enum spi_mode mode, uint baudrate_hz, + uint64_t min_delay_ns, + uint8_t bogus_data, uint pin_miso, uint pin_mosi, uint pin_clk, -- cgit v1.2.3-2-g168b From c336bf7f2205131c86e6d2991770a2c150d85ca9 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 24 Feb 2025 22:54:30 -0700 Subject: libhw: rp2040_hwspi: Use DMA --- libhw/rp2040_include/libhw/rp2040_hwspi.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'libhw/rp2040_include') diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h index fef1dbd..f90c1af 100644 --- a/libhw/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h @@ -25,6 +25,10 @@ struct rp2040_hwspi { uint64_t min_delay_ns; uint8_t bogus_data; uint pin_cs; + uint dma_tx_data; + uint dma_tx_ctrl; + uint dma_rx_data; + uint dma_rx_ctrl; /* mutable */ uint64_t dead_until_ns; @@ -47,6 +51,7 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) * @param pin_mosi : uint : pin number; 3, 7, 19, or 23 for _HWSPI_0; 11, 15, or 27 for _HWSPI_1 * @param pin_clk : uint : pin number; 2, 6, 18, or 22 for _HWSPI_0; 10, 14, or 26 for _HWSPI_1 * @param pin_cs : uint : pin number; any unused GPIO pin + * @param dma{1-4} : uint : DMA channel; any unused channel * * There is no bit-order argument; the RP2040's hardware SPI always * uses MSB-first bit order. @@ -76,7 +81,8 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) #define rp2040_hwspi_init(self, name, \ inst_num, mode, baudrate_hz, \ min_delay_ns, bogus_data, \ - pin_miso, pin_mosi, pin_clk, pin_cs) \ + pin_miso, pin_mosi, pin_clk, pin_cs, \ + dma1, dma2, dma3, dma4) \ do { \ bi_decl(bi_4pins_with_names(pin_miso, name" SPI MISO", \ pin_mosi, name" SPI MOSI", \ @@ -85,7 +91,8 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) _rp2040_hwspi_init(self, \ inst_num, mode, baudrate_hz, \ min_delay_ns, bogus_data, \ - pin_miso, pin_mosi, pin_clk, pin_cs); \ + pin_miso, pin_mosi, pin_clk, pin_cs, \ + dma1, dma2, dma3, dma4); \ } while(0) void _rp2040_hwspi_init(struct rp2040_hwspi *self, enum rp2040_hwspi_instance inst_num, @@ -96,6 +103,10 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self, uint pin_miso, uint pin_mosi, uint pin_clk, - uint pin_cs); + uint pin_cs, + uint dma1, + uint dma2, + uint dma3, + uint dma4); #endif /* _LIBHW_RP2040_HWSPI_H_ */ -- cgit v1.2.3-2-g168b From 7a1f764cda070de396fcb186e1f7457ff2704ba4 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sun, 2 Mar 2025 23:22:40 -0700 Subject: Bump the CPU clock speed, wring a few more MHz out of the hwspi --- libhw/rp2040_include/libhw/rp2040_hwspi.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libhw/rp2040_include') diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h index f90c1af..a76a2c8 100644 --- a/libhw/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h @@ -73,6 +73,10 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) * that the CPU can't do things in time. * + Experimentally: * | clk_sys=125MHz | baud=31.25MHz | works OK | + * | clk_sys=160MHz | baud=40 MHz | works OK | + * | clk_sys=170MHz | baud=42.5 MHz | works OK | + * | clk_sys=180MHz | baud=45 MHz | mangled in funny ways? | + * | clk_sys=200MHz | baud=50 MHz | messages get shifted right a bit | * | clk_sys=125MHz | baud=62.5 MHz | messages get shifted right a bit | * * Both of these restrictions aught to be avoidable by using a -- cgit v1.2.3-2-g168b From 3f49a57b99e7fe5aafa73e70ed146d98b1ae174c Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 24 Feb 2025 22:54:30 -0700 Subject: libhw: rp2040_hwspi: Use interrupts instead of busy-polling --- libhw/rp2040_include/libhw/rp2040_hwspi.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libhw/rp2040_include') diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h index a76a2c8..eb54cdc 100644 --- a/libhw/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h @@ -9,6 +9,7 @@ #include /* for bi_* */ +#include #include #include @@ -32,6 +33,7 @@ struct rp2040_hwspi { /* mutable */ uint64_t dead_until_ns; + cr_sema_t sema; END_PRIVATE(LIBHW_RP2040_HWSPI_H) }; LO_IMPLEMENTATION_H(io_duplex_readwriter, struct rp2040_hwspi, rp2040_hwspi) -- cgit v1.2.3-2-g168b