Merge pull request #2714 from openmv/fix_alif_spi
Some checks are pending
🔥 Firmware Build / build-firmware (ARDUINO_GIGA) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_33_BLE_SENSE) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_RP2040_CONNECT) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NICLA_VISION) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_PORTENTA_H7) (push) Waiting to run
🔥 Firmware Build / build-firmware (DOCKER) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV2) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4P) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMVPT) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_AE3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_RT1060) (push) Waiting to run
🔥 Firmware Build / code-size-report (push) Blocked by required conditions
🔥 Firmware Build / stable-release (push) Blocked by required conditions
🔥 Firmware Build / development-release (push) Blocked by required conditions

ports/alif: Implement spi_transfer with poll and timeout.
This commit is contained in:
Ibrahim Abdelkader 2025-06-16 21:37:25 +03:00 committed by GitHub
commit a95ce57e16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 88 additions and 22 deletions

View File

@ -84,7 +84,11 @@ static void spi_switch_mode(py_display_obj_t *self, int bits, bool dma) {
spi_config.datasize = bits; spi_config.datasize = bits;
spi_config.bus_mode = OMV_SPI_BUS_TX; spi_config.bus_mode = OMV_SPI_BUS_TX;
spi_config.nss_enable = false; spi_config.nss_enable = false;
#if OMV_SPI_NO_DMA
spi_config.dma_flags = 0;
#else
spi_config.dma_flags = dma ? OMV_SPI_DMA_NORMAL : 0; spi_config.dma_flags = dma ? OMV_SPI_DMA_NORMAL : 0;
#endif
omv_spi_init(&self->spi_bus, &spi_config); omv_spi_init(&self->spi_bus, &spi_config);
} }

View File

@ -125,10 +125,14 @@ struct { \
#define OMV_SPI_MAX_8BIT_XFER (32768U - 32U) #define OMV_SPI_MAX_8BIT_XFER (32768U - 32U)
#define OMV_SPI_MAX_16BIT_XFER (32768U - 16U) #define OMV_SPI_MAX_16BIT_XFER (32768U - 16U)
#define OMV_SPI_MAX_TIMEOUT (0xFFFFFFFF) #define OMV_SPI_MAX_TIMEOUT (0xFFFFFFFF)
#define OMV_SPI_NO_DMA (1)
#define OMV_SPI_PORT_BITS \ #define OMV_SPI_PORT_BITS \
struct { \ struct { \
SPI_Type *inst; \ SPI_Type *inst; \
bool is_lp; \ bool is_lp; \
uint32_t spi_mode; \
uint32_t bus_mode; \
uint8_t datasize; \
}; };
#endif // __OMV_PORTCONFIG_H__ #endif // __OMV_PORTCONFIG_H__

View File

@ -34,7 +34,9 @@
#include <string.h> #include <string.h>
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/runtime.h"
#include "spi.h" #include "spi.h"
#include "alif_hal.h" #include "alif_hal.h"
@ -76,31 +78,84 @@ static const omv_spi_descr_t omv_spi_descr_all[] = {
#endif #endif
}; };
int omv_spi_transfer_start(omv_spi_t *spi, omv_spi_transfer_t *xfer) { static int omv_spi_poll_flag(SPI_Type *spi, uint32_t flag, uint32_t timeout) {
mp_uint_t tick_start = mp_hal_ticks_ms();
const omv_spi_descr_t *spi_descr = &omv_spi_descr_all[spi->id]; while (!(spi->SPI_SR & flag)) {
if (mp_hal_ticks_ms() - tick_start >= timeout) {
if (xfer->flags & OMV_SPI_XFER_BLOCKING) { return -1;
spi_transfer_t spi_xfer = { 0 };
spi_xfer.tx_buff = xfer->txbuf;
spi_xfer.tx_total_cnt = xfer->size;
spi_xfer.rx_buff = xfer->rxbuf;
spi_xfer.rx_total_cnt = xfer->size;
spi_xfer.tx_default_val = 0xFF;
spi_xfer.tx_default_enable = true;
spi_xfer.mode = SPI_TMOD_TX_AND_RX;
if (!spi_descr->is_lp) {
spi_transfer_blocking(spi->inst, &spi_xfer);
} else {
lpspi_transfer_blocking(spi->inst, &spi_xfer);
} }
mp_event_handle_nowait();
}
return 0;
}
int omv_spi_transfer_start(omv_spi_t *spi, omv_spi_transfer_t *xfer) {
if (xfer->flags & OMV_SPI_XFER_BLOCKING) {
volatile uint32_t *dr = spi->inst->SPI_DR;
spi_set_tmod(spi->inst, SPI_TMOD_TX_AND_RX);
size_t tx_sent = 0;
size_t rx_received = 0;
// FIFO depth is 16 words
const size_t rx_threshold = (SPI_RX_FIFO_DEPTH - 1);
while (rx_received < xfer->size) {
// Fill TX FIFO as much as possible without causing RX overflow
while (tx_sent < xfer->size &&
(tx_sent - rx_received) < rx_threshold &&
(spi->inst->SPI_SR & SPI_SR_TFNF)) {
// Send data
if (xfer->txbuf == NULL) {
*dr = 0xFFFFFFFFU;
} else if (spi->datasize > 16) {
*dr = ((uint32_t *) xfer->txbuf)[tx_sent];
} else if (spi->datasize > 8) {
*dr = ((uint16_t *) xfer->txbuf)[tx_sent];
} else {
*dr = ((uint8_t *) xfer->txbuf)[tx_sent];
}
tx_sent++;
}
// Receive available data
while (rx_received < tx_sent &&
(spi->inst->SPI_SR & SPI_SR_RFNE)) {
if (xfer->rxbuf == NULL) {
(void) *dr;
} else if (spi->datasize > 16) {
((uint32_t *) xfer->rxbuf)[rx_received] = *dr;
} else if (spi->datasize > 8) {
((uint16_t *) xfer->rxbuf)[rx_received] = *dr;
} else {
((uint8_t *) xfer->rxbuf)[rx_received] = *dr;
}
rx_received++;
}
// If we're not making progress, use blocking wait
if (tx_sent < xfer->size && (tx_sent - rx_received) >= rx_threshold) {
// Wait for RX data to free up space
if (omv_spi_poll_flag(spi->inst, SPI_SR_RFNE, xfer->timeout) == -1) {
return -1;
}
} else if (tx_sent == xfer->size && rx_received < tx_sent) {
// All data sent, wait for remaining RX data
if (omv_spi_poll_flag(spi->inst, SPI_SR_RFNE, xfer->timeout) == -1) {
return -1;
}
} else if (tx_sent < xfer->size) {
// Wait for space in the TX FIFO
if (omv_spi_poll_flag(spi->inst, SPI_SR_TFNF, xfer->timeout) == -1) {
return -1;
}
}
}
return 0; return 0;
} }
return -1; return -1;
} }
@ -116,6 +171,9 @@ int omv_spi_init(omv_spi_t *spi, omv_spi_config_t *config) {
spi->inst = spi_descr->inst; spi->inst = spi_descr->inst;
spi->cs = spi_descr->cs; spi->cs = spi_descr->cs;
spi->is_lp = spi_descr->is_lp; spi->is_lp = spi_descr->is_lp;
spi->spi_mode = config->spi_mode;
spi->bus_mode = config->bus_mode;
spi->datasize = config->datasize;
if (spi->inst == NULL) { if (spi->inst == NULL) {
return -1; return -1;