Atmel Microchip SAMG55 I2S master using DMA - Page 1
Forum section: electronics / general

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 10, 2017, 10:45:06 pm
content: Hi all,I'm trying to program an audio playback application on a SAMG55 board using I2S as output and wav file from SD card.I've been able to output a correct I2S signal using "blocking" method but for some reasons I can't make the DMA (PDC) works on this.I've seen this thread on avrfreaks, where @atadarov talks about issue using the DMA in non-poled mode on the G53.I've tried to initialize DMA before and after enabling I2SC with no luck.Please find my code attached. (cpp uses txt extension for attachment upload...)Any help would be appreciatedThanks!

author: ataradov
author_rank: Super Contributor
timestamp: July 10, 2017, 11:58:07 pm
content: I'm not sure if I provided this code on AVR Freaks, but here is my latest test source code for G53. It is very messy, and has a lot of unrelevant code commented out, but it does use PDC and it worked, if I remember correctly.See if any of this helps.I'm not really sure how to debug non-working PDC, I usually just try a lot of things until something works

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 11, 2017, 07:47:56 am
content: Hi Alex, thanks for your reply !I've taken a look at your code, and I think we have almost the same flow. I personally clock the I2SC with PCK4 with a prescaler of 28 (120MHz/29 = 4.138MHz) and I have a FS_RATIO of 128 => FS=32,3kHz. I've setup the mode to Master (I2SC_MR_MODE_MASTER), TX mono (I2SC_MR_TXMONO), 16bit data (4<< I2SC_MR_DATALENGTH_Pos), Master clock enable (I2SC_MR_IMCKMODE) with divider of 1.I think I have to set I2SC_MR_TXDMA to use one PCD channel only, but is it relevant since I'm in MONO mode? I tested with both settings but this doesn't change the overall non-working result, as expected.Once the setup is done, i do the following :Code:I2SC0->I2SC_TPR = (uint32_t)buffer_i2sc; //this is my buffer which contains 2048 bytes from 1 to 2048. uint16_t buffer_i2scI2SC0->I2SC_TCR = (uint32_t)I2SC_BUFFER_LENGTH; //2048 samplesI2SC0->I2SC_TNPR = (uint32_t)NULL;I2SC0->I2SC_TNCR = (uint32_t)0;I2SC0->I2SC_PTCR = PERIPH_PTCR_TXTEN;I2SC0->I2SC_CR = I2SC_CR_CKEN|I2SC_CR_TXEN;after this, I check using my logic analyzer and the clocking is right (MCLK, BCLK and WS), but I only have zeroes as data...If I replace all this code with the following, I get the correct data. So this is really a PDC issue I guess. Do you think that I should clock the peripheral with an higher frequency than ~4MHz?Code:I2SC0->I2SC_THR=0xCAFE;Thanks for your help

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 11, 2017, 04:40:56 pm
content: @atadarov I've tried your code (adapted to my setup, file attached), but with no results... The flag in I2SC_SR areneveralreadyset (see comment in code) and the output is always zero... Clocking is fine (MCLK, BCLK and WS). I have no idea what is wrong :/

