Sampling and taskset giving me errors.

Code:
#include <FreeRTOS.h>
#include <task.h>
#include <ADC.h>
#include <Arduino.h>
#include <DMAChannel.h>
#include <semphr.h>
#include <queue.h>




ADC adc;
const int bufferSize = 512;
uint16_t bufferA0[bufferSize];
uint16_t bufferA1[bufferSize];
uint32_t bufferSumA0 = 0;
uint32_t bufferSumA1 = 0;
uint16_t avSampleA0 = 0;
uint16_t peakA1 = 0;
DMAChannel dmaA0;
DMAChannel dmaA1;
int dmaBufferSize = bufferSize * sizeof(uint16_t);
volatile bool dmaA0TransferComplete = false;
volatile bool dmaA1TransferComplete = false;

SemaphoreHandle_t semA7 = NULL;
SemaphoreHandle_t semA13 = NULL;
QueueHandle_t queuePrint = NULL;

typedef struct {
  uint16_t avSampleA0;
  uint16_t peakA1;
} printMessage_t;



void taskADCA7(void *pvParameters)
{
  for (;;) {
    xSemaphoreTake(semA7, portMAX_DELAY);
    bufferSumA0 = 0;
    for (int i = 0; i < bufferSize; i++) {
      bufferA0[i] = adc.analogRead(A7);
      bufferSumA0 += bufferA0[i];
    }
    avSampleA0 = bufferSumA0 / bufferSize;
    xQueueSend(queuePrint, &avSampleA0, portMAX_DELAY);
  }
}

void taskADCA13(void *pvParameters)
{
  for (;;) {
    xSemaphoreTake(semA13, portMAX_DELAY);
    bufferSumA1 = 0;
    peakA1 = 0;
    for (int i = 0; i < bufferSize; i++) {
      bufferA1[i] = adc.analogRead(A13);
      bufferSumA1 += bufferA1[i];
      if (bufferA1[i] > peakA1) {
        peakA1 = bufferA1[i];
      }
    }
    
    xQueueSend(queuePrint, &peakA1, portMAX_DELAY);
  }
}

void taskPrint(void *pvParameters)
{
  uint16_t avSampleA0;
  uint16_t peakA1;
  for (;;) {
    xQueueReceive(queuePrint, &avSampleA0, portMAX_DELAY);
    xQueueReceive(queuePrint, &peakA1, portMAX_DELAY);
    Serial.print("A7 Average: ");
    Serial.print(avSampleA0);
    Serial.print(", A13 Peak: ");
    Serial.println(peakA1);
    vTaskDelay(pdMS_TO_TICKS(100)); // delay for 100 milliseconds before running again
  }
}

void taskPWM(void *pvParameters)
{
  // TODO: Implement PWM task
}

void setup()
{
  Serial.begin(115200);

  adc.setReference(ADC_REFERENCE::REF_3V3);                       // set the ADC reference voltage to 3.3V
  adc.setAveraging(1);                                            // set the number of ADC readings to average to 0
  adc.setResolution(12);                                          // set the ADC resolution to 12 bits
  adc.setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);  // set the ADC conversion speed to very high speed
  adc.setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);      // set the ADC sampling speed to very high speed


  dmaA0.begin(true);                                 // set the DMA channel to be interrupt-based
  dmaA0.destinationBuffer(bufferA0, dmaBufferSize);  // set the destination buffer to buffer
  dmaA0.attachInterrupt([]() {
    dmaA0TransferComplete = true;
    dmaA0.clearInterrupt();
  });

  dmaA1.begin(true);
  dmaA1.destinationBuffer(bufferA1, dmaBufferSize);
  dmaA1.attachInterrupt([]() {
    dmaA1TransferComplete = true;
    dmaA1.clearInterrupt();
  });

  adc.adc0->enableDMA();
  adc.adc1->enableDMA();
  dmaA0.transferSize(bufferSize);
  dmaA1.transferSize(bufferSize);

  // Start the continuous conversions on A7 and A13
  adc.startContinuous(A7, A13);

  // Create the time semaphores
  semA7 = xSemaphoreCreateBinary();
  semA13 = xSemaphoreCreateBinary();

  // Create the message queue
  queuePrint = xQueueCreate(10, sizeof(printMessage_t));


  // Create the tasks
  xTaskCreate(taskADCA7, "ADCA7", 1000, NULL, 1, NULL);
  xTaskCreate(taskADCA13, "ADCA13", 1000, NULL, 1, NULL);
  xTaskCreate(taskPrint, "Print", 1000, NULL, 1, NULL);
  xTaskCreate(taskPWM, "PWM", 1000, NULL, 1, NULL);

  // Start the scheduler
  vTaskStartScheduler();
}

