Needs help on KL05Z "AdcDemoWithDMA" sample project (bitwise masks, high level questions)

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

Needs help on KL05Z "AdcDemoWithDMA" sample project (bitwise masks, high level questions)

1,128 Views
codenoob
Contributor II

Hi all,

I am an absolute newbie to embedded programming world. I downloaded the code sample package and am trying to understand the AdcDemoWithDMA that came with it. I am using Keil.

Question 1:  I understood it's demo-ing Analog to Digital conversion, but from what kind of analog input? and output to where?

Question 2:  This is a piece of code from "dma0_init". I can barely understand any of them. I am particularly confused by the bit-wise operations and the thousands of "masks" involved. Can anybody pick some examples and explain what those "masks" really do?

Question 3: are there more fundamental tutorials? I have read the quick start package, but as you guys have probably realized, I still need more help....

Thanks a lot!

void Dma0_init(void)

{

      SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;

      SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;

      // Config DMA Mux for UART0 operation

      // Disable DMA Mux channel first

      DMAMUX0_CHCFG0 = 0x00;

          

      // 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;

     

      // Set Source Address (this is the UART0_D register

      DMA_SAR0 = (unsigned int)&ADC0_RA;

     

      // Set BCR to know how many bytes to transfer

      DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(10);

     

      // Clear Source size and Destination size fields. 

      DMA_DCR0 &= ~(DMA_DCR_SSIZE_MASK

                    | DMA_DCR_DSIZE_MASK

                    );

     

      //     Set DMA as follows:

      //     Source size is byte size

      //     Destination size is byte size

      //     D_REQ cleared automatically by hardware

      //     Destination address will be incremented after each transfer

      //     Cycle Steal mode

      //     External Requests are enabled

      //     Asynchronous DMA requests are enabled.

      DMA_DCR0 |= (DMA_DCR_SSIZE(2)

                   | DMA_DCR_DSIZE(2)

                   | DMA_DCR_DMOD(0)

                   | DMA_DCR_D_REQ_MASK

                   | DMA_DCR_DINC_MASK

                //  | DMA_DCR_SINC_MASK  // no change source address

                   | DMA_DCR_CS_MASK

                   | DMA_DCR_EINT_MASK

                   | DMA_DCR_ERQ_MASK

                   | DMA_DCR_LINKCC(2)

                   | DMA_DCR_LCH1(2)

                //   | DMA_DCR_EADREQ_MASK

                   );

     

      // Set destination address

      DMA_DAR0 = (unsigned int)&m_uiADCResultBuff[0];

     

      // Enables the DMA channel and select the DMA Channel Source 

      DMAMUX0_CHCFG0 = DMA_REQUEST_SOURCE_ADC0; //DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(0x31); //0xb1;

      DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK;

      enable_irq(0);

}

Tags (3)
0 Kudos
Reply
2 Replies

634 Views
adriansc
Contributor IV

Hi,

In order to understand the Projects you need to know what is being written to the registers. All the masks there are already defined, try to find the definition for each mask and check its value. Also you need to look in the Reference Manual for KL05 and see the registers and their fields.

You can find the RM here: http://cache.freescale.com/files/32bit/doc/ref_manual/KL05P48M48SF1RM.pdf?fsrch=1&WT_TYPE=Reference%...

I will give you an example:

  • This is part of the code:

         DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;

        The name of the register is: DMA_DSR_BCRn (Section 23.3.3 in RM)

  • Here are the register fields.

dma1.JPG

  • Bit 24 is field DONE, it says writing 1 to that bit will clear all DMA status bits.

dma2.JPG

  • Definition of DMA_DSR_BCR_DONE_MASK is:

          #define DMA_DSR_BCR_DONE_MASK                    0x1000000u

        It is writng 0x1000000 to register DMA_DSR_BCR0.

  • The bitwise operator |= means that you only will write to that field and leave the other as they are.

Hope this helps.

634 Views
codenoob
Contributor II

Hi Adrian, Thanks a lot for your detailed answer. It was extremely helpful. I have better understanding about the registers now. Though I still have more questions about the overall workflow of the Analog to Digital Converter.

I extracted a few lines of code here.

Question 1:

How did they define those channels. From the reference manual, I found the channel address goes as things like "4003_B000". But from the source code, where do those "0x0d|0x40" come from?


Question 2:


Can you explain how the main function works? I don't quite understand the difference between "m_bDMA2Flag" and "m_bDMA0Flag"


Question 3:


Can you explain what method "StartADCScan" does? I don't quite understand how  DMA_DCR2 |= DMA_DCR_START_MASK; does any scanning...


I didn't include the implementation of

void Dma0_init(void);

void Dma2_init(void);

void DMA0_IRQHandler(void);

void DMA2_IRQHandler(void);

void StartADCScan( void );


But if you need them I will include them. Thanks again!


#include "common.h"

#include "adc.h"

#ifdef CMSIS

#include "start.h"

#endif

#define DMA_REQUEST_SOURCE_ADC0 40

#define DMA_REQUEST_SOURCE_ALWAYS   60

uint8_t m_uiADCChannelBuff[6] = {

  0x0d|0x40,        //channel 0x0d  -- external channel 13

  0x1d|0x40,        //channel 0x0d  -- Vrefh

  0x1e|0x40,        //channel 0x1e  -- Vrefl

  0x1d|0x40,        //channel 0x1d  -- Vrefh

  0x1a|0x40,        //channel 0x1a  -- temperature sensor

  0x1f|0x40         //channel disable,last time,disable ADC channel to avoid to generate new ADC interrupt.

};

uint16_t m_uiADCResultBuff[8] = {0,0,0,0,0,0,0};

uint8_t m_bDMA0Flag;

uint8_t m_bDMA2Flag;

void Dma0_init(void);

void Dma2_init(void);

void DMA0_IRQHandler(void);

void DMA2_IRQHandler(void);

void StartADCScan( void );

/********************************************************************/

int main (void)

{

  uint8_t i;

    uint32_t uiSum;

     

    printf("\nRunning the AdcDemoWithDMA project.\n");

    InitADC();

    if( ADC_Cal(ADC0_BASE_PTR) )

    {

    printf("ADC calibration fail!\n");

    }

    Dma0_init();

  

    Dma2_init();

    // disable ADC module

    ADC0_SC1A = 0x1f;

    // enable DMA transfer for ADC module

    ADC0_SC2 |= ADC_SC2_DMAEN_MASK;

    printf("input char 's', trigger new ADC scan with DMA...\n");

  while(1)

  {

  if( m_bDMA0Flag )

  {

  m_bDMA0Flag = 0;

  printf("ADC conversion success!\n");

            uiSum = 0;

  for(i=0;i<5;i++)

  {

  printf("0x%x,",m_uiADCResultBuff[i]);

                uiSum += m_uiADCResultBuff[i];

  }

  printf("\n");

          

        //    printf("new value for input voltage is: 0x%x\n",uiSum);

  }

  if( m_bDMA2Flag )

  {

  m_bDMA2Flag = 0;

  //printf("DMA channel 2 transfer completed!\n");

  }

        if( UART0_S1 & UART0_S1_RDRF_MASK )

        {

            if( 's' == UART0_D )

            {

                StartADCScan();

            }

        }

  }

}

void StartADCScan( void )

{

    // write start to DMA channel to start DMA transfer, so that write channel data to ADC_SCA

    DMA_DCR2 |= DMA_DCR_START_MASK;

}


					
				
			
			
				
			
			
				
			
			
			
			
			
			
		
0 Kudos
Reply