| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- #include "spi.h"
- void SPI_Init(SPI_TypeDef *spi, SPI_SclkDivTypeDef div)
- {
- SPI_Reset(spi);
- spi->CTRL = div | SPI_CTRL_LITTLE_ENDIAN;
- }
- void SPI_Send(SPI_TypeDef *spi, int tx_bytes, const uint32_t tx_data)
- {
- // When sending more than 4 bytes, the first 4 bytes are from tx_data and the rest are dummy.
- ASSERT(tx_bytes <= SPI_PHASE_BYTE_CNT_MAX);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, tx_bytes);
- SPI_SetPhaseData(spi, SPI_PHASE_0, tx_data);
- SPI_Start(spi, SPI_CTRL_PHASE_CNT1, SPI_CTRL_DMA_OFF, SPI_INTERRUPT_OFF);
- SPI_WaitForDone(spi);
- }
- void SPI_SendDMAStart(SPI_TypeDef *spi, int tx_bytes, const uint32_t *tx_data, DMAC_ChannelNumTypeDef channel)
- {
- // If tx_bytes is no more than 4, use SPI_Send.
- ASSERT(tx_bytes > 4 && tx_bytes <= SPI_PHASE_BYTE_CNT_MAX);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, 4);
- SPI_SetPhaseData(spi, SPI_PHASE_0, *tx_data);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, tx_bytes - 4);
- DMAC_Config(channel, (uint32_t)(tx_data + 1), (uint32_t)&spi->PHASE_DATA[SPI_PHASE_1],
- DMAC_ADDR_INCR_ON, DMAC_ADDR_INCR_OFF, DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT,
- DMAC_BURST_1, DMAC_BURST_1, 0, DMAC_MEM_TO_PERIPHERAL_PERIPHERAL_CTRL,
- 0, SPI_TX_DMA_REQ(spi));
- SPI_Start(spi, SPI_CTRL_PHASE_CNT2, SPI_CTRL_DMA_ON, SPI_INTERRUPT_OFF);
- }
- void SPI_DMAWait(SPI_TypeDef *spi, DMAC_ChannelNumTypeDef channel)
- {
- SPI_WaitForDone(spi);
- DMAC_HaltChannel(channel);
- }
- void SPI_SendDMA(SPI_TypeDef *spi, int tx_bytes, const uint32_t *tx_data, DMAC_ChannelNumTypeDef channel)
- {
- SPI_SendDMAStart(spi, tx_bytes, tx_data, channel);
- SPI_DMAWait(spi, channel);
- }
- uint32_t SPI_SendAndReceive(SPI_TypeDef *spi, int tx_bytes, const uint32_t tx_data, int rx_bytes)
- {
- // When sending more than 4 bytes, the first 4 bytes are from tx_data and the rest are dummy.
- ASSERT(tx_bytes <= SPI_PHASE_BYTE_CNT_MAX && rx_bytes <= 4); // Can receive up to 4 bytes.
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, tx_bytes);
- SPI_SetPhaseData(spi, SPI_PHASE_0, tx_data);
- if (SPI_RX_PIPELINE) {
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_DUMMY_TX, SPI_PHASE_MODE_QUAD, 1);
- }
- SPI_SetPhaseCtrl(spi, SPI_RX_PIPELINE ? SPI_PHASE_2 : SPI_PHASE_1, SPI_PHASE_ACTION_RX, SPI_PHASE_MODE_SINGLE, rx_bytes);
- SPI_Start(spi, SPI_RX_PIPELINE ? SPI_CTRL_PHASE_CNT3 : SPI_CTRL_PHASE_CNT2, SPI_CTRL_DMA_OFF, SPI_INTERRUPT_OFF);
- SPI_WaitForDone(spi);
- return SPI_GetPhaseData(spi, SPI_RX_PIPELINE ? SPI_PHASE_2 : SPI_PHASE_1);
- }
- void SPI_SendAndReceiveDMAStart(SPI_TypeDef *spi, int tx_bytes, const uint32_t *tx_data,
- int rx_bytes, uint32_t *rx_data, DMAC_ChannelNumTypeDef channel)
- {
- ASSERT(tx_bytes <= (SPI_RX_PIPELINE ? 24 : 28) && rx_bytes <= SPI_PHASE_BYTE_CNT_MAX);
- SPI_PhaseNumberTypeDef phase = SPI_PHASE_0;
- while (tx_bytes > 0) {
- int bytes = tx_bytes > 4 ? 4 : tx_bytes;
- SPI_SetPhaseCtrl(spi, phase, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, bytes);
- SPI_SetPhaseData(spi, phase++, *tx_data++);
- tx_bytes -= bytes;
- }
- if (SPI_RX_PIPELINE) {
- SPI_SetPhaseCtrl(spi, phase++, SPI_PHASE_ACTION_DUMMY_TX, SPI_PHASE_MODE_QUAD, 1);
- }
- SPI_SetPhaseCtrl(spi, phase, SPI_PHASE_ACTION_RX, SPI_PHASE_MODE_SINGLE, rx_bytes);
- DMAC_Config(channel, (uint32_t)&spi->PHASE_DATA[phase], (uint32_t)rx_data,
- DMAC_ADDR_INCR_OFF, DMAC_ADDR_INCR_ON, DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT,
- DMAC_BURST_1, DMAC_BURST_1, 0, DMAC_PERIPHERAL_TO_MEM_PERIPHERAL_CTRL,
- SPI_RX_DMA_REQ(spi), 0);
- SPI_Start(spi, phase << SPI_CTRL_PHASE_CNT_OFFSET, SPI_CTRL_DMA_ON, SPI_INTERRUPT_OFF);
- }
- void SPI_SendAndReceiveDMA(SPI_TypeDef *spi, int tx_bytes, const uint32_t *tx_data,
- int rx_bytes, uint32_t *rx_data, DMAC_ChannelNumTypeDef channel)
- {
- SPI_SendAndReceiveDMAStart(spi, tx_bytes, tx_data, rx_bytes, rx_data, channel);
- SPI_DMAWait(spi, channel);
- }
- void SPI_FLASH_SetCmdPhase(SPI_TypeDef *spi, uint32_t cmd)
- {
- // Command phase is always the first phase and tx 1 byte in single mode
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, 1);
- SPI_SetPhaseData(spi, SPI_PHASE_0, cmd);
- }
- void SPI_FLASH_SetCmdAddrPhase(SPI_TypeDef *spi, uint32_t cmd, uint32_t addr)
- {
- // Command + address make the first phase and tx 4 bytes in single mode
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_SINGLE, 4);
- addr = SPI_FLASH_ADDR(addr);
- SPI_SetPhaseData(spi, SPI_PHASE_0, cmd | (addr << SPI_PHASE_BYTE_CNT_OFFSET));
- }
- // 1 byte of command without any extra address or data
- void SPI_FLASH_SingleCmd(SPI_TypeDef *spi, uint32_t cmd)
- {
- SPI_Send(spi, 1, cmd);
- }
- // 1 byte of command with 3 bytes of address and no data
- void SPI_FLASH_SingleCmdAddr(SPI_TypeDef *spi, uint32_t cmd, uint32_t addr)
- {
- SPI_Send(spi, 4, SPI_FLASH_CMD_ADDR(cmd, addr));
- }
- void SPI_FLASH_WaitForWrite(SPI_TypeDef *spi, SPI_InterruptTypeDef interrupt)
- {
- SPI_FLASH_SetCmdPhase(spi, SPI_FLASH_CMD_RDSR);
- if (SPI_RX_PIPELINE) {
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_DUMMY_TX, SPI_PHASE_MODE_QUAD, 1);
- }
- const int rx_phase = SPI_RX_PIPELINE ? SPI_PHASE_2 : SPI_PHASE_1;
- const int phase_cnt = SPI_RX_PIPELINE ? SPI_CTRL_PHASE_CNT3 : SPI_CTRL_PHASE_CNT2;
- SPI_SetPhaseCtrl(spi, rx_phase, SPI_PHASE_ACTION_POLL, SPI_PHASE_MODE_SINGLE, 0);
- SPI_SetPhaseData(spi, rx_phase, SPI_FLASH_WIP_FLAG << 16);
- SPI_Start(spi, phase_cnt, SPI_CTRL_DMA_OFF, interrupt);
- if (interrupt == SPI_INTERRUPT_OFF) {
- SPI_WaitForDone(spi);
- }
- }
- uint32_t SPI_FLASH_ReadID(SPI_TypeDef *spi)
- {
- return SPI_SendAndReceive(spi, 1, SPI_FLASH_CMD_RDID, 3);
- }
- uint32_t SPI_FLASH_ReadManufacturerID(SPI_TypeDef *spi)
- {
- return SPI_SendAndReceive(spi, 4, SPI_FLASH_CMD_ADDR(SPI_FLASH_CMD_REMS, 0), 2);
- }
- uint32_t SPI_FLASH_GetCapacity(SPI_TypeDef *spi)
- {
- return SPI_SendAndReceive(spi, 5, SPI_FLASH_CMD_ADDR(SPI_FLASH_CMD_SFDP, 0x34), 4);
- }
- void SPI_FLASH_ReadUniqueID(SPI_TypeDef *spi, uint32_t *uid, DMAC_ChannelNumTypeDef channel)
- {
- uint32_t data[2] = {SPI_FLASH_CMD_RDUID, 0};
- SPI_SendAndReceiveDMA(spi, 5, data, 16, uid, channel);
- }
- uint32_t SPI_FLASH_ReleaseDP(SPI_TypeDef *spi)
- {
- return SPI_SendAndReceive(spi, 4, SPI_FLASH_CMD_RDP, 1);
- }
- uint16_t SPI_FLASH_ReadStatus(SPI_TypeDef *spi)
- {
- return SPI_SendAndReceive(spi, 1, SPI_FLASH_CMD_RDSR, 1) | SPI_SendAndReceive(spi, 1, SPI_FLASH_CMD_RDSR2, 1) << 8;
- }
- void SPI_FLASH_WriteStatus(SPI_TypeDef *spi, uint16_t status)
- {
- SPI_FLASH_WriteEnable(spi);
- SPI_Send(spi, 3, SPI_FLASH_CMD_WRSR | status << 8);
- SPI_FLASH_WaitForWrite(spi, SPI_INTERRUPT_OFF);
- }
- void SPI_FLASH_QuadEnable(SPI_TypeDef *spi)
- {
- uint16_t status = SPI_FLASH_ReadStatus(spi);
- if (!(status & SPI_FLASH_QE_FLAG)) {
- SPI_FLASH_WriteStatus(spi, status | SPI_FLASH_QE_FLAG);
- }
- }
- void SPI_FLASH_QuadDisable(SPI_TypeDef *spi)
- {
- uint16_t status = SPI_FLASH_ReadStatus(spi);
- if (status & SPI_FLASH_QE_FLAG) {
- SPI_FLASH_WriteStatus(spi, status & ~SPI_FLASH_QE_FLAG);
- }
- }
- void SPI_FLASH_EraseSector(SPI_TypeDef *spi, uint32_t addr, SPI_InterruptTypeDef interrupt)
- {
- SPI_FLASH_WriteEnable(spi);
- SPI_FLASH_SingleCmdAddr(spi, SPI_FLASH_CMD_SE, addr);
- SPI_FLASH_WaitForWrite(spi, interrupt);
- }
- void SPI_FLASH_EraseBlock(SPI_TypeDef *spi, uint32_t addr, SPI_InterruptTypeDef interrupt)
- {
- SPI_FLASH_WriteEnable(spi);
- SPI_FLASH_SingleCmdAddr(spi, SPI_FLASH_CMD_BE, addr);
- SPI_FLASH_WaitForWrite(spi, interrupt);
- }
- void SPI_FLASH_EraseChip(SPI_TypeDef *spi, SPI_InterruptTypeDef interrupt)
- {
- SPI_FLASH_WriteEnable(spi);
- SPI_FLASH_SingleCmd(spi, SPI_FLASH_CMD_CE);
- SPI_FLASH_WaitForWrite(spi, interrupt);
- }
- // Program a flash page, length must be <=256 and the range [addr, addr + length) cannot go across page boundary.
- void SPI_FLASH_WritePage(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, uint32_t length, SPI_PhaseModeTypeDef mode,
- DMAC_ChannelNumTypeDef channel, SPI_InterruptTypeDef interrupt)
- {
- uint32_t cmd = mode == SPI_PHASE_MODE_SINGLE ? SPI_FLASH_CMD_PP : mode == SPI_PHASE_MODE_DUAL ? SPI_FLASH_CMD_DPP : SPI_FLASH_CMD_QPP;
- SPI_FLASH_WriteEnable(spi);
- SPI_FLASH_SetCmdAddrPhase(spi, cmd, addr);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_TX, mode, length);
- DMAC_Config(channel, (uint32_t)buf, (uint32_t)&spi->PHASE_DATA[SPI_PHASE_1],
- DMAC_ADDR_INCR_ON, DMAC_ADDR_INCR_OFF, DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT,
- DMAC_BURST_1, DMAC_BURST_1, 0, DMAC_MEM_TO_PERIPHERAL_PERIPHERAL_CTRL,
- 0, SPI_TX_DMA_REQ(spi));
- SPI_Start(spi, SPI_CTRL_PHASE_CNT2, SPI_CTRL_DMA_ON, SPI_INTERRUPT_OFF);
- SPI_WaitForDone(spi);
- DMAC_HaltChannel(channel);
- SPI_FLASH_WaitForWrite(spi, interrupt);
- }
- void SPI_FLASH_ReadSector(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, uint32_t length, SPI_PhaseModeTypeDef mode,
- DMAC_ChannelNumTypeDef channel, SPI_InterruptTypeDef interrupt)
- {
- length = (length <= SPI_PHASE_BYTE_CNT_MAX ? length : SPI_PHASE_BYTE_CNT_MAX);
- uint32_t cmd = mode == SPI_PHASE_MODE_SINGLE ? SPI_FLASH_CMD_FREAD : mode == SPI_PHASE_MODE_DUAL ? SPI_FLASH_CMD_2READ : SPI_FLASH_CMD_4READ;
- int dummy_bytes = mode == SPI_PHASE_MODE_QUAD ? 3 : 1;
- SPI_FLASH_SetCmdPhase(spi, cmd);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_TX, mode, 3 + dummy_bytes); // 3 bytes address + dummy
- SPI_SetPhaseData(spi, SPI_PHASE_1, SPI_FLASH_ADDR(addr));
- if (SPI_RX_PIPELINE) {
- SPI_SetPhaseCtrl(spi, SPI_PHASE_2, SPI_PHASE_ACTION_DUMMY_TX, SPI_PHASE_MODE_QUAD, 1);
- }
- int rx_phase = SPI_RX_PIPELINE ? SPI_PHASE_3 : SPI_PHASE_2;
- int phase_cnt = SPI_RX_PIPELINE ? SPI_CTRL_PHASE_CNT4 : SPI_CTRL_PHASE_CNT3;
- SPI_SetPhaseCtrl(spi, rx_phase, SPI_PHASE_ACTION_RX, mode, length);
- DMAC_Config(channel, (uint32_t)&spi->PHASE_DATA[rx_phase], (uint32_t)buf,
- DMAC_ADDR_INCR_OFF, DMAC_ADDR_INCR_ON, DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT,
- DMAC_BURST_1, DMAC_BURST_1, 0, DMAC_PERIPHERAL_TO_MEM_PERIPHERAL_CTRL,
- SPI_RX_DMA_REQ(spi), 0);
- SPI_Start(spi, phase_cnt, SPI_CTRL_DMA_ON, interrupt);
- if (interrupt == SPI_INTERRUPT_OFF) {
- SPI_WaitForDone(spi);
- DMAC_HaltChannel(channel);
- }
- }
- void SPI_FLASH_Erase(SPI_TypeDef *spi, uint32_t addr, int total)
- {
- while (total > 0) {
- uint32_t block_start = addr & SPI_FLASH_BLOCK_MASK;
- uint32_t sector_start = addr & SPI_FLASH_SECTOR_MASK;
- uint32_t erase_size;
- bool use_block_erase = (addr - block_start + total > SPI_FLASH_BLOCK_SIZE - SPI_FLASH_SECTOR_SIZE);
- if (block_start == sector_start && use_block_erase) {
- erase_size = (block_start + SPI_FLASH_BLOCK_SIZE - addr);
- SPI_FLASH_EraseBlock(spi, addr, SPI_INTERRUPT_OFF);
- } else {
- erase_size = (sector_start + SPI_FLASH_SECTOR_SIZE - addr);
- SPI_FLASH_EraseSector(spi, addr, SPI_INTERRUPT_OFF);
- }
- addr += erase_size;
- total -= erase_size;
- }
- }
- void SPI_FLASH_Read(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, int total, SPI_PhaseModeTypeDef mode, DMAC_ChannelNumTypeDef channel)
- {
- while (total > 0) {
- uint32_t length = total > SPI_PHASE_BYTE_CNT_MAX ? SPI_PHASE_BYTE_CNT_MAX : total;
- SPI_FLASH_ReadSector(spi, buf, addr, length, mode, channel, SPI_INTERRUPT_OFF);
- addr += length ;
- total -= length;
- buf += length / 4;
- }
- }
- void SPI_FLASH_Write(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, int total, SPI_PhaseModeTypeDef mode, DMAC_ChannelNumTypeDef channel)
- {
- while (total > 0) {
- uint32_t length = ((addr + SPI_FLASH_PAGE_SIZE) & SPI_FLASH_PAGE_MASK) - addr;
- if ((int)length > total) {
- length = total;
- }
- SPI_FLASH_WritePage(spi, buf, addr, length, mode, channel, SPI_INTERRUPT_OFF);
- addr += length;
- total -= length;
- buf += length / 4;
- }
- }
- // SPI PSRAM functions
- void SPI_PRAM_EnableQPI(SPI_TypeDef *spi)
- {
- SPI_FLASH_SingleCmd(spi, SPI_PSRAM_CMD_QPI_EN);
- }
- void SPI_PRAM_DisableQPI(SPI_TypeDef *spi)
- {
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, SPI_PHASE_MODE_QUAD, 1);
- SPI_SetPhaseData(spi, SPI_PHASE_0, SPI_PSRAM_CMD_QPI_DIS);
- SPI_Start(spi, SPI_CTRL_PHASE_CNT1, SPI_CTRL_DMA_OFF, SPI_INTERRUPT_OFF);
- SPI_WaitForDone(spi);
- }
- void SPI_PSRAM_WritePage(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, uint32_t length, SPI_PhaseModeTypeDef mode,
- DMAC_ChannelNumTypeDef channel, SPI_InterruptTypeDef interrupt, bool qpi_mode)
- {
- uint32_t cmd = mode == SPI_PHASE_MODE_SINGLE ? SPI_PSRAM_CMD_WRITE : SPI_PSRAM_CMD_QWRITE;
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, qpi_mode ? mode : SPI_PHASE_MODE_SINGLE, 1);
- SPI_SetPhaseData(spi, SPI_PHASE_0, cmd);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_TX, mode, 3);
- SPI_SetPhaseData(spi, SPI_PHASE_1, SPI_FLASH_ADDR(addr));
- SPI_SetPhaseCtrl(spi, SPI_PHASE_2, SPI_PHASE_ACTION_TX, mode, length);
- DMAC_Config(channel, (uint32_t)buf, (uint32_t)&spi->PHASE_DATA[SPI_PHASE_2],
- DMAC_ADDR_INCR_ON, DMAC_ADDR_INCR_OFF, DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT,
- DMAC_BURST_1, DMAC_BURST_1, 0, DMAC_MEM_TO_PERIPHERAL_PERIPHERAL_CTRL,
- 0, SPI_TX_DMA_REQ(spi));
- SPI_Start(spi, SPI_CTRL_PHASE_CNT3, SPI_CTRL_DMA_ON, SPI_INTERRUPT_OFF);
- SPI_WaitForDone(spi);
- DMAC_HaltChannel(channel);
- }
- void SPI_PSRAM_ReadPage(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, uint32_t length, SPI_PhaseModeTypeDef mode,
- DMAC_ChannelNumTypeDef channel, SPI_InterruptTypeDef interrupt, bool qpi_mode)
- {
- length = (length <= SPI_PHASE_BYTE_CNT_MAX ? length : SPI_PHASE_BYTE_CNT_MAX);
- uint32_t cmd = mode == SPI_PHASE_MODE_SINGLE ? SPI_PSRAM_CMD_READ : SPI_PSRAM_CMD_QREAD;
- int dummy_bytes = mode == SPI_PHASE_MODE_QUAD ? 3 : 1;
- SPI_SetPhaseCtrl(spi, SPI_PHASE_0, SPI_PHASE_ACTION_TX, qpi_mode ? mode : SPI_PHASE_MODE_SINGLE, 1);
- SPI_SetPhaseData(spi, SPI_PHASE_0, cmd);
- SPI_SetPhaseCtrl(spi, SPI_PHASE_1, SPI_PHASE_ACTION_TX, mode, 3 + dummy_bytes); // 3 bytes address + dummy
- SPI_SetPhaseData(spi, SPI_PHASE_1, SPI_FLASH_ADDR(addr));
- if (SPI_RX_PIPELINE) {
- SPI_SetPhaseCtrl(spi, SPI_PHASE_2, SPI_PHASE_ACTION_DUMMY_TX, SPI_PHASE_MODE_QUAD, 1);
- }
- int rx_phase = SPI_RX_PIPELINE ? SPI_PHASE_3 : SPI_PHASE_2;
- int phase_cnt = SPI_RX_PIPELINE ? SPI_CTRL_PHASE_CNT4 : SPI_CTRL_PHASE_CNT3;
- SPI_SetPhaseCtrl(spi, rx_phase, SPI_PHASE_ACTION_RX, mode, length);
- DMAC_Config(channel, (uint32_t)&spi->PHASE_DATA[rx_phase], (uint32_t)buf,
- DMAC_ADDR_INCR_OFF, DMAC_ADDR_INCR_ON, DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT,
- DMAC_BURST_1, DMAC_BURST_1, 0, DMAC_PERIPHERAL_TO_MEM_PERIPHERAL_CTRL,
- SPI_RX_DMA_REQ(spi), 0);
- SPI_Start(spi, phase_cnt, SPI_CTRL_DMA_ON, interrupt);
- if (interrupt == SPI_INTERRUPT_OFF) {
- SPI_WaitForDone(spi);
- DMAC_HaltChannel(channel);
- }
- }
- void SPI_PSRAM_Write(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, int total, SPI_PhaseModeTypeDef mode,
- DMAC_ChannelNumTypeDef channel, bool qpi_mode)
- {
- while (total > 0) {
- uint32_t length = ((addr + SPI_PSRAM_PAGE_SIZE) & SPI_PSRAM_PAGE_MASK) - addr;
- if ((int)length > total) {
- length = total;
- }
- SPI_PSRAM_WritePage(spi, buf, addr, length, mode, channel, SPI_INTERRUPT_OFF, qpi_mode);
- addr += length;
- total -= length;
- buf += length / 4;
- }
- }
- void SPI_PSRAM_Read(SPI_TypeDef *spi, uint32_t *buf, uint32_t addr, int total, SPI_PhaseModeTypeDef mode,
- DMAC_ChannelNumTypeDef channel, bool qpi_mode)
- {
- while (total > 0) {
- // Don't cross page boundary to achieve higher frequency
- uint32_t length = ((addr + SPI_PSRAM_PAGE_SIZE) & SPI_PSRAM_PAGE_MASK) - addr;
- if ((int)length > total) {
- length = total;
- }
- SPI_PSRAM_ReadPage(spi, buf, addr, length, mode, channel, SPI_INTERRUPT_OFF, qpi_mode);
- addr += length ;
- total -= length;
- buf += length / 4;
- }
- }
|