void loop()
{
  // Empty. All tasks are running independently under the FreeRTOS scheduler.
}

Gives me the follow errors:

Code:
In file included from C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC.h:59:0,
                 from C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:3:
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'void ADC_Module::continuousMode()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:248:9: error: 'atomic' has not been declared
         atomic::setBitFlag(adc_regs.GC, ADC_GC_ADCO);
         ^
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'void ADC_Module::singleMode()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:257:9: error: 'atomic' has not been declared
         atomic::clearBitFlag(adc_regs.GC, ADC_GC_ADCO);
         ^
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'void ADC_Module::setSoftwareTrigger()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:284:9: error: 'atomic' has not been declared
         atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADTRG);
         ^
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'void ADC_Module::setHardwareTrigger()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:294:9: error: 'atomic' has not been declared
         atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADTRG);
         ^
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'volatile bool ADC_Module::isConverting()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:309:16: error: 'atomic' has not been declared
         return atomic::getBitFlag(adc_regs.GS, ADC_GS_ADACT);
                ^
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'volatile bool ADC_Module::isComplete()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:326:16: error: 'atomic' has not been declared
         return atomic::getBitFlag(adc_regs.HS, ADC_HS_COCO0);
                ^
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h: In member function 'volatile bool ADC_Module::isContinuous()':
C:\Users\soren\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.1\libraries\ADC/ADC_Module.h:353:16: error: 'atomic' has not been declared
         return atomic::getBitFlag(adc_regs.GC, ADC_GC_ADCO);
                ^

exit status 1

Compilation error: exit status 1





The purpose of the code is to sample on 2 different channels, and then also print a PWM. I have yet to do the PWM.
Then a separate task to print the values from the 2 ADC tasks.

However, it's giving me the "atomic" error, which I am unsure what the relation is.


EDIT: I get the error, whether or not I've included the atomic.h header.
EDIT 2: It's on a Teensy 4.1
 
Last edited:
Update: I've got some sampling code that can it can handle, but opon implementing it in tasks with FreeRTOS, I come back to the "Atomic" issue.
 
My gut tells me, this is related to your usage of FreeRTOS. I could be wrong. I did verify that with current Teensyduino I could compile at least one or two ADC examples.

What version of FreeRTOS are you using? And where did you install it from? I do not have this installed as such I can not try it out.
From here? https://github.com/tsandmann/freertos-teensy/tree/master/src

Was this all of the compiler errors or were there some before this, like conflict between ...

If so I suspect the issue is that both ADC and FreeRTOS both have a file atomic.h
 
It's related to the FreeRTOS implementation yes.

You're correct, that is the tsandmann FreeRTOS library, that I've downloaded, and using.

Without the FreeRTOS implementation, I get no "atomic not declared" in the ADC_Module.h from Teensyduino.

Edit:
No, there are no other compiler errors. All other errors I've patched, as they were a lack of structs.

EDIT:

Removing the atomic.h from freertos_teensy from tsandmann the follow errors shows up:

Code:
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino: In function 'void adc1Task(void*)':
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:55:44: error: call to 'ADC::setReference' declared with attribute error: Use adc->adcX->setReference instead
   adc->setReference(ADC_REFERENCE::REF_3V3);
                                            ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:56:25: error: call to 'ADC::setResolution' declared with attribute error: Use adc->adcX->setResolution instead
   adc->setResolution(12);
                         ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:57:65: error: call to 'ADC::setConversionSpeed' declared with attribute error: Use adc->adcX->setConversionSpeed instead
   adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
                                                                 ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:58:61: error: call to 'ADC::setSamplingSpeed' declared with attribute error: Use adc->adcX->setSamplingSpeed instead
   adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
                                                             ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:59:24: error: call to 'ADC::setAveraging' declared with attribute error: Use adc->adcX->setAveraging instead
   adc->setAveraging(32);
                        ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino: In function 'void adc2Task(void*)':
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:87:42: error: call to 'ADC::setReference' declared with attribute error: Use adc->adcX->setReference instead
 adc->setReference(ADC_REFERENCE::REF_3V3);
                                          ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:88:23: error: call to 'ADC::setResolution' declared with attribute error: Use adc->adcX->setResolution instead
 adc->setResolution(12);
                       ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:89:63: error: call to 'ADC::setConversionSpeed' declared with attribute error: Use adc->adcX->setConversionSpeed instead
 adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
                                                               ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:90:59: error: call to 'ADC::setSamplingSpeed' declared with attribute error: Use adc->adcX->setSamplingSpeed instead
 adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
                                                           ^
