Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

stm32h7: handle SPI transfers via interrupts

Change-Id: I6e60f4222f4d99019e72377de7c3b689a77ac548

authored by

Aidan MacDonald and committed by
Solomon Peachy
37b90baa 7eed19db

+71 -43
+7
firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c
··· 21 21 #include "system.h" 22 22 #include "kernel.h" 23 23 #include "lcd.h" 24 + #include "nvic-arm.h" 24 25 #include "spi-stm32h7.h" 25 26 #include "gpio-stm32h7.h" 26 27 #include "regs/stm32h743/rcc.h" ··· 58 59 59 60 /* Configure SPI bus */ 60 61 stm_spi_init(&spi, &spi_cfg); 62 + nvic_enable_irq(NVIC_IRQN_SPI5); 61 63 62 64 /* Ensure controller is reset */ 63 65 gpio_set_level(GPIO_LCD_RESET, 0); ··· 133 135 stm_spi_transmit(&spi, &row[x * 2], width * sizeof(*row) * 2); 134 136 } 135 137 } 138 + 139 + void spi5_irq_handler(void) 140 + { 141 + stm_spi_irq_handler(&spi); 142 + }
+54 -43
firmware/target/arm/stm32/spi-stm32h7.c
··· 19 19 * 20 20 ****************************************************************************/ 21 21 #include "spi-stm32h7.h" 22 + #include "panic.h" 23 + #include "kernel.h" 22 24 #include "regs/stm32h743/spi.h" 23 - #include "panic.h" 24 25 25 26 /* 26 27 * Align the max transfer size to ensure it will always be a multiple ··· 30 31 #define TSIZE_MAX \ 31 32 ALIGN_DOWN(BM_SPI_CR2_TSIZE >> BP_SPI_CR2_TSIZE, sizeof(uint32_t)) 32 33 33 - static void stm_spi_set_cs(struct stm_spi *spi, bool enable) 34 - { 35 - if (spi->set_cs) 36 - spi->set_cs(spi, enable); 37 - 38 - reg_writelf(spi->regs, SPI_CR1, SSI(1)); 39 - } 40 - 41 34 static void stm_spi_enable(struct stm_spi *spi, bool hd_tx, size_t size) 42 35 { 43 36 size_t tsize = size / spi->frame_size; 44 37 if (tsize > TSIZE_MAX) 45 38 panicf("%s: tsize > TSIZE_MAX", __func__); 46 39 40 + if (spi->set_cs) 41 + spi->set_cs(spi, true); 42 + 47 43 /* TSIZE must be programmed before setting SPE. */ 48 44 reg_assignlf(spi->regs, SPI_CR2, TSIZE(tsize), TSER(0)); 49 - reg_writelf(spi->regs, SPI_CR1, HDDIR(hd_tx), SPE(1)); 45 + reg_writelf(spi->regs, SPI_CR1, HDDIR(hd_tx), SSI(1), SPE(1)); 46 + reg_assignlf(spi->regs, SPI_IER, RXPIE(1), TXPIE(1), EOTIE(1)); 47 + 48 + /* Set CSTART to kick off the transfer */ 49 + reg_writelf(spi->regs, SPI_CR1, CSTART(1)); 50 50 } 51 51 52 52 static void stm_spi_disable(struct stm_spi *spi) 53 53 { 54 54 reg_assignlf(spi->regs, SPI_IFCR, TSERFC(1), TXTFC(1), EOTC(1)); 55 55 reg_writelf(spi->regs, SPI_CR1, SPE(0)); 56 - } 57 56 58 - static void stm_spi_start(struct stm_spi *spi) 59 - { 60 - reg_writelf(spi->regs, SPI_CR1, CSTART(1)); 57 + if (spi->set_cs) 58 + spi->set_cs(spi, false); 61 59 } 62 60 63 61 static uint32_t stm_spi_pack(const void **bufp, size_t *sizep) ··· 114 112 spi->regs = config->instance; 115 113 spi->mode = config->mode; 116 114 spi->set_cs = config->set_cs; 115 + 116 + semaphore_init(&spi->sem, 1, 0); 117 117 118 118 /* Set FIFO level based on 32-bit packed writes */ 119 119 if (config->frame_bits > 16) ··· 176 176 const void *tx_buf, void *rx_buf) 177 177 { 178 178 bool hd_tx = false; 179 - size_t size_tx = tx_buf ? size : 0; 180 - size_t size_rx = rx_buf ? size : 0; 181 179 182 180 /* Ignore zero-length transfers. */ 183 181 if (size == 0) ··· 199 197 hd_tx = true; 200 198 } 201 199 202 - stm_spi_set_cs(spi, true); 203 - stm_spi_enable(spi, hd_tx, size); 204 - stm_spi_start(spi); 200 + spi->tx_buf = tx_buf; 201 + spi->tx_size = tx_buf ? size : 0; 205 202 206 - while (size_tx > 0 || size_rx > 0) 207 - { 208 - uint32_t sr = reg_readl(spi->regs, SPI_SR); 203 + spi->rx_buf = rx_buf; 204 + spi->rx_size = rx_buf ? size : 0; 209 205 210 - /* Handle FIFO write */ 211 - if (size_tx > 0 && reg_vreadf(sr, SPI_SR, TXP)) 212 - { 213 - uint32_t data = stm_spi_pack(&tx_buf, &size_tx); 206 + stm_spi_enable(spi, hd_tx, size); 214 207 215 - reg_varl(spi->regs, SPI_DR) = data; 216 - } 217 - 218 - /* 219 - * Handle FIFO read. Since RXP is set only if the FIFO level 220 - * exceeds the threshold we can't rely on it at the end of a 221 - * transfer, and must check EOT as well. 222 - */ 223 - if (size_rx > 0 && 224 - (reg_vreadf(sr, SPI_SR, RXP) || reg_vreadf(sr, SPI_SR, EOT))) 225 - { 226 - uint32_t data = reg_readl(spi->regs, SPI_DR); 227 - 228 - stm_spi_unpack(&rx_buf, &size_rx, data); 229 - } 230 - } 208 + semaphore_wait(&spi->sem, TIMEOUT_BLOCK); 231 209 232 210 /* 233 211 * Errata 2.22.2: Master data transfer stall at system clock much faster than SCK ··· 242 220 udelay(5); 243 221 244 222 stm_spi_disable(spi); 245 - stm_spi_set_cs(spi, false); 246 223 return 0; 247 224 } 225 + 226 + void stm_spi_irq_handler(struct stm_spi *spi) 227 + { 228 + while (true) 229 + { 230 + uint32_t sr = reg_readl(spi->regs, SPI_SR); 231 + 232 + if (spi->tx_size == 0 && spi->rx_size == 0) 233 + { 234 + semaphore_release(&spi->sem); 235 + reg_varl(spi->regs, SPI_IER) = 0; 236 + return; 237 + } 238 + 239 + if (spi->tx_size > 0 && reg_vreadf(sr, SPI_SR, TXP)) 240 + { 241 + uint32_t data = stm_spi_pack(&spi->tx_buf, &spi->tx_size); 242 + 243 + reg_varl(spi->regs, SPI_DR) = data; 244 + continue; 245 + } 246 + 247 + if (spi->rx_size > 0 && 248 + (reg_vreadf(sr, SPI_SR, RXP) || reg_vreadf(sr, SPI_SR, EOT))) 249 + { 250 + uint32_t data = reg_readl(spi->regs, SPI_DR); 251 + 252 + stm_spi_unpack(&spi->rx_buf, &spi->rx_size, data); 253 + continue; 254 + } 255 + 256 + break; 257 + } 258 + }
+10
firmware/target/arm/stm32/spi-stm32h7.h
··· 22 22 #define __SPI_STM32H743_H__ 23 23 24 24 #include "system.h" 25 + #include "semaphore.h" 25 26 #include <stddef.h> 26 27 27 28 struct stm_spi; ··· 67 68 enum stm_spi_mode mode; 68 69 stm_spi_set_cs_t set_cs; 69 70 uint32_t frame_size; 71 + 72 + const void *tx_buf; 73 + size_t tx_size; 74 + 75 + void *rx_buf; 76 + size_t rx_size; 77 + 78 + struct semaphore sem; 70 79 }; 71 80 72 81 void stm_spi_init(struct stm_spi *spi, ··· 74 83 75 84 int stm_spi_xfer(struct stm_spi *spi, size_t size, 76 85 const void *tx_buf, void *rx_buf); 86 + void stm_spi_irq_handler(struct stm_spi *spi); 77 87 78 88 static inline int stm_spi_transmit(struct stm_spi *spi, 79 89 const void *buf, size_t size)