ADC RTOS Driver

The Analog to Digital Converter (ADC) RTOS driver is intended to use ADC functions in a Real-Time operating system, i.e. is thread safe.

Summary of the API's Functional Features

The API provides functions to:
  • Initialize and deinitialize the driver and associated hardware

  • Select single shot or free running conversion modes

  • Configure major ADC properties such as resolution and reference source

  • Start ADC conversion

  • Read back conversion results

Summary of Configuration Options

Below is a list of the main ADC parameters that can be configured in START. Many of these parameters are used by the adc_os_init function when initializing the driver and underlying hardware. Most of the initial values can be overridden and changed runtime by calling the appropriate API functions, such as adc_os_set_resolution.
  • Selecting which ADC input channels to enable for positive and negative input

  • Which clock source and prescaler the ADC uses

  • Various aspects of Event control

  • Single shot or free running conversion modes

  • Sampling properties such as resolution, window mode, and reference source

  • Run in Standby or Debug mode

Driver Implementation Description

The convert functions of the ADC RTOS driver are optimized for RTOS support. That is, the convert functions will not work without RTOS. The convert functions should only be called in an RTOS task or thread.

The ADC OS driver use a ring buffer to store ADC sample data. When the ADC raise the sample complete interrupt, a copy of the ADC sample register is stored in the ring buffer at the next free location. This will happen regardless of if the ADC is in one shot mode or in free running mode. When the ring buffer is full, the next sample will overwrite the oldest sample in the ring buffer.

To read the samples from the ring buffer, the function adc_os_read_channel is used. This function reads the number of bytes asked for from the ring buffer, starting from the oldest byte. If the number of bytes asked for are more than currently available in the ring buffer, or more than ringbuf size, the task/thread will be blocked until read done. If the number of bytes asked for is less than the available bytes in the ring buffer, the remaining bytes will be kept until a new call. The adc_os_read_channel function will return the number of bytes that want to read from the buffer back to the caller.

During data conversion, the ADC convert process is not protected, so that a more flexible way can be chosen in the application if multi-task/thread access.

Example of Usage

The following shows a simple example of using the ADC. The ADC must have been initialized by adc_os_init. This initialization will configure the operation of the ADC, such as single-shot or continuous mode, etc.

The example creates two tasks for channel 0 of ADC0: convert task and read task, and finally starts the RTOS task scheduler.

          /**
           * Example convert task of using ADC_0.
           */
          void ADC_0_example_convert_task(void *p)
          {
              (void)p;
              adc_os_enable_channel(&ADC_0, 0);
              while (1) {
                  adc_os_start_conversion(&ADC_0);
                  os_sleep(10);
              }
          }
          /**
           * Example read task of using ADC_0.
           */
          void ADC_0_example_read_task(void *p)
          {
              uint8_t adc_values[8];
              uint8_t num = 0;
              (void)p;
              while (1) {
                  num = adc_os_read_channel(&ADC_0, 0, adc_values, 8);
                  if (num == 8) {
                      /* read OK, handle data. */;
                  } else {
                      /* error. */;
                  }
              }
          }
          #define TASK_ADC_CONVERT_STACK_SIZE        ( 256/sizeof( portSTACK_TYPE ))
          #define TASK_ADC_CONVERT_PRIORITY          ( tskIDLE_PRIORITY + 1 )
          #define TASK_ADC_READ_STACK_SIZE           ( 256/sizeof( portSTACK_TYPE ))
          #define TASK_ADC_READ_STACK_PRIORITY       ( tskIDLE_PRIORITY + 1 )
          static TaskHandle_t xAdcConvertTask;
          static TaskHandle_t xAdcReadTask;
          int main(void)
          {
              /* Initializes MCU, drivers and middleware */
              atmel_start_init();
              /* Create ADC convert task */
              if (xTaskCreate(ADC_0_example_convert_task, "ADC convert", TASK_ADC_CONVERT_STACK_SIZE,
                              NULL,
                              TASK_ADC_CONVERT_PRIORITY, &xAdcConvertTask) != pdPASS) {
                  while (1) {
                      ;
                  }
              }
              /* Create ADC read task */
              if (xTaskCreate(ADC_0_example_read_task, "ADC read", TASK_ADC_READ_STACK_SIZE,
                              NULL,
                              TASK_ADC_READ_STACK_PRIORITY, &xAdcReadTask) != pdPASS) {
                  while (1) {
                      ;
                  }
              }
              /*  Start RTOS scheduler */
              vTaskStartScheduler();
              /* Replace with your application code */
              while (1) {
              }
          }
        

Dependencies

  • The ADC peripheral and its related I/O lines and clocks

  • The NVIC must be configured so that ADC interrupt requests are periodically serviced

  • RTOS