This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software: Code Composer Studio
Hi all,
because I´m emulating an I2S-interface described in document spma042b.pdf I want two use two SSI-modules (SSI0 and SSI3) with µDMA in Ping-Pong-Mode. SSI0 ist the left and SSI3 ist the right channel. But SSI0 only is transferring data and SSI3 don´t get into the interrupt. Have you some tipps for me?
// Buffer definitions outside main.c #pragma DATA_SECTION(inbuffera1, ".data") static uint16_t inbuffera1[BUFF_SIZE]; #pragma DATA_SECTION(inbuffera2, ".data") static uint16_t inbuffera2[BUFF_SIZE]; #pragma DATA_SECTION(outbuffera1, ".data") static uint16_t outbuffera1[BUFF_SIZE]; #pragma DATA_SECTION(outbuffera2, ".data") static uint16_t outbuffera2[BUFF_SIZE]; #pragma DATA_SECTION(inbufferb1, ".data") static uint16_t inbufferb1[BUFF_SIZE]; #pragma DATA_SECTION(inbufferb2, ".data") static uint16_t inbufferb2[BUFF_SIZE]; #pragma DATA_SECTION(outbufferb1, ".data") static uint16_t outbufferb1[BUFF_SIZE]; #pragma DATA_SECTION(outbufferb2, ".data") static uint16_t outbufferb2[BUFF_SIZE]; // uDMA control table aligned to 1024-byte boundary outside main.c #pragma DATA_ALIGN(ucControlTable, 1024) uint16_t ucControlTable[1024]; // Functions called inside main.c void hwi_SSI0_ISR(void) { uint32_t ui32Status; uint32_t ui32Mode; ui32Status = SSIIntStatus(SSI0_BASE, 1); SSIIntClear(SSI0_BASE, ui32Status); ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { //wssus(inbuffera1, outbuffera1); g_ui32SSIRxPingCount++; uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,(void *)(SSI0_BASE + SSI_O_DR), inbuffera1, sizeof(inbuffera1)); } ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT); if(ui32Mode == UDMA_MODE_STOP) { //wssus(inbuffera2, outbuffera2); g_ui32SSIRxPongCount++; uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), inbuffera2, sizeof(inbuffera2)); } ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { g_ui32SSITxPingCount++; uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, outbuffera1, (void *)(SSI0_BASE + SSI_O_DR), sizeof(outbuffera1)); } ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0TX | UDMA_ALT_SELECT); if(ui32Mode == UDMA_MODE_STOP) { g_ui32SSITxPongCount++; uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, outbuffera2, (void *)(SSI0_BASE + SSI_O_DR), sizeof(outbuffera2)); } } void hwi_SSI3_ISR(void) { uint32_t ui32Status; uint32_t ui32Mode; ui32Status = SSIIntStatus(SSI3_BASE, 1); SSIIntClear(SSI3_BASE, ui32Status); ui32Mode = uDMAChannelModeGet(UDMA_CH14_SSI3RX | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { //wssus(inbufferb1, outbufferb1); g_ui32SSIRxPingCount++; uDMAChannelTransferSet(UDMA_CH14_SSI3RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,(void *)(SSI3_BASE + SSI_O_DR), inbufferb1, sizeof(inbufferb1)); } ui32Mode = uDMAChannelModeGet(UDMA_CH14_SSI3RX | UDMA_ALT_SELECT); if(ui32Mode == UDMA_MODE_STOP) { //wssus(inbufferb2, outbufferb2); g_ui32SSIRxPongCount++; uDMAChannelTransferSet(UDMA_CH14_SSI3RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI3_BASE + SSI_O_DR), inbufferb2, sizeof(inbufferb2)); } ui32Mode = uDMAChannelModeGet(UDMA_CH15_SSI3TX | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { g_ui32SSITxPingCount++; uDMAChannelTransferSet(UDMA_CH15_SSI3TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, outbufferb1, (void *)(SSI3_BASE + SSI_O_DR), sizeof(outbufferb1)); } ui32Mode = uDMAChannelModeGet(UDMA_CH15_SSI3TX | UDMA_ALT_SELECT); if(ui32Mode == UDMA_MODE_STOP) { g_ui32SSITxPongCount++; uDMAChannelTransferSet(UDMA_CH15_SSI3TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, outbufferb2, (void *)(SSI3_BASE + SSI_O_DR), sizeof(outbufferb2)); } } // Initialize SSI uDMA transfer void Init_SSI0_uDMA_Transfer(void) { // Enable uDMA SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)); // wait until uDMA is ready IntEnable(INT_UDMAERR); uDMAEnable(); uDMAControlBaseSet(ucControlTable); SSIDMAEnable(SSI0_BASE, SSI_DMA_RX | SSI_DMA_TX); // Enable TX and RX channels. //HWREG(SSI0_BASE + SSI_O_CR1) |= SSI_CR1_LBM; // Loopback-mode (data sent to TX (output) to RX (input) ) uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | (UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)); // assure starting point for RX-channel //**************************************************************************** //uDMA SSI0 RX Ping //**************************************************************************** uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_16); // transfer element size RX Ping uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), inbuffera1, sizeof(inbuffera1)); // source and destination for RX Ping //**************************************************************************** //uDMA SSI0 RX Pong //**************************************************************************** uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_16); // transfer element size RX Pong uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), inbuffera2, sizeof(inbuffera2)); // source and destination for RX Pong uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); // put attributes in known state uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_USEBURST); // use burst mode (transfer, when 4 or more items are in RX FIFO) //**************************************************************************** //uDMA SSI0 TX Ping //**************************************************************************** uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_16); // transfer element size uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, outbuffera1, (void *)(SSI0_BASE + SSI_O_DR), sizeof(outbuffera1)); //**************************************************************************** //uDMA SSI0 TX Pong //**************************************************************************** uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_16); uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, outbuffera2, (void *)(SSI0_BASE + SSI_O_DR), sizeof(outbuffera2)); uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); SSIIntEnable(SSI0_BASE, SSI_DMATX | SSI_DMARX); // Enable the SSI0 DMA TX/RX interrupts. IntEnable(INT_SSI0); // Enable the SSI0 peripheral interrupts. } void Init_SSI3_uDMA_Transfer(void) { //uDMAChannelSelectSecondary(); SSIDMAEnable(SSI3_BASE, SSI_DMA_RX | SSI_DMA_TX); // Enable TX and RX channels. uDMAChannelAttributeDisable(UDMA_CH14_SSI3RX, UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | (UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)); // assure starting point for RX-channel //**************************************************************************** //uDMA SSI3 RX Ping //**************************************************************************** uDMAChannelControlSet(UDMA_CH14_SSI3RX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_16); // transfer element size RX Ping uDMAChannelTransferSet(UDMA_CH14_SSI3RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI3_BASE + SSI_O_DR), inbufferb1, sizeof(inbufferb1)); // source and destination for RX Ping //**************************************************************************** //uDMA SSI3 RX Pong //**************************************************************************** uDMAChannelControlSet(UDMA_CH14_SSI3RX | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_16); // transfer element size RX Pong uDMAChannelTransferSet(UDMA_CH14_SSI3RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI3_BASE + SSI_O_DR), inbufferb2, sizeof(inbufferb2)); // source and destination for RX Pong uDMAChannelAttributeDisable(UDMA_CH15_SSI3TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); // put attributes in known state uDMAChannelAttributeEnable(UDMA_CH15_SSI3TX, UDMA_ATTR_USEBURST); // use burst mode (transfer, when 4 or more items are in RX FIFO) //**************************************************************************** //uDMA SSI3 TX Ping //**************************************************************************** uDMAChannelControlSet(UDMA_CH15_SSI3TX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_16); // transfer element size uDMAChannelTransferSet(UDMA_CH15_SSI3TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, outbufferb1, (void *)(SSI3_BASE + SSI_O_DR), sizeof(outbufferb1)); //**************************************************************************** //uDMA SSI3 TX Pong //**************************************************************************** uDMAChannelControlSet(UDMA_CH15_SSI3TX | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_16); uDMAChannelTransferSet(UDMA_CH15_SSI3TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, outbufferb2, (void *)(SSI3_BASE + SSI_O_DR), sizeof(outbufferb2)); uDMAChannelEnable(UDMA_CH14_SSI3RX); uDMAChannelEnable(UDMA_CH15_SSI3TX); SSIIntEnable(SSI3_BASE, SSI_DMATX | SSI_DMARX); // Enable the SSI3 DMA TX/RX interrupts. IntEnable(INT_SSI3); // Enable the SSI0 peripheral interrupts. } void Init_SSI(void) { // GPIO setup for SSI0 SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_SSI0); GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA4_SSI0RX); GPIOPinConfigure(GPIO_PA5_SSI0TX); GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2); SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_SLAVE, 10000, 16); SSIEnable(SSI0_BASE); // GPIO setup for SSI3 SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_SSI3); GPIOPinConfigure(GPIO_PD0_SSI3CLK); GPIOPinConfigure(GPIO_PD1_SSI3FSS); GPIOPinConfigure(GPIO_PD2_SSI3RX); GPIOPinConfigure(GPIO_PD3_SSI3TX); GPIOPinTypeSSI(GPIO_PORTD_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3); SSIConfigSetExpClk(SSI3_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_SLAVE, 10000, 16); SSIEnable(SSI3_BASE); } // called inside main.c FPULazyStackingEnable(); //Set CPU Clock to 80MHz. 400MHz PLL/2 = 200 DIV 2.5 = 80MHz SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); SysCtlPeripheralClockGating(true); Init_AIC3104(); Init_SSI(); Init_SSI0_uDMA_Transfer(); Init_SSI3_uDMA_Transfer(); BIOS_start();
Sadullah Zeyrek said:I´m emulating an I2S-interface
Perhaps - in light of your clear effort (the great mass of code presented) it proves useful to ask:
You should know that (even) Cortex M0 class MCUs contain a (proper) I2S interface - can the "lesser (emulation) performance" - and extra work - demanded when "bending/beating a (function deprived) device into (some) compliance" make full/proper sense? Should you not first seek (some) "specification" of your, "minimum functional requirements" - to justify such effort?
It is noted that you reference a "tech-doc" - it is hoped that (some) listing of "expected performance figures" are contained therein. (if not - is that not "telling?")
You may be able to "glean" minimal performance, I2S specs, via use of an MCU which includes "native I2S" - and then (deliberately) down-grading its performance - to discover the "spec level your application" may require...
Emulation (any emulation) most always cannot approach the "original" for "Speed, functional completeness, clarity of usage, and robustness" - thus "analysis should be performed" prior to, "Launching such effort." (especially so when the "candidate function to be emulated is, "ALIVE & WELL in Native Form!")
Hi cb1_mobile,
I am using a TM4C123GH6PM with the AIC3104 Audio-Codec. Because this Microcontroller don´t have a I2S-Interface, I need to emulate I2S with tow SPI-Modules.
I have the solution already.
uDMAChannelAssign(UDMA_CH14_SSI3RX); uDMAChannelAssign(UDMA_CH15_SSI3TX);
With this function it works!