C:\Users\soren\OneDrive\Documents\Arduino\2Channel_DMA_ADC_Sample\2Channel_DMA_ADC_Sample.ino:91:21: error: call to 'ADC::setAveraging' declared with attribute error: Use adc->adcX->setAveraging instead
 adc->setAveraging(1);
                     ^

exit status 1

Compilation error: call to 'ADC::setReference' declared with attribute error: Use adc->adcX->setReference instead

Reinserting it, and the ADC errors disappear.
 
Last edited:
Those errors, are because he changed the ADC class awhile ago to remove some of the members...

So like: adc.setResolution(12); // set the ADC resolution to 12 bits

Needs to change to something like: adc->adc1->setResolution(12);

It has been awhile so I don't remember for sure if it is adc0, adc1 or is adc1 and adc2...
 
Code:
#include <FreeRTOS.h>
#include <task.h>
#include <ADC.h>
#include <Arduino.h>
#include <DMAChannel.h>
#include <semphr.h>
#include <queue.h>




ADC adc;
const int bufferSize = 512;
uint16_t bufferA0[bufferSize];
uint16_t bufferA1[bufferSize];
uint32_t bufferSumA0 = 0;
uint32_t bufferSumA1 = 0;
uint16_t avSampleA0 = 0;
uint16_t peakA1 = 0;
DMAChannel dmaA0;
DMAChannel dmaA1;
int dmaBufferSize = bufferSize * sizeof(uint16_t);
volatile bool dmaA0TransferComplete = false;
volatile bool dmaA1TransferComplete = false;

SemaphoreHandle_t semA7 = NULL;
SemaphoreHandle_t semA13 = NULL;
QueueHandle_t queuePrint = NULL;

typedef struct {
  uint16_t avSampleA0;
  uint16_t peakA1;
} printMessage_t;



void taskADCA7(void *pvParameters)
{
  for (;;) {
    xSemaphoreTake(semA7, portMAX_DELAY);
    bufferSumA0 = 0;
    for (int i = 0; i < bufferSize; i++) {
      bufferA0[i] = adc.analogRead(A7);
      bufferSumA0 += bufferA0[i];
    }
    avSampleA0 = bufferSumA0 / bufferSize;
    xQueueSend(queuePrint, &avSampleA0, portMAX_DELAY);
  }
}

void taskADCA13(void *pvParameters)
{
  for (;;) {
    xSemaphoreTake(semA13, portMAX_DELAY);
    bufferSumA1 = 0;
    peakA1 = 0;
    for (int i = 0; i < bufferSize; i++) {
      bufferA1[i] = adc.analogRead(A13);
      bufferSumA1 += bufferA1[i];
      if (bufferA1[i] > peakA1) {
        peakA1 = bufferA1[i];
      }
    }
    
    xQueueSend(queuePrint, &peakA1, portMAX_DELAY);
  }
}

void taskPrint(void *pvParameters)
{
  uint16_t avSampleA0;
  uint16_t peakA1;
  for (;;) {
    xQueueReceive(queuePrint, &avSampleA0, portMAX_DELAY);
    xQueueReceive(queuePrint, &peakA1, portMAX_DELAY);
    Serial.print("A7 Average: ");
    Serial.print(avSampleA0);
    Serial.print(", A13 Peak: ");
    Serial.println(peakA1);
    vTaskDelay(pdMS_TO_TICKS(100)); // delay for 100 milliseconds before running again
  }
}

void taskPWM(void *pvParameters)
{
  // TODO: Implement PWM task
}

