kinetis KL05 DMA based ADC triggering

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

kinetis KL05 DMA based ADC triggering

2,322 Views
barryb
Contributor II

Hello,

I am working on a BLDC motor control project based on a KL05Z32 MCU. The application needs ADC sampling at a rate of 100kSamples/second.

I have built a solution based on chaining the PIT, DMA and the ADC. The PIT is running at 100kHz, it triggers DMA channel 0 to load one of 4 different configurations from a buffer to the SC1A register of ADC0. This starts the ADC conversion. The result of the measurement is placed in a buffer by another DMA channel.

This setup is working fine, as long as the first DMA0 request is running. I know I have to make sure the byte count register is not zero when the PIT triggers DMA0, but this is not working at the moment. The idea to achieve this, is by placing 0xFFFFC (= the highest allowed value which is a multiple of four) in the BCR register in the DMA0 complete interrupt. This trick was suggested in the topic stated below:

Re: PIT trigger the DMA and the DMA transfer data to the DAC doesn't work

After the BCR update in the interrupt, the configuration error is set.

Is there a way to fix this problem?

I attached the code from my project, note that the modulo buffers are disabled for easier testing.

The controller i`m using has mask 1N96F.

Thanks in advance

void DMA0_init(void)

{

    //use DMA channel 0 to move channel settings / triggering to ADC

    SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;

    SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;

   

    DMAMUX0_CHCFG0 = DMAMUX_CHCFG_SOURCE(0x00); //disable DMAMux modules before initialization

    DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(0xFFFFC);//(); //highest allowed multiple of 4

    DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

    // Clear pending errors and/or the done bit

    if (((DMA_DSR_BCR0 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)| ((DMA_DSR_BCR0 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)

       | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK) | ((DMA_DSR_BCR0 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))

       DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

   

    DMA_SAR0 = (uint32_t)&u32ADCcontrol[0];

    DMA_DAR0 = (uint32_t)&ADC0_SC1A;

   

  

    DMA_DCR0 = DMA_DCR_ERQ_MASK | DMA_DCR_CS_MASK |  DMA_DCR_EINT_MASK | DMA_DCR_SSIZE(0x00) | DMA_DCR_DSIZE(0x00) | DMA_DCR_SMOD(0x00) | DMA_DCR_DMOD(0x00) | DMA_DCR_LINKCC(0x00) | DMA_DCR_LCH1(0x00);

    DMAMUX0_CHCFG0 = DMAMUX_CHCFG_TRIG_MASK | DMAMUX_CHCFG_SOURCE(60); //use always enabled channel

   

    enable_irq(INT_DMA0, 0);

}

void DMA0_IRQHandler()

{

    GPIOA_PSOR = (1 << 9);

       

    DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

           

    DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(0xFFFFC) | DMA_DSR_BCR_DONE_MASK;

       

    GPIOA_PCOR = (1 << 9);

}

Tags (3)
18 Replies

1,385 Views
kroony
Contributor I

!I had what seems to be a very similar problem from what I can tell. Would have been nice to get a solution here, but I think I found out a solution/workaround.

I made made my IRQ handler look that same as yours in your initial post and found that configuration error(CE) bit was set when the DONE was reset (no matter the state of BCR, which has to be greater than 0).

I found that clearing the ERQ bit in DCRn while tending to DSRn and then resetting it stopped this from occuring (BCRn MUST be set after clearing DONE as it is cleared when DONE is cleared). Below is what got mine working (I am moving 4 samples of 16 bits).

void DMA0_IRQHandler()

{

  DMA_DCR0 &= ~DMA_DCR_ERQ_MASK;

  DMA_DAR0 = (uint32_t)& adc_Result;

  DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

  DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(0x08);

  DMA_DCR0 |= DMA_DCR_ERQ_MASK;

}

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry Bustsers,

First of all, I'd like to share an application note which using similar method to capture a couple of ADC channels, please check it through the link as below.

Next, can you tell me which error flag set then trigger the interrupt happens?

http://cache.freescale.com/files/32bit/doc/app_note/AN4590.pdf?fromsite=zh-Hans
Have a great day,

Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

Thank you for the application note, I will take a look in it.

The Configuration error bit becomes inside the DMA interrupt. The BCR value is also not loaded correctly (stays 0).

edit:

I have tried the construction in the application note, but it doesn`t work for me. The DMA module I have in the kinetis KL05 is fundamentally different than the one in the kinetis K controller. I don`t have the ability to use minor/major loops like described in the AN. The BCR still needs to be updated in the DMA ISR, which was the problem we started with.

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry,

According to your statement, I think you want to use 4 different configurations to set 4 ADC channel successively.

However I'm confused about set BCR=0xFFFFC that means the DMA0 will transfer to 0xFFFFC bytes when DMA request happens.

Obviously, the address 0xFFFFE08 is not allowed to set and DMA interrupt will triggered because of this configuration error definitely.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

Hello Ping,

I have checked the memory adress for the control register again, it is located at location 0x1FFFFE08. So the information I gave you earlier was incorrect, I'm sorry about that.

This means that the problem will not be caused by the source adress, because it is located in the lower sram part of the memory map. The DMA controller should be able to acces this location.

Do you have another idea what is causing the problem?

Thank you in advance

0 Kudos

1,385 Views
barryb
Contributor II

Hello Ping,

You are right about the address, I will check if I can fix the problem by placing the variables in the usable address space.

The concept around the usage of BCR is working fine, it just decrements the BCR by 4 after the transmission of 1 value from the control buffer (uint32_t datatype).

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry,

I think your purpose was transfer 4 bytes per time when DMA request came, Am I right?

If I am right, your purpose can't be achieved, as I mentioned before, the DMA would transfer to 0xFFFFC bytes one time.

Wish it helps.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

Hello

According to the reference manual, the DMA module should be able to transfer 4 bytes at a time by setting the cycle steal (CS) bit in the DMA_DCR0 register and setting the transfer size to 32bits. I visualised this by setting an I/O pin in the ADC interrupt handler, and the ADC triggered at exactly the right moment (tested with a digital oscilloscope).

Have a nice day 

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry,

I've checked your code again and I found that I missed the DMA_DCR0[CS] before.

Just like you mentioned, the DMA_DCR0[CS] can enable a single data transfer per DMA request when DMA_DCR0[CS] is asserted.

Now how's going on about your issue?
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

Hello

There is still no solution for the problem. I am running out of time for the project, therefore  I changed the software to update the ADC settings and store the result in the ADC interrupt handler. This is working, but causes a high interrupt load on the CPU. This is fine as a temporary solution, but in the final code I need to have working DMA code.

If there are any suggestions, I am off course more than happy to test them out.

Have a nice day

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry,

I was wondering if you can upload your whole project, then I can reproduce this issue on FRDM-KL05 board and work it out more effectively.

I'm looking forward to your reply.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

hello

Can I send you the files via email? I can’t publish the whole code on the internet due to company policy.

Have a nice day

From: jeremyzhou

Sent: Monday, March 23, 2015 9:52 AM

To: Barry Butsers

Subject: Re: - kinetis KL05 DMA based ADC triggering

kinetis KL05 DMA based ADC triggering

reply from jeremyzhou in Kinetis Microcontrollers - View the full discussion

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry,

You can just send me a simplified project that use the PIT to trigger the DMA to load the ADC configuration and store the ADC sample result through the DMA too when the ADC operate complete.

And I think it's OK to public.

I'm looking forward to your reply.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

Hello

You can find the project in the attached zip file. It is completely stripped, but I left some basic code to simulate the usual interrupt load on the CPU.

DMA0 is triggered by the PIT overflow, the transfer to ADC0_SC1A triggers an ADC conversion and the adc conversion complete dma request triggers the ADC result transfer to memory.

The transfers fail when the BCR from DMA0 reach 0.

Let me know if there are any questions.

Have a nice day

0 Kudos

1,385 Views
barryb
Contributor II

Hello

Have you made any progress with solving the DMA problem?

Have a nice day

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barrry,

Sorry for delay reply.

I have had a brief look through the code and I didn't find any obvious errors inside it, however I have one worry about it.

You'd better to move the arrays u32ADmeas[4] and u32ADCcontrol[4] to the RAM, it can avoid the address format incompatibility.

Hope it helps.
Have a great day,

Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Barry,

I've had a brief look through your code and I didn't find the any noticeable errors except the source address definition.

You can find the limitations of the source address value in the RM, just as the Fig1 shows. So I need to confirm the address of the u32ADCcontrol[0] whether follow the rule or not.

2015-03-18_9-49-20.jpg

                                                                          Fig 1
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,385 Views
barryb
Contributor II

Thank you for your response.

u32ADCcontrol[0] is located at memory location 0xFFFFE08 ->0xFFFFE14.

I don`t think this is the real problem because everything is working fine after the first DMA0 activation. It looks like the module doesn`t accept the BCR change when the last DMA cycle has ended.

0 Kudos