author: ataradov
author_rank: Super Contributor
timestamp: July 11, 2017, 05:47:14 pm
content: if in the codeCode:while (0 == (I2SC0->I2SC_SR & I2SC_SR_ENDTX)){Serial.println("Waiting endtx..."); //never happensdelay(10);}the body never happens, it meant that I2SC_SR_ENDTX is set. Is it possible that previous digitalWrite() takes too long, and the whole buffer is sent before you get to the loop?

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 11, 2017, 06:07:49 pm
content: My bad, you're right, maybe the flag is already set but that sounds weird.I've removed the digitalWrite fuction and use direct port access still with no success...Code:I2SC0->I2SC_TPR = (uint32_t)sound_buf_0;I2SC0->I2SC_TCR = SOUND_BUF_SIZE;I2SC0->I2SC_TNPR = (uint32_t)sound_buf_0;I2SC0->I2SC_TNCR = SOUND_BUF_SIZE;I2SC0->I2SC_PTCR = I2SC_PTCR_TXTEN;I2SC0->I2SC_PTCR = I2SC_PTCR_TXCBEN;I2SC0->I2SC_CR = I2SC_CR_TXEN;I2SC0->I2SC_CR = I2SC_CR_CKEN;do{//digitalWrite(LED_BUILTIN, HIGH);PIOA->PIO_SODR = (1 << 6);while (0 == (I2SC0->I2SC_SR & I2SC_SR_ENDTX)){Serial.println("Waiting endtx..."); //never happensdelay(10);}while (0 == (I2SC0->I2SC_SR & I2SC_SR_TXBUFE)){Serial.println("Waiting txbufe..."); //never happensdelay(10);}if (PDC_I2SC0->PERIPH_PTSR & PERIPH_PTSR_ERR){Serial.println("DMA error..."); //never happensdelay(10);}delay(100);PIOA->PIO_CODR = (1 << 6);}while (millis() < 5000);PDC_I2SC0->PERIPH_PTCR = PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS;Serial.println("SETUP DONE!");I monitor the output pins with my logic analyzer since the reset and there is really only zeroes...Does the flow looks good to you? I'm a bit confused, I don't really know where to look...

author: ataradov
author_rank: Super Contributor
timestamp: July 11, 2017, 06:22:17 pm
content: It looks OK. Let me try this on my side. I'll get back to you.

author: ataradov
author_rank: Super Contributor
timestamp: July 11, 2017, 09:02:17 pm
content: Ok, so I think I remember now. The reason my code is so messy, is that I never managed to make it work. I originally started with D21, and got DMA working there with I2S. But I needed more processing power for actual sound generation, so I turned to G53. I started experimenting, but never got it to work with PDC.I tried to run my code as is (same binary from 2014) on G53, and did a port to G55. Neither one works with PDC.I'll poke at it a bit more, but you may want to create a support ticket.

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 11, 2017, 09:30:57 pm
content: Hum... sounds bad. I'll open a ticket at Microchip then....Let me know if you find anything interesting on your side. I'll get back to you as soon as I have anything new as well.Thanks for your help anyway Alex !

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 08:55:19 am
content: Hi,I'm still waiting for an answer on my ticket on MCP/Atmel.I tried to change the configurations but with no luck... (stereo/mono, one dma per channel/one dma for both, FS ratio, bit depth etc)Do you have any news on your side?Thanks,Theo

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 05:14:22 pm
content: Hi!Good news! I've been able to successfully send one buffer using DMA! Seems like both DMA channel must be configured even if only one channel is used (I2SC_MR_TXDMA). This channel must have the same buffer than the first one (not automatically copied by the I2SC as said in the datasheet apparently...). At the moment I use circular buffer. I'll try to implement interrupts next.I've made a new project based on @ataradov mcu-starter-projects code. Please find my version attached (I took the pmc.h from the a more recent CMSIS version). I'll try to make it work with my custom code setup too now.One issue though : the clock seems divided by two no idea why... I had to put FS_RATE64 instead of FS_RATE128 to have 32kHz FS.@ataradov, do you have any idea what's going on?Thanks

author: ataradov
author_rank: Super Contributor
timestamp: July 17, 2017, 05:30:24 pm
content: Have you actually checked what is sent? It is possible that mono option is ignored and that somehow also factors into frequency difference?Try to actually set different data for the other channel, and see if any of it appears in the output.

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 05:38:29 pm
content: If I put different data in the right PDC channel (base PDC+0x100 ?), I only see these data...

author: ataradov
author_rank: Super Contributor
timestamp: July 17, 2017, 05:44:38 pm
content: Ok, so from what you are saying, it looks like right channel is the main channel for mono operation. Try to disable the left one and see if things still work.

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 05:48:40 pm
content: Mmmmm, now this is weird. I have disabled the left channel and now I have only data coming from the right channel but in a strange order. This is not mono anymore since I have different data for left and right and there is no evident order.

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 05:51:13 pm
content: My bad, it works the same but with data only from the right channel. Correct order, and in mono (same data in both words).

author: ataradov
author_rank: Super Contributor
timestamp: July 17, 2017, 05:53:25 pm
content: So if it does not work at all with left-only configuration, and works as expected with right-only, it just looks like right channel is the primary channel for the mono mode. If everything else works, I'l just roll with that.

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 06:53:04 pm
content: Yep, sounds a bit weird. I'll let you know as soon as I have an official answer from Atmel/MCP supportThanks Alex for your help and your amazing work

author: ataradov
author_rank: Super Contributor
timestamp: July 17, 2017, 07:48:03 pm
content: EDIT: this was a response to CMSIS version question. I did not finish typing before going to lunchI have no idea. I just took all the header files from a sample project created by AS. So they would have been current 2 years ago.The only things that are used verbatim from CMSIS are header files, and I don't see how changing header files can break things, unless there is something wrong with them.But you also need to check that linker script is correct, and places vectors at the beginning. Arduino linker scripts may expect some other name or section for the vector table.

author: AloyseTech
author_rank: Regular Contributor
timestamp: July 17, 2017, 08:09:35 pm
content: I actually found the solution, it was absolutely not due to CMSIS version difference.The issue was that doingCode:PIOA->PIO_PDR = PIN_MCK;is not the same as calling theCode:pinPeripheral(PIN_I2SC0_MCK, GPIO_PERIPH_A);I found out right after posting. I should have tried more things before posting this.Now I'm facingthe same issue that you back in time with the G53, with the ENDTX interrupt being always set...