Understanding _io_read Errors

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

Understanding _io_read Errors

668 Views
ttocsmi
Contributor I


I'm using MQX 4.0 and am using _io_read to read values from one the internal ADC modules on a MK10 mirco.  My read logic is similar to:

if ( _io_read(...) ) {

     do something

} else {

     write error message to console

}

Every so often, the _io_read function returns an error value and I get an error message on the console output.  I'm having trouble trying to understand what's causing the error & am hoping for some help.  How can I translate the return value of the function to a pass/fail value and learn more about why the read failed?

Here's more info:

  • I'm reading from multiple ADC inputs, and it's not always the same channel which errors out
  • Only one task reads from the ADCs
  • I have higher-priority tasks running, so it's possible my ADC task could be pre-empted during the _io_read process.  If so, how would I know this and how could I prevent it?
  • Is there a way to monitor task stack usage, or tell if a task is being continually pre-empted?

Thanks for the help!

Tags (3)
0 Kudos
2 Replies

487 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Scott,

Can you show on the configuration about the ADC and the task ,  also the error ?

And you can refer to the adc sample under  C:\Freescale\Freescale_MQX_4_1_1\mqx\examples (change 4.1 to 4.0,  I use MQX4.1, ).

Hope it helps

Alice

0 Kudos

487 Views
ttocsmi
Contributor I

Thanks for the reply, Alice.

I'm not sure exactly what the "error" is, as I'm having difficulty reading and interpreting the return value of the _io_read function.  When the "error" occurs, my code enters the "else" branch and I see the message I have within.

This looks to be the relevant code from the adc_demo.c file:

        /* channel 1 sample ready? */
        if (read(f_ch1, &data, sizeof(data) ))
            printf("ADC ch 1: %4d ", data.result);
        else
            printf("              ");

Looking at the comment line, if a sample cannot be read, it's because it is not "ready".  Does this imply that there is not necessarily an error, just that it hasn't been acquired/processed yet?  If so, then my interpretation of a "failed" read as an "error" is incorrect.  Like I stated previously, this does not happen regularly or consistently on any one channel.

Is there a way to determine the reason why the sample isn't ready?  What can I do to ensure that when requested, the sample will be ready? 

Here are the configuration/initialization commands for my ADC:

#define ADC1 "adc1:"   /* adc1  must be #1 as the inputs are wired to ADC 1 */

// ADC configuration parameters

#define ADC_HARDWARE_AVERAGING      16
#define NO_SAMPLE_IN_ONE_RUN     16  // number of samples in one run sequence (orig 32)
#define START_OFFSET    4400 // time offset from trigger point in us (orig 100); manually tweaked for improved accuracy
#define PERIOD      30000   // period in us (orig 30000)
#define SCALE_RANGE     0x10000 // scale range of result (not used now)
#define CIRCULAR_BUFFER_SIZE  16  // circular buffer size (sample count) (orig 32)
#define ADC_LONG_SAMPLE    2  // long sample time = 2 usec
#define ADC_REF_VREF    3300    // Vref = 3.3 volts
#define MY_TRIGGER ADC_PDB_TRIGGER    // logical trigger ID that starts this ADC channel

// global variables
MQX_FILE_PTR f0, f1;

// ADC device initialization structure
const ADC_INIT_STRUCT adc_init = { ADC_RESOLUTION_DEFAULT, /* resolution */
};

//
// AI_MUX_DA and AI_MUX_DA read together
//

  const ADC_INIT_CHANNEL_STRUCT ai_mux_da_param = { AI_MUX_DA, //  physical ADC channel
  ADC_CHANNEL_MEASURE_ONCE | ADC_CHANNEL_START_TRIGGERED,
  NO_SAMPLE_IN_ONE_RUN,
  START_OFFSET,
  PERIOD,
  SCALE_RANGE,
  CIRCULAR_BUFFER_SIZE,
  MY_TRIGGER
};

  const ADC_INIT_CHANNEL_STRUCT ai_mux_db_param = { AI_MUX_DB, //  physical ADC channel
  ADC_CHANNEL_MEASURE_ONCE | ADC_CHANNEL_START_TRIGGERED,
  NO_SAMPLE_IN_ONE_RUN,
  START_OFFSET+100,     // problems occur if both reads occur simultaneously
  PERIOD,
  SCALE_RANGE,
  CIRCULAR_BUFFER_SIZE,
  MY_TRIGGER
};

Within the main task loop, I'm opening the ADCs

_mqx_int error_code = MQX_OK;

f1 = _io_fopen(ADC1, (const char*) &adc_init);
if (f1 != NULL) {
  // long sample time
  error_code = _io_ioctl(f1, ADC_IOCTL_SET_LONG_SAMPLE, (pointer)ADC_LONG_SAMPLE);
  // hardware averaging
  error_code = _io_ioctl(f1, ADC_IOCTL_SET_HW_AVERAGING, (pointer)ADC_HARDWARE_AVERAGING);
  // reference voltage; not sure how this is used
  error_code = _io_ioctl(f1, ADC_IOCTL_SET_REFERENCE,(pointer)ADC_REF_VREF);
  // acquisition speed (was previously HIGH speed
  error_code = _io_ioctl(f1, ADC_IOCTL_SET_LOW_SPEED, NULL);
} else {
   _task_block();
}
_time_delay(OPEN_DELAY);

Then opening the individual channels

ch_ai_mux_da = _io_fopen(ADC1 "MUX_DA", (const char*) &ai_mux_da_param);
if (ch_ai_mux_da != NULL) {
} else {
  _io_printf("Failed to open MUX_DA\n");
  _task_block();
}
ch_ai_mux_db = _io_fopen(ADC1 "MUX_DB", (const char*) &ai_mux_db_param);
if (ch_ai_mux_db != NULL) {
} else {
  _io_printf("Failed to open MUX_DB\n");
  _task_block();
}

Then triggering

_io_ioctl(f1, ADC_IOCTL_FIRE_TRIGGER, (pointer) MY_TRIGGER);
_time_delay(TRIGGER_TIME_DELAY);

Then reading (analogLimitCheck is my limit check routine, the BYPASS... statement is the one which started this discussion)


if (_io_read(ch_ai_mux_da, &data, sizeof(data))) {
  analogLimitCheck(...);
} else {
  _io_printf("BYPASS reading ch_ai_mux_da\n");
}
if (_io_read(ch_ai_mux_db, &data, sizeof(data))) {
  analogLimitCheck(...);
} else {
  _io_printf("BYPASS reading ch_ai_mux_da\n");
}

Then closing the channels

   
_io_fclose(ch_ai_mux_da);
_io_fclose(ch_ai_mux_db);


And closing the ADC

_io_fclose(f1);
_time_delay(CLOSE_DELAY);


========

Please let me know if I'm missing anything. I think I got it all.

Thanks!

0 Kudos