- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have not used the DMA yet and now looking at using it for Buffer to SPI and SPI to Buffer data transfer.
For beginning, I thought of using the example code in Creator for 5LP. It appears straight forward but how is the transmission initiated in a real world example?
Can I simply load data into txBuffer, wait till transfer complete and read results each time I want to transfer, like below?
sprintf(txBuffer,"some data"); //put new data in tx Buffer
while (0u == (SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)) { } //.wait till transferred
for(i=0u; i<BUFFER_SIZE; i++)
{
LCD_PrintHexUint8(rxBuffer); //read received data
}
Thanks
- Labels:
-
PSoC 5 Device Programming
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Further to my Post, How do you specify how many bytes to send for any particular transaction?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Attached is my project connecting F-RAM to PSoC 3 with DMA. This project is created by PSoC Creator 3.0 SP1. So, I don't know if a recent PSoC Creator can be used.
You can find the same project on my GitHub repository at "GitHub - noritan/Design116_3p0_3: F-RAM test project using SPI "
It seems that the data length is specified by the CyDmaTdSetConfiguration() API function.
// Initialize DMA RX descriptors
DMA_RX_Chan = DMA_RX_DmaInitialize(
DMA_RX_BYTES_PER_BURST, DMA_RX_REQUEST_PER_BURST,
HI16(DMA_RX_SRC_BASE), HI16(DMA_RX_DST_BASE)
);
DMA_RX_TD[0] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_RX_TD[0],
sizeof misoBuffer,
CY_DMA_DISABLE_TD,
TD_INC_DST_ADR | DMA_RX__TD_TERMOUT_EN
);
CyDmaTdSetAddress(DMA_RX_TD[0],
LO16((uint32)SPIM_RXDATA_PTR), LO16((uint32)misoBuffer.stream)
);
CyDmaChSetInitialTd(DMA_RX_Chan, DMA_RX_TD[0]);
Regards,
Noriaki
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks,
Would something like below work? Where I re-init the dma each call with new numBytes to send/receive. Would I still need the "CyDmaChSetRequest(..." function if I am reinitializing the dma each call?
CY_ISR(DMA_RX_INT_ISR) {
DMA_RX_completed = 1;
}
void spiWrite(uint8 numBytes) {
txBuffer[0] = dat0;
txBuffer[1] = dat1;
txBuffer[2] = dat2;
dmaInit(numBytes);
CyDmaChSetRequest(DMA_TX_Chan, CY_DMA_CPU_REQ); ???
// Wait for transfer completed
while (!DMA_RX_completed) ;
}
void dmaInit(uint8 numBytes) {
// Initialize DMA TX descriptors
DMA_TX_Chan = DMA_TX_DmaInitialize(
DMA_TX_BYTES_PER_BURST, DMA_TX_REQUEST_PER_BURST,
HI16(DMA_TX_SRC_BASE), HI16(DMA_TX_DST_BASE)
);
DMA_TX_TD[0] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_TX_TD[0],
numBytes,
CY_DMA_DISABLE_TD,
TD_INC_SRC_ADR
);
CyDmaTdSetAddress(DMA_TX_TD[0],
LO16((uint32)mosiBuffer.stream), LO16((uint32)SPIM_TXDATA_PTR)
);
CyDmaChSetInitialTd(DMA_TX_Chan, DMA_TX_TD[0]);
// Initialize DMA RX descriptors
DMA_RX_Chan = DMA_RX_DmaInitialize(
DMA_RX_BYTES_PER_BURST, DMA_RX_REQUEST_PER_BURST,
HI16(DMA_RX_SRC_BASE), HI16(DMA_RX_DST_BASE)
);
DMA_RX_TD[0] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_RX_TD[0],
numBytes,
CY_DMA_DISABLE_TD,
TD_INC_DST_ADR | DMA_RX__TD_TERMOUT_EN
);
CyDmaTdSetAddress(DMA_RX_TD[0],
LO16((uint32)SPIM_RXDATA_PTR), LO16((uint32)misoBuffer.stream)
);
CyDmaChSetInitialTd(DMA_RX_Chan, DMA_RX_TD[0]);
}
Main Loop
...
spiWrite(3);
for(int i = 0; i < numBytes ; i++)
{
//do something with rxBuffer
}
...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is required to call CyDmaChSetRequest(DMA_TX_Chan, CY_DMA_CPU_REQ); to start a DMA transfer with or without initialization. By calling this API, the DMA writes a byte to the SPI data register and the SPI starts a transfer sequence.
In addition, don't forget to enable the DMA channel when starting a DMA sequence.
Regards,
Noriaki