Hi,
I am attempting to get CPPI DMA transfers to work with USB0 in peripheral mode. The USB interface configuration and initialization seems correct: CPU-based transfers (CPU reads/writes the endpoint Fifos) work without problems.
I tried to work through the documentation, but lots of questions remain. Especially the demo code on page 81+ in sprufm9f uses undefined constants and memory regions. Even invalid register definitions are used in this code - at least not compatible with the current CSLR - has this code ever been actually tested? Is any other example code available?
Our example is quite simplistic: a single message should be transmitted via EP1-IN in transparent DMA mode. I therefore configured the CPPI registers, configured the endpoint for DMA, and set-up a single HPD descriptor. But no output is produced when this descriptor is enqueued. Also the descriptor is not returned in the completion queue. BTW: The same message written to the EP1 fifo by the CPU is transmitted correctly.
Many thanks for your assistance!
Best Regards,
Adolf Klemenz
#define CPPI_NUM_DESC 32 /**< number of available descriptors for CPPI */
typedef struct CPPIDesc
{
uint32_t HPDword0;
uint32_t HPDword1;
uint32_t HPDword2;
size_t HPDword3buffLength;
void * HPDword4buffAdd;
struct CPPIDesc * HPDword5nextHBDptr;
size_t HPDword6orgBuffLength;
void * HPDword7orgBuffAdd;
} T_CPPIDesc;
#pragma DATA_ALIGN (cppi_desc, 32);
T_CPPIDesc cppi_desc[CPPI_NUM_DESC]; /**< HPD/HBD descriptors */
uint32_t cppi_linkram[CPPI_NUM_DESC] = {0}; /**< reserve memory for linking ram */
/***************************************************************//**
configure transparent DMA transfers
*******************************************************************/
usb_otgRegs->CTRLR &= ~0x00000010; // Global RNDIS disable
usb_otgRegs->MODE = 0; // all endpoints in transparent DMA mode
/***************************************************************//**
configure Queue Manager and Linking RAM
*******************************************************************/
usb_otgRegs->QMEMREGION[0].QMEMRBASE = (uint32_t)cppi_desc;
usb_otgRegs->QMEMREGION[0].QMEMRCTRL = 0; /**< 32 descriptors, size = 32 bytes, index = 0 */
usb_otgRegs->QMGR.LRAM0BASE = (uint32_t)cppi_linkram;
usb_otgRegs->QMGR.LRAM0SIZE = CPPI_NUM_DESC;
/***************************************************************//**
enable DMA for transmit endpoint 1, use queue 24 for completion
*******************************************************************/
usb_otgRegs->DMA_CTRL[0].TXGCR=(0x80000000 | 24);
/***************************************************************//**
configure the CPPI scheduler: only one Tx EP is used (EP1-IN)
enable scheduler
*******************************************************************/
usb_otgRegs->DMA_SCHED.ENTRY[0] = 0x01; // endpoint 1 transmit: 1 credit
usb_otgRegs->DMA_SCHED.DMA_SCHED_CTRL = 0x80000000;
/***************************************************************//**
setup HPD for a single transfer
@note: strlen(usb_msg) <= max_packet_size
*******************************************************************/
cppi_desc[0].HPDword0 = 0x80000000 | strlen(usbtx_msg);
cppi_desc[0].HPDword1 = 0x08000000; // source = EP1
cppi_desc[0].HPDword2 = 0x14004000 | 24; // 24 = completion queue
cppi_desc[0].HPDword3buffLength =
cppi_desc[0].HPDword6orgBuffLength = strlen(usbtx_msg);
cppi_desc[0].HPDword4buffAdd =
cppi_desc[0].HPDword7orgBuffAdd = usbtx_msg;
cppi_desc[0].HPDword5nextHBDptr = NULL;
/***************************************************************//**
configure endpoint for DMA and enqueue HPD
*******************************************************************/
usb_otgRegs->INDEX = 1;
usb_otgRegs->TXCSR.PERI_TXCSR &= 0x7FFF;
usb_otgRegs->TXCSR.PERI_TXCSR |= 0x1400;
usb_otgRegs->QCTRL[16].CTRLD=(uint32_t)&cppi_desc[0] | 2;