2

I'm trying to read 8 different single-ended analog signals from an array of op-amps with a STM32H7 MCU, however I only get an array of 8 zeros when using ADC1 with DMA (the readings are recovered via the UART5, but the zeros can also be seen when putting a break point after the ADC buffer is populated). Here's the setup/code:

enter image description here

enter image description here

In the main.c I have the following global variables for reading the ADC values:

/* USER CODE BEGIN PV */
uint8_t adc_ch=0; //adc channel index
volatile uint32_t adc_readings[ADC_CHS_QTITY]; //ADC values buffer, ADC_CHS_QTITY=8
uint16_t adc_res = 19859;
float adc_reading =0; //instantaneous converted value

inside void main(void) I have the following inits():

/* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();

(...)

/* USER CODE BEGIN 2 */

  xSemaphoreGive(xsemaph_adc);

  HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_readings, ADC_CHS_QTITY);

  xTaskCreate(vAnalogRead, "analog_read", 256, NULL, 24, &xAnalogRead_Handle);
  xTaskCreate(vSendAnalogReading, "send_reading", 128, NULL, 24, &xSendAnalogReading_Handle); //The ADC readings are sent to the UART for debugging
 

The AnalogRead and SendAnalogReading tasks:

void vAnalogRead(void *argument)
{
  /* Infinite loop */
  for(;;)
  {
     xSemaphoreTake(xsemaph_adc, portMAX_DELAY);
     adc_reading = adc_readings[adc_ch] / adc_res;
     adc_ch++;
     if(adc_ch>7)
     {
         adc_ch=0;
     }

     xSemaphoreGive(xsemaph_uart);
  }
  /* USER CODE END StartLeAnalog */
}

void vSendAnalogReading(void *argument)
{
    uint8_t ch=0;
    uint8_t reading[8];
    for(;;)
    {
        xSemaphoreTake(xsemaph_uart, portMAX_DELAY);
        ch = adc_ch - 1;
        if(ch==0xff)
        {
            ch=7;
        }
        reading[0] = 0x0a; //read begin
        reading[1] = 0x0a; //Analog reading, not digital
        reading[2] = ch; //adc channel
        gcvt(adc_reading, 3, &reading[3]); //the converted ADC readings
        reading[7] = 0x0b; //read end

        HAL_UART_Transmit(&huart5, reading, 8, 100);

        vTaskDelay(pdMS_TO_TICKS(1500));

        xSemaphoreGive(xsemaph_adc);
    }
}

2 Answers2

0

Bothe, vAnalogRead() and vSendAnalogReading() are pending on the semaphore from each other, xsemaph_adc & xsemaph_uart.

jay
  • 3,781
  • 8
  • 24
  • before the scheduler is started, a semaphore is given to vAnalogRead() to begin the readings. – strange_bakery Aug 10 '21 at 19:05
  • Oh, I see that now. Then, the problem is that the tasks might need to be created prior to the semaphore creation and initialization of that in the tasks' context. It is pure guess. Meantime, does portMAX_DELAY prevent interlocking too long? It's been a while since I looked at free rtos. – jay Aug 10 '21 at 19:10
  • The tasks do get created/started because I can fall into breakpoints set inside the tasks – strange_bakery Aug 10 '21 at 19:11
  • I am talking about "USER CODE BEGIN 2" releases "xsemaph_adc" first then xTaskCreate() comes next. BTW, is the ADC configured as auto-trigger? Otherwise, it needs to be triggered again at EOC. Am I missing that part as well? – jay Aug 10 '21 at 19:15
  • @strange_bakery At what point, is vAnalogRead() checking the ADC conversion end? – jay Aug 10 '21 at 19:17
  • 1
    @strange_bakery, I see the ADC is configured for continuous conversion. Now, I am trying to find how the EOC & re-trigger is handled. – jay Aug 10 '21 at 19:23
  • 1
    @strange_bakery One more thing, if you are using STM32 library, though I forgot what version it was, you probably need to carefully read their API and example. I felt their DMA implementation wasn't very intuitive. – jay Aug 10 '21 at 19:28
0

Make sure that you have Cortex M7 L1 data cache disabled on the DMA area of memory (or invalidate the cache prior to reading). You can also globally disable it (at a performance cost) with:

void SCB_DisableDCache (void);

The DMA writes to the memory, not to the cache so cache coherency is not maintained.

n.b. declaring the buffer as volatile is not sufficient.

Spehro Pefhany
  • 376,485
  • 21
  • 320
  • 842