void setup()
{
  Serial.begin(115200);

     adc.adc0->setReference(ADC_REFERENCE::REF_3V3);
    adc.adc0->setAveraging(0);
    adc.adc0->setResolution(12);
    adc.adc0->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
    adc.adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);


  adc.adc1->setReference(ADC_REFERENCE::REF_3V3);
  adc.adc1->setAveraging(0);
  adc.adc1->setResolution(12);
  adc.adc1->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
  adc.adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);


  dmaA0.begin(true);                                 // set the DMA channel to be interrupt-based
  dmaA0.destinationBuffer(bufferA0, dmaBufferSize);  // set the destination buffer to buffer
  dmaA0.attachInterrupt([]() {
    dmaA0TransferComplete = true;
    dmaA0.clearInterrupt();
  });

  dmaA1.begin(true);
  dmaA1.destinationBuffer(bufferA1, dmaBufferSize);
  dmaA1.attachInterrupt([]() {
    dmaA1TransferComplete = true;
    dmaA1.clearInterrupt();
  });

  adc.adc0->enableDMA();
  adc.adc1->enableDMA();
  dmaA0.transferSize(bufferSize);
  dmaA1.transferSize(bufferSize);

  // Start the continuous conversions on A7 and A13
  adc.adc0->startContinuous(A7);
  adc.adc1->startContinuous(A13);

  // Create the time semaphores
  semA7 = xSemaphoreCreateBinary();
  semA13 = xSemaphoreCreateBinary();

  // Create the message queue
  queuePrint = xQueueCreate(10, sizeof(printMessage_t));


  // Create the tasks
  xTaskCreate(taskADCA7, "ADCA7", 1000, NULL, 1, NULL);
  xTaskCreate(taskADCA13, "ADCA13", 1000, NULL, 1, NULL);
  xTaskCreate(taskPrint, "Print", 1000, NULL, 1, NULL);
  xTaskCreate(taskPWM, "PWM", 1000, NULL, 1, NULL);

  // Start the scheduler
  vTaskStartScheduler();
}

void loop()
{
  // Empty. All tasks are running independently under the FreeRTOS scheduler.
}

Decided to make 2 ADC channels just in case, it compiles fine.

Just the printing going wrong:
15:47:49.232 ->
15:47:53.719 ->
15:47:53.719 -> ASSERT in [c:\Users\soren\OneDrive\Documents\Arduino\libraries\freertos-teensy\src\portable\port.c:236] prvTaskExitError(): uxCriticalNesting == ~0UL
15:47:53.719 ->
15:47:53.719 -> Stack trace:
15:47:53.733 ->
-----------------------
Or this:
15:52:00.028 ->
15:52:00.028 -> ASSERT in [c:\Users\soren\OneDrive\Documents\Arduino\libraries\freertos-teensy\src\portable\port.c:236] prvTaskExitError(): uxCriticalNesting == ~0UL
15:52:00.028 ->
15:52:00.028 -> Stack trace:
15:52:00.028 -> Fault IRQ: 0x00000004
15:52:00.029 -> sp: 0x20207BC0
15:52:00.029 -> lr: 0xFFFFFFFD
15:52:00.029 -> stacked_r0: 0xE0508186
15:52:00.029 -> stacked_r1: 0x00007984
15:52:00.029 -> stacked_r2: 0xC0A00FFC
15:52:00.029 -> stacked_r3: 0x00000000
15:52:00.029 -> stacked_r12: 0x20207E90
15:52:00.029 -> stacked_lr: 0x00005E0B
15:52:00.029 -> stacked_pc: 0x00005E10
15:52:00.029 -> stacked_psr: 0x41000000
15:52:00.029 -> _CFSR: 0x00000082
15:52:00.029 -> (DACCVIOL) Data Access Violation
15:52:00.029 -> (MMARVALID) MemMange Fault Address Valid
--------------------------

This is all the serial monitor says.
No compiler errors. But hey, progress is progress.
And I think the way it's setup, it doesn't really care.


Edit: It crashes in taskA7, the first loop. Back to the drawingboard and patching.

Thanks so far :)
 
Last edited:
Sorry, I am probably can not help very much on that part as I don't use this RTOS. So I don't know the best way to debug these asserts and crashes.

I have not spent much time on any of the RTOS or threading libraries for the Teensy as they are not used or the like in any of the sort of standard things included with Teensyduino.
I wish there was one, but...

Good luck, hopefully some others that do use FreeRTOS will chime in.
 
Got something working. Forgot to initiate the tasks giving the semaphores away.

God so much it helps just to talk about the code. Thanks
 
Back
Top