Hello TI forums!
I have a confounding problem in my project. I have a couple ADMP441 microphones connected to the I2S1 peripheral. The microphones are connected so that one is on the left channel and one is on the right channel (as expected). The I2S1 peripheral is in master mode to read the data from the microphones, and the word length is set to 24-bits. My goal is to use DMA3 to transfer the incoming bits to memory in ping-pong mode so that I can do various signal processing stuff on the data. However, when I look at the buffer via a LOG_printf call, it outputs only zeros. I look at the registers of the I2S1 peripheral and I can see data there. Here is my setup code: I've made the ping-pong buffer just one big array. I've only set up one channel to make sure it works.
/* Includes -------------------------------------------------------------------*/
#include "csl_dma.h"
#include "csl_i2s.h"
#include "csl_intc.h"
#include "csl_general.h"
#include "csl_sysctrl.h"
#include <std.h>
#include <log.h>
#include <sem.h>
#include <gbl.h>
#include "previscfg.h"
/* Defines --------------------------------------------------------------------*/
#define I2SCTRL_SOK ( 0 )
#define I2SCTRL_OPEN_FAIL ( 1 )
#define I2SCTRL_SETUP_FAIL ( 2 )
#define I2SCTRL_DMA0_CFG_FAIL ( 3 )
#define I2SCTRL_DMA1_CFG_FAIL ( 4 )
#define I2SCTRL_DMA0_START_FAIL ( 5 )
#define I2SCTRL_DMA1_START_FAIL ( 6 )
#define I2SCTRL_FLG_CLEAR_FAIL ( 7 )
#define I2SCTRL_INT_FAIL ( 8 )
#define I2S_INSTANCE ( I2S_INSTANCE1 )
#define DMA_CHAN_L ( CSL_DMA_CHAN0 )
#define DMA_CHAN_R ( CSL_DMA_CHAN1 )
#define DMA_BUFFER_SIZE ( 512 )
/* Prototypes -----------------------------------------------------------------*/
Int16 I2S_Start(void);
/* Variable Declarations ------------------------------------------------------*/
CSL_I2sHandle hI2s;
I2S_Config hwConfig;
CSL_DMA_Config dmaConfig;
CSL_DMA_ChannelObj dmaObj;
CSL_DMA_Handle dmaRightRxHandle;
#pragma DATA_ALIGN (readRightBuf, 8)
Uint32 readRightBuf[DMA_BUFFER_SIZE];
Int16 I2S_Start(void)
{
CSL_Status status;
hI2s = I2S_open(I2S_INSTANCE1, DMA_INTERRUPT, I2S_CHAN_STEREO);
if(NULL == hI2s)
return I2SCTRL_OPEN_FAIL;
/* Set the configuration for the I2S Peripheral */
hwConfig.dataType = I2S_STEREO_ENABLE; // Stereo, we have two microphones
hwConfig.loopBackMode = I2S_LOOPBACK_DISABLE; // TESTING PURPOSES: loopback enabled
hwConfig.fsPol = I2S_FSPOL_LOW; // Left channel selected when low
hwConfig.clkPol = I2S_RISING_EDGE;
hwConfig.datadelay = I2S_DATADELAY_ONEBIT; // Delay one bit
hwConfig.datapack = I2S_DATAPACK_DISABLE; // Not supported in 24-bit mode
hwConfig.signext = I2S_SIGNEXT_DISABLE; // Disable sign extend
hwConfig.wordLen = I2S_WORDLEN_24; // Microphone 24-bit data word out
hwConfig.i2sMode = I2S_MASTER; // uC as master, Microphone as a slave
hwConfig.dataFormat = I2S_DATAFORMAT_LJUST;
hwConfig.clkDiv = I2S_CLKDIV32;
hwConfig.fsDiv = I2S_FSDIV64;
hwConfig.FError = I2S_FSERROR_DISABLE;
hwConfig.OuError = I2S_OUERROR_DISABLE;
/* Configure the I2S peripheral */
if(I2S_setup(hI2s, &hwConfig) != I2SCTRL_SOK)
return I2SCTRL_SETUP_FAIL;
CSL_I2S1_REGS->I2SINTMASK &= 0xFFD7;
I2S_transEnable(hI2s, TRUE);
DMA_init();
/* Set the reset clock cycle */
CSL_FINS(CSL_SYSCTRL_REGS->PSRCR, SYS_PSRCR_COUNT,
CSL_DMA_RESET_CLOCK_CYCLE);
CSL_FINST(CSL_SYSCTRL_REGS->PRCR, SYS_PRCR_DMA_RST, RST);
/* Enable the corresponding DMA clock from PCGCR Registers */
CSL_FINST(CSL_SYSCTRL_REGS->PCGCR1, SYS_PCGCR1_DMA0CG, ACTIVE);
CSL_FINST(CSL_SYSCTRL_REGS->PCGCR2, SYS_PCGCR2_DMA1CG, ACTIVE);
CSL_FINST(CSL_SYSCTRL_REGS->PCGCR2, SYS_PCGCR2_DMA2CG, ACTIVE);
CSL_FINST(CSL_SYSCTRL_REGS->PCGCR2, SYS_PCGCR2_DMA3CG, ACTIVE);
/* Clear all DMA interrupt flags */
CSL_SYSCTRL_REGS->DMAIFR = 0xFFFF;
IRQ_clear(DMA_EVENT);
/* Enable all DMA interrupts */
CSL_SYSCTRL_REGS->DMAIER = 0xFFFF;
/* Configure DMA Channel 1 for I2S read. Enable interrupts here because
* the right channel is the last channel to be transmitted. */
dmaConfig.pingPongMode = CSL_DMA_PING_PONG_ENABLE;
dmaConfig.autoMode = CSL_DMA_AUTORELOAD_ENABLE;
dmaConfig.burstLen = CSL_DMA_TXBURST_1WORD;
dmaConfig.trigger = CSL_DMA_EVENT_TRIGGER;
dmaConfig.dmaEvt = CSL_DMA_EVT_I2S1_RX; // Microphone on I2S1
dmaConfig.dmaInt = CSL_DMA_INTERRUPT_ENABLE;
dmaConfig.chanDir = CSL_DMA_READ;
dmaConfig.trfType = CSL_DMA_TRANSFER_IO_MEMORY;
dmaConfig.dataLen = DMA_BUFFER_SIZE * 4; // CPU uses word addr, DMA uses byte addr
dmaConfig.srcAddr = (Uint32)(0x282C); // I2S Receive Right Data 0 Register
dmaConfig.destAddr = (Uint32)readRightBuf;
dmaRightRxHandle = DMA_open(CSL_DMA_CHAN13, &dmaObj, &status);
DMA_config(dmaRightRxHandle, &dmaConfig);
/* Clear DMA Interrupt Flags */
if(IRQ_clear(DMA_EVENT) != I2SCTRL_SOK)
return I2SCTRL_FLG_CLEAR_FAIL;
/* Enable DMA Interrupt */
if(IRQ_enable(DMA_EVENT) != I2SCTRL_SOK)
return I2SCTRL_INT_FAIL;
/* Start DMA Channel 1 */
if(DMA_start(dmaRightRxHandle) != I2SCTRL_SOK)
return I2SCTRL_DMA1_START_FAIL;
return I2SCTRL_SOK;
}
void dmaISR(void)
{
CSL_Status status;
if(DMA_getLastTransferType(dmaRightRxHandle, &status) == FALSE)
{
LOG_printf(&i2s, "Pong[0] = 0x%x", (Uint16)readRightBuf[0]);
}
else
{
LOG_printf(&i2s, "Ping[0] = 0x%x", (Uint16)readRightBuf[256]);
}
CSL_SYSCTRL_REGS->DMAIFR = 0xFFFF;
IRQ_clear(DMA_EVENT);
}
The setup seems correct yet readRightBuf seems to be set to zero.
Questions:
- Have I set the wordsize correctly? The ping-pong buffer is 512 Uint32's so 512 * (4 bytes per Uint32).
- Should the I2S1 peripheral be DMA_POLLED or DMA_INTERRUPT.
- I've made the buffer a Uint32 buffer because I'm getting 24 bits in from the microphones. The microphones need 32 clocks per frame however. Will a 24 bit word length generate 32 clocks per frame?
- It seems like pausing my program while in debug mode has no effect on the I2S and DMA. I can see that the destination address is changing in the DMA but sometimes after I unpause the address goes to a lower value, sometimes higher. If I single step through, I see the same behavior. I would expect a single step to increment one address block. Is this normal?
- Have I set the burst mode correctly? Only one 32-bit word is stored in the I2S register so it should be TXBURST_1WORD right?
Relevant Information
- I'm using a custom board with a C5535 installed. I'm using DSPBIOS 5.42.0.07, CSL 3.03, and CCS v5.
- I can see data coming in to the I2S1 peripheral. I've put a scope on the pins and verified that clocking/data/cs are correct.
- I've set the HWI_INT8 in the DSPBIOS configuration to _dmaISR.
- Previously in my main file, I've set SP0 to mode 0, SP1 to mode 0, and PP to mode 1.