Freescale MCU and analogin_read_u16 with multiple pins

01 Sep 2015

Hello,

I believe I found a bug with the routine analogin_read_u16 in the libraries/mbed/targets/HAL/TARGET_KLXX/analogin_api.c file.

On various Freescale MCUs, the ADC unit may have several channels which are multiplexed/sub-divided into channels "a" & "b" (e.x.. ADC4a, ADC5b, etc.) Selection of which sub-channel is controlled through ADCx_CFG2[MUXSEL] .

The analog_init routine sets ADCx_CFG2 appropriately for the pin being setup. The problem happens when the last ADC pin initialized is on a sub-channel that does not match a later pin read which has a different sub channel.

Using the KL16 processor as an example, say you want to use PTE17 & PTE29 as analog inputs. PTE17 is on channel ADC_SE5a while PTE29 is on ADC_SE4b. analog_init is called for PTE17 and then later PTE29 is initialized as well, ADCx_CFG2 will be left configured for the "b" channel.

Now, when analog_read_u16 is called to read PTE17 - it will incorrectly read SE5b instead of SE5a because ADCx_CFG2 is not set to the right mux selection (ADCx_CFG2[MUXSEL]).

analog_read_u16 needs to set the correct sub-channel before doing anything.

My suggestion is add an additional field to the analog_s structure to track the appropriate MUXSEL value for the pin. Then in analogin_read_uint16 set ADCx_CFG2[MUXSEL] to said value before initiating the read.

Maybe something like this:

objects.h

struct analogin_s {
    ADCName adc;
   uint32_t muxsel;
};

analogin_api.s

analogin_init:
    obj->muxsel = ADC_CFG2_MUXSEL_MASK
     if (obj->adc & (1 << CHANNELS_A_SHIFT)) {
       obj->muxsel = 0;
    }

analogin_read_u16:
       ADC0->CFG2 = obj->muxsel            // ADxxb or ADxxa channels
               | ADC_CFG2_ADHSC_MASK    // High-Speed Configuration
               | ADC_CFG2_ADLSTS(0);    // Long Sample Time Select
    // start conversion
    ADC0->SC1[0] = ADC_SC1_ADCH(obj->adc & ~(1 << CHANNELS_A_SHIFT));

Mike

01 Sep 2015

You are completely correct. Personally I have left it happily there since no one complained yet that their AnalogIn doesn't work :P (At least for the KL25 virtually all are on one channel). But your solution would be better yes. If you want you can always submit pull request on the mbed github.

01 Sep 2015

@Michael, thanks for this report.

As Erik wrote above, can you send PR to mbed sources https://github.com/mbedmicro/mbed. You can report this there as an issue and then fix it via PR.