#include "bsp/pmod_spi.h" #include "bsp/mmio.h" #include "bsp/soc.h" #define PMOD_SPI_CTRL (BSP_PMOD_SPI_BASE + 0x00u) #define PMOD_SPI_TX (BSP_PMOD_SPI_BASE + 0x04u) #define PMOD_SPI_RX (BSP_PMOD_SPI_BASE + 0x08u) #define PMOD_SPI_READY (BSP_PMOD_SPI_BASE + 0x0cu) #define PMOD_SPI_CTRL_BUSY 0x1u #define PMOD_SPI_CTRL_CSN 0x2u #define PMOD_SPI_CTRL_QUAD 0x4u static uint32_t pmod_spi_ctrl_shadow = PMOD_SPI_CTRL_CSN; static void pmod_spi_wait_ready(void) { while ((bsp_read32(PMOD_SPI_READY) & 1u) == 0u) { } while ((bsp_read32(PMOD_SPI_CTRL) & PMOD_SPI_CTRL_BUSY) != 0u) { } } static void pmod_spi_write_ctrl(uint32_t ctrl) { pmod_spi_wait_ready(); pmod_spi_ctrl_shadow = ctrl & (PMOD_SPI_CTRL_CSN | PMOD_SPI_CTRL_QUAD); bsp_write32(PMOD_SPI_CTRL, pmod_spi_ctrl_shadow); } void bsp_pmod_spi_init(void) { pmod_spi_write_ctrl(PMOD_SPI_CTRL_CSN); } void bsp_pmod_spi_set_mode(bsp_pmod_spi_mode_t mode) { uint32_t ctrl = pmod_spi_ctrl_shadow & ~PMOD_SPI_CTRL_QUAD; if (mode == BSP_PMOD_SPI_MODE_QUAD) { ctrl |= PMOD_SPI_CTRL_QUAD; } pmod_spi_write_ctrl(ctrl); } bsp_pmod_spi_mode_t bsp_pmod_spi_mode(void) { return (pmod_spi_ctrl_shadow & PMOD_SPI_CTRL_QUAD) != 0u ? BSP_PMOD_SPI_MODE_QUAD : BSP_PMOD_SPI_MODE_SINGLE; } void bsp_pmod_spi_set_quad(int enabled) { bsp_pmod_spi_set_mode(enabled ? BSP_PMOD_SPI_MODE_QUAD : BSP_PMOD_SPI_MODE_SINGLE); } void bsp_pmod_spi_select(void) { pmod_spi_write_ctrl(pmod_spi_ctrl_shadow & ~PMOD_SPI_CTRL_CSN); } void bsp_pmod_spi_deselect(void) { pmod_spi_write_ctrl(pmod_spi_ctrl_shadow | PMOD_SPI_CTRL_CSN); } int bsp_pmod_spi_ready(void) { return ((bsp_read32(PMOD_SPI_READY) & 1u) != 0u) && ((bsp_read32(PMOD_SPI_CTRL) & PMOD_SPI_CTRL_BUSY) == 0u); } uint32_t bsp_pmod_spi_ctrl(void) { return bsp_read32(PMOD_SPI_CTRL); } uint32_t bsp_pmod_spi_rx(void) { return bsp_read32(PMOD_SPI_RX); } uint8_t bsp_pmod_spi_xfer8(uint8_t value) { pmod_spi_wait_ready(); bsp_pmod_spi_set_mode(BSP_PMOD_SPI_MODE_SINGLE); bsp_write32(PMOD_SPI_TX, ((uint32_t)value) << 24); pmod_spi_wait_ready(); return (uint8_t)(bsp_read32(PMOD_SPI_RX) & 0xffu); } uint32_t bsp_pmod_spi_xfer32(uint32_t value) { pmod_spi_wait_ready(); bsp_pmod_spi_set_mode(BSP_PMOD_SPI_MODE_QUAD); bsp_write32(PMOD_SPI_TX, value); pmod_spi_wait_ready(); return bsp_read32(PMOD_SPI_RX); } void bsp_pmod_spi_transfer(const uint8_t *tx, uint8_t *rx, size_t len) { for (size_t i = 0; i < len; ++i) { uint8_t out = tx ? tx[i] : 0xffu; uint8_t in = bsp_pmod_spi_xfer8(out); if (rx) { rx[i] = in; } } }