#include #include #include "encoding.h" #include "platform.h" #include "eos.h" #include "msgq.h" #include "interrupt.h" #include "event.h" #include "net.h" #include "spi.h" #include "spi_def.h" #include "irq_def.h" #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) #define SPI_IOF_MASK (((uint32_t)1 << IOF_SPI1_SCK) | ((uint32_t)1 << IOF_SPI1_MOSI) | ((uint32_t)1 << IOF_SPI1_MISO)) | ((uint32_t)1 << IOF_SPI1_SS0) | ((uint32_t)1 << IOF_SPI1_SS2) | ((uint32_t)1 << IOF_SPI1_SS3) static uint8_t spi_dev; static uint8_t spi_dev_cs_pin; static uint8_t spi_state_flags; static unsigned char spi_in_xchg; uint32_t _eos_spi_state_len = 0; uint32_t _eos_spi_state_idx_tx = 0; uint32_t _eos_spi_state_idx_rx = 0; unsigned char *_eos_spi_state_buf = NULL; static eos_evt_fptr_t evt_handler[EOS_SPI_MAX_DEV]; static void spi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) { unsigned char idx = (type & ~EOS_EVT_MASK) - 1; if (idx < EOS_SPI_MAX_DEV) { evt_handler[idx](type, buffer, len); } else { eos_evtq_bad_handler(type, buffer, len); } } static void spi_flush(void) { SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(1); while (!(SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM)); while (!(SPI1_REG(SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY)); } static void spi_xchg_wait(void) { volatile uint8_t done = 0; while (!done) { clear_csr(mstatus, MSTATUS_MIE); done = !(spi_state_flags & SPI_FLAG_XCHG); if (!done) asm volatile ("wfi"); set_csr(mstatus, MSTATUS_MIE); } spi_in_xchg = 0; } void eos_spi_init(void) { int i; for (i=0; i> 8; } else { while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF00) >> 8; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF); } if (rx) { if (flags & EOS_SPI_FLAG_BSWAP) { while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF); while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 8; } else { while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 8; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF); } } if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear(); return r; } uint32_t eos_spi_xchg24(uint32_t data, uint8_t flags) { volatile uint32_t x = 0; uint8_t rx = !(flags & EOS_SPI_FLAG_TX); uint32_t r = 0; if (spi_in_xchg) spi_xchg_wait(); if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush(); spi_state_flags &= 0xF0; spi_state_flags |= flags; if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set(); if (flags & EOS_SPI_FLAG_BSWAP) { while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF); while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16; } else { while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF); } if (rx) { if (flags & EOS_SPI_FLAG_BSWAP) { while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF); while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 8; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 16; } else { while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 16; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 8; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF); } } if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear(); return r; } uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags) { volatile uint32_t x = 0; uint8_t rx = !(flags & EOS_SPI_FLAG_TX); uint32_t r = 0; if (spi_in_xchg) spi_xchg_wait(); if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush(); spi_state_flags &= 0xF0; spi_state_flags |= flags; if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set(); if (flags & EOS_SPI_FLAG_BSWAP) { while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF); while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24; } else { while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8; while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF); } if (rx) { if (flags & EOS_SPI_FLAG_BSWAP) { while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF); while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 8; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 16; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 24; } else { while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 24; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 16; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF) << 8; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); r |= (x & 0xFF); } } if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear(); return r; }