Vybrid LWADC more channels in continuous mode

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

Vybrid LWADC more channels in continuous mode

Jump to solution
1,492 Views
johannestraxler
Contributor III

I use the LWADC driver from MQX for accessing the ADC in Vybrid VF6xx by using the two functions: "_lwadc_init_input()" and "_lwadc_read_raw()".

For one single channel (ADC0SE2) this method works, but when I add a second channel (ADC0SE8) I don't get the correct samples, for any of the two channels!

Is there any restriction if I put more than one ADC channel into continuous mode by calling "_lwadc_init_input()"?

Thanks,

Johannes

Labels (3)
Tags (2)
1 Solution
812 Views
rendy
NXP Employee
NXP Employee

Hi Johannes,

this is obviously a bug in MQX. I've written a workaround for you and will report this to MQX team. Please try my workaround and tell me if it works.

lwadc_vadc.c

boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample)

{

    ADC_MemMapPtr adc_ptr = _bsp_get_adc_base_address(lwadc_ptr->context_ptr->init_ptr->ADC_NUMBER);

    LWADC_VALUE sample;

    _mqx_int ch_num = adc_ptr->HC1 & 0x1F;

    if( ch_num != lwadc_ptr->input )

        adc_ptr->HC1 = ADC_CHANNEL(lwadc_ptr->input);

    while((adc_ptr->HS & ADC_HS_COCO1_MASK) == 0){}

    sample = adc_ptr->R1;

    *outSample = sample & ADC_CDR_CDATA_MASK;

    /* Clear conversion complete */

    adc_ptr->HC1 &= ~ADC_HC1_AIEN1_MASK;

    return TRUE;

}

lwadc_vadc.h

extern boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr,  LWADC_VALUE_PTR outSample);

Thanks

Rene

View solution in original post

0 Kudos
12 Replies
813 Views
rendy
NXP Employee
NXP Employee

Hi Johannes,

this is obviously a bug in MQX. I've written a workaround for you and will report this to MQX team. Please try my workaround and tell me if it works.

lwadc_vadc.c

boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample)

{

    ADC_MemMapPtr adc_ptr = _bsp_get_adc_base_address(lwadc_ptr->context_ptr->init_ptr->ADC_NUMBER);

    LWADC_VALUE sample;

    _mqx_int ch_num = adc_ptr->HC1 & 0x1F;

    if( ch_num != lwadc_ptr->input )

        adc_ptr->HC1 = ADC_CHANNEL(lwadc_ptr->input);

    while((adc_ptr->HS & ADC_HS_COCO1_MASK) == 0){}

    sample = adc_ptr->R1;

    *outSample = sample & ADC_CDR_CDATA_MASK;

    /* Clear conversion complete */

    adc_ptr->HC1 &= ~ADC_HC1_AIEN1_MASK;

    return TRUE;

}

lwadc_vadc.h

extern boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr,  LWADC_VALUE_PTR outSample);

Thanks

Rene

0 Kudos
812 Views
johannestraxler
Contributor III

Dear Rene,

when I use your function I get the correct values, but the while loop confuses me a little bit, because I don't want the read_raw-Function to be blocking (it is read from an ISR), therefore I'm going to try Juan Antonios solution!

0 Kudos
812 Views
juangutierrez
NXP Employee
NXP Employee

Sorry, I meant to say the lwadc_vdac.c file.

Yeah, definitelly my suggestion will not work. The HC1 register does not expect bit-fields.

The patch from Rene should work.

I test Rene's changes updated to my version I working on (I'm not using the lwadc_vdac.c file from thread/317081), so I modified the read function in next way and it worked for me:

boolean _lwadc_read_raw(LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample)

{

    ADC_MemMapPtr  adc_ptr;

    LWADC_VALUE    sample;

    uint_32        device, input;

    _mqx_int        ch_num; 

    if (NULL == lwadc_ptr){

        return FALSE;

    }

    input = lwadc_ptr->input;

    device  = ADC_DEVICE(input);

    if (lwadc_ptr->context_ptr == NULL) {

        return FALSE;

    }

    adc_ptr = lwadc_ptr->context_ptr->adc_ptr;

    ch_num = adc_ptr->HC1 & 0x1F;

    if( ch_num != input )

        adc_ptr->HC1 = ADC_CHANNEL(lwadc_ptr->input);

    if ((adc_ptr->GC & ADC_GC_ADCO_MASK) == 0) {

        /* ADC is not in continuous mode. */

        adc_ptr->GC |= ADC_GC_ADCO_MASK;

    }

    sample = adc_ptr->R1;

   *outSample = sample & ADC_CDR_CDATA_MASK;

   return TRUE;

}

Note that:

Instead of replacing lwadc_vdac.c from thread/317081, what I did to make the ADC work was to comment out the next lines in _lwadc_init and just add the last line.

    // enable clock for adc module

    //if (_bsp_adc_io_init(init_ptr->ADC_NUMBER) != IO_OK)

    //{

    //    return FALSE;

    //}

    _bsp_adc_io_init(init_ptr->ADC_NUMBER);

