0
\$\begingroup\$

Goal

On my current project I have connected a multiplexer (4051) on 8 adcs that I read from a single pin on my stm32h7. I would like to sequentially change the three gpio's connected to the mux between the values 000,001,010,011...,111 and on every change read the adc's values.

Design

I would like to achieve that with as less CPU interaction as I can so I decided to connect the adc with a dma(peripheral to memory) , and after a finished adc conversion cycle the gpio's values from another dma (memory to peripheral) as the three gpios are on the same port.I tried to do all that with a makefile project generated from the CubeMx and I tried to use the low level drivers at most parts as I have noticed that in several cases HAL was quite buggy.

Caveats I surpassed

The dma could not access the main ram so I had to change my linker script to allocate my dma buffers on an accessible part of the memory. So I did the following on the linker script:

 .dma_buffer (NOLOAD) : 
 {
   *(.dma_buffer)
 } > RAM_D2

And the following on my buffers:

#define DMA_ACCESSIBLE __attribute__((section(".dma_buffer"))) __attribute__((aligned(32)))
DMA_ACCESSIBLE volatile uint16_t adc_val[4] = {0};

Also I used the high level drivers for the adc as I noticed a bug on initialization

The problem

On the current state the adcs seems to work correct but I can not make DMAMAMUX and the gpios to work.So here is a minimal example and the configurations on CubeMX :

#define DMA_ACCESSIBLE __attribute__((section(".dma_buffer"))) __attribute__((aligned(32)))
DMA_ACCESSIBLE volatile uint16_t adc_val[4] = {0};
DMA_ACCESSIBLE volatile uint32_t mux_val[8] = {
  MUX1_Pin << 16 | MUX2_Pin << 16 | MUX3_Pin << 16,
  MUX1_Pin       | MUX2_Pin << 16 | MUX3_Pin << 16,
  MUX1_Pin << 16 | MUX2_Pin       | MUX3_Pin << 16,
  MUX1_Pin       | MUX2_Pin       | MUX3_Pin << 16,
  MUX1_Pin << 16 | MUX2_Pin << 16 | MUX3_Pin      ,
  MUX1_Pin       | MUX2_Pin << 16 | MUX3_Pin      ,
  MUX1_Pin << 16 | MUX2_Pin       | MUX3_Pin      ,
  MUX1_Pin       | MUX2_Pin       | MUX3_Pin 
};
int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
 
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)(&adc_val), 4);
 
  LL_GPIO_SetOutputPin(MUX1_GPIO_Port,MUX1_Pin);
  LL_GPIO_SetOutputPin(MUX2_GPIO_Port,MUX2_Pin);
  LL_GPIO_SetOutputPin(MUX3_GPIO_Port,MUX3_Pin);

  LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, 8); 
  LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_1, (uint32_t)mux_val);
  LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_1, (uint32_t)&MUX1_GPIO_Port->BSRR);
  LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);

  while (1)
  {
    printf("adc arr is:%u,%u,%u,%u\n", adc_val[0],adc_val[1],adc_val[2],adc_val[3]);
    LL_mDelay(1);
  }
}

Adc configuration Gpio configuration

On these example I just read the 8th adc (as I initially have the gpios to 111) and the gpios doesn't seem to update,what am I missing about the dma configurations?is there a better design I could use?

\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.