LPC1769 I2S + DMA

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1769 I2S + DMA

1,334 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by suja20 on Wed Jan 08 20:47:33 MST 2014
Hi, I'm using a LPC1769 with a WM8731 Audio Codec. Right now I'm only testing the transmission and the problem I'm having is that the DMA interrupts once and after that it doesn't interrupt. I think that the configuration part of the I2S is ok, because I checked the signals with a frequency meter and an oscilloscope.

I based most of the code on the cmsis examples.

This is the DMA Interrupt
void DMA_IRQHandler (void)
{
// check GPDMA interrupt on channel 0 TRANSMISION
if (GPDMA_IntGetStatus(GPDMA_STAT_INT, 0)){ //check interrupt status on channel 0
// Check counter terminal status
if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0)){
// Clear terminate counter Interrupt pending
GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
Channel0_TC++;
}
// Check error terminal status
if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)){
// Clear error counter Interrupt pending
GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
Channel0_Err++;
}
}
}


The DMA config, this DMA_Config is not the complete function just to make it easier to read:
#define BUFFER_SIZE 1024
uint8_t Channel0_TC = 0;
uint8_t Channel0_Err = 0;
uint8_t buff_tx[BUFFER_SIZE];
uin8_t *I2STXBuffer = buff_tx;

void DMA_Config(void)
{
    GPDMA_Init();
     LPC_GPDMA->DMACConfig = 0x01;

 /* Setting GPDMA interrupt */
    // Disable interrupt for DMA
    NVIC_DisableIRQ (DMA_IRQn);
    /* preemption = 1, sub-priority = 1 */
    NVIC_SetPriority(DMA_IRQn, ((0x01<<3)|0x01));

/*
 * Configure GPDMA channel 0 -------------------------------------------------------------
 * Used for I2S Transmit
 */
// Setup GPDMA channel --------------------------------
// channel 0
GPDMACfg.ChannelNum = 0;
// Source memory
GPDMACfg.SrcMemAddr = I2STXBuffer;
// Destination memory
GPDMACfg.DstMemAddr = 0;
// Transfer size
GPDMACfg.TransferSize = BUFFER_SIZE;
// Transfer width - unused
GPDMACfg.TransferWidth = 0;
// Transfer type
GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
// Source connection
GPDMACfg.SrcConn = 0;
// Destination connection - unused
GPDMACfg.DstConn = GPDMA_CONN_I2S_Channel_0;
// Linker List Item - unused
GPDMACfg.DMALLI = 0;
GPDMA_Setup(&GPDMACfg);

/* Reset terminal counter */
Channel0_TC = 0;
/* Reset Error counter */
Channel0_Err = 0;

GPDMA_ChannelCmd(0, ENABLE);

// Enable interrupt for DMA
NVIC_EnableIRQ (DMA_IRQn);

I2S_DMAStruct.DMAIndex = I2S_DMA_1;
I2S_DMAStruct.depth = 1;
I2S_DMAConfig(LPC_I2S, &I2S_DMAStruct, I2S_TX_MODE);
}


And a main loop, which does basically nothing

        I2S_DMACmd(LPC_I2S, I2S_DMA_1, I2S_TX_MODE, ENABLE);
while (1) {
}



Thanks in advance, please feel free to ask anything
Labels (1)
0 Kudos
Reply
5 Replies

1,031 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by suja20 on Thu Jan 09 19:07:12 MST 2014
Well i could get it running, however I tried generating a sine wave and I cant hear it correctly. My question is: When does the TX DMA interrupts? Is it when it sends GPDMACfg.TransferSize (in my case 1024) bytes or when it sends I2S_DMAStruct.depth (in my case 15)?

0 Kudos
Reply

1,031 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by suja20 on Thu Jan 09 15:42:08 MST 2014
Thanks for the answers!

I think I don't fully understand how the dma linked list work. if I want it to send a buffer continously (once it reaches the end, start from the beggining), is this approach alright?

DMA_LLI_Struct.SrcAddr = (uint32_t)I2STXBuffer; //buffer
DMA_LLI_Struct.DstAddr = (uint32_t)0; //peripheral
DMA_LLI_Struct.NextLLI = (uint32_t)&DMA_LLI_Struct;
DMA_LLI_Struct.Control = (BUFFER_SIZE)
| (2<<18) //source width 32 bit
| (2<<21) //dest. width 32 bit
| (1<<26) //source increment
| (1<<27)
;

So the next points to the same.
0 Kudos
Reply

1,031 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FrankAndersen on Thu Jan 09 06:52:02 MST 2014
Well, if you want to make the DMA interupt again, mabye you should create a linked list, so that the DMA continues to run.

Best regards,

Frank
0 Kudos
Reply

1,031 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by suja20 on Thu Jan 09 05:45:52 MST 2014
Thanks for the answer vostro! But still, I don't quite get what you meant... I'm enabling the IRQ in:

I2S_DMACmd(LPC_I2S, I2S_DMA_1, I2S_TX_MODE, ENABLE);

Which according to the cmsis code sets the tx_dma1_enable bit in the I2SDMA1 register.

And also I'm enabling the DMA interrupts, which in fact interrupts once:
NVIC_EnableIRQ (DMA_IRQn);


Is there another register which I have to configure?
0 Kudos
Reply

1,031 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by vostro1000 on Thu Jan 09 03:29:05 MST 2014
You need to enable interrupt on dma complete bit at one register that i dont remember and it should work!
0 Kudos
Reply