The problem is that the _bsp_adc_io_init is ALWAYS returning IO_ERR, so not checking the return value do the trick.

I just commenting this if you are using a MQX version closer to 4.0.

Next release 4.0.1 will be as the lwadc_vdac.c file already provided by Rene.

812 Views
johannestraxler
Contributor III

Dear juangutierrez,

what is the current status of the ADC fix? Is it already fixed in the BSP trunk and when can we expect the new release?

Thanks Johannes

0 Kudos
812 Views
juangutierrez
NXP Employee
NXP Employee

Hi rendy

I checked the MQX4.1 and this fix was not included, actually they stick with the version in 4.0.

Any idea of why? Do you know when they plan to include this fix?

Thanks

0 Kudos
812 Views
johannestraxler
Contributor III

Dear rendy and juangutierrez

please give a short update when it is to expect that the fix will be included in the trunk version of MQX RTOS!

Thanks,

Johannes

0 Kudos
812 Views
johannestraxler
Contributor III

After checking the problem more in detail it seems, that only the last added input (with _lwadc_init_input()) is returned when calling _lwadc_read_raw().

When I pause the CPU and manually set the "ADCH" bits in the register ADC0_HC0 I can enable another channel, but each time calling _lwadc_read_raw() the same channel is read out, no matter what pointer is passed as "lwadc_ptr"! Please give advice!

0 Kudos
812 Views
naoumgitnik
Senior Contributor V

Dear Johannes,

Before a software person starts digging deeper, may you, please, take a look at https://community.freescale.com/thread/317081? - Perhaps it will help you.

Regards, Naoum Gitnik.

rendy

0 Kudos
812 Views
johannestraxler
Contributor III

Dear Naoum,

thanks for your answer, but this doesn't solve my problem, since I already applied this workaround in my BSP.

My problem is, when I use two (or more) different inputs on the same ADC (e.g. ADC0SE2, ADC0SE8) I only can read the values of the last input that has been registered with _lwadc_init_input(), when using _lwadc_read_raw().

I also tried to swap the init order of the inputs: at first ADC0SE8 and afterwards ADC0SE2 and as a result I only get the values from Input 2, even if I try reading Input 8.

Here's a code snippet how I'm using the ADC:

...

    LWADC_STRUCT input2;

    LWADC_STRUCT input8;

    LWADC_VALUE sample2 = 0;

    LWADC_VALUE sample8 = 0;

    _lwadc_init_input (&input2, ADC_INPUT_ADC0_AN2);

    _lwadc_init_input (&input8, ADC_INPUT_ADC0_AN8);

    while (1)

    {

         _lwadc_read_raw (&input2, &sample2);

         _lwadc_read_raw (&input8, &sample8);

         printf ("val2: %d, val8: %d \n", sample2, sample8);     // at this time i always get the samples from input8

         _time_delay(250);

    }

...

When you then swap the two lines

    _lwadc_init_input (&input8, ADC_INPUT_ADC0_AN8);

    _lwadc_init_input (&input2, ADC_INPUT_ADC0_AN2);

Then you will see that only the samples from input2 are output.

Looking forward to receiving your feedback!

BR,

Johannes

0 Kudos
812 Views
juangutierrez
NXP Employee
NXP Employee

Hi

Inspecting the code, it seems that each time _lwadc_init_input is called the ADC_HC1 is overwritten allowing the conversion for only the last channel initialized by this fxn.

Can you try the next change at mqx\source\io\lwadc.c file, please?

boolean _lwadc_init_input(LWADC_STRUCT_PTR lwadc_ptr, uint_32 input)

{

    ADC_MemMapPtr    adc_ptr;

    uint_32          device, channel;

      . . .

    /* Set channel to convert */

-   adc_ptr->HC1 = channel;

adc_ptr->HC1 |= channel;

    return TRUE;

}

I will try it tomorrow too.

0 Kudos
812 Views
johannestraxler
Contributor III

Hello,

I don't have the file mqx\source\io\lwadc.c in my BSP, but what I got is mqx/source/io/lwadc/lwadc_vadc.c (File-Version: 3.8.1.0, Oct-3-2012 with applied patch for ADC0/1) so I modified this one!

But the modification does not bring the benefit. It makes it even worse, because the function _lwadc_wait_next() does not return. So I tried it without wait_next, i.e. directly call _lwadc_read_raw() in a loop, but it only reads zeros. Please let me know how your tests are going?

Thanks,

Johannes

0 Kudos
812 Views
naoumgitnik
Senior Contributor V

Dear rendy,

May you look into this thread, please? - It looks like you already developed expertise with Vybrid ADC while dealing with the ADC previous issue.

Thanks in advance, Naoum Gitnik.

0 Kudos