cancel
Showing results for 
Search instead for 
Did you mean: 

Making ADC with DMA working with µSD card (SDMMC1 + FATFS) on NUCLEO-H743ZI2

M.CHN
Associate III

Hello,

I am working on a project in which I have to write data from my adc into a µSD card using SDMMC1 peripheral.

In my testing program to see the ADC1 behaviour with the DMA all work. My buffer stores the datas from my ADC using DMA and the callaback functions are used (HAL_ADC_ConvHalfCpltCallback() and HAL_ADC_ConvCpltCallback()).

In another testing program for SD card (using SDMMC1 and FATFS ) all work too. I can write textfiles on my sd card correctly.

However problems come when I want to write data from my ADC's buffer on the SD card. My callbacks fonction are never used in my program (the peripherals are configured like in my testing programs which work).

I saw on this post that ADC and DMA work correctly on D2 memory domain (https://community.st.com/s/question/0D50X00009XkXEH/stm32h7stm32h743-adc-with-dma?t=1596012726292), but SDMMC1 peripheral works in D1 domain and it can't access to D2 and D3 domain (it is in STM32H7 datasheet figure 4). The problem can be here but I don't know how to solve it.

I am using STM32CUBEIDE and STM32CUBEMX

Do you have an idea on the way to solve this matter ? You will find my project attached

Thanks for your help.

Mathieu

4 REPLIES 4

Might skim project later when at a computer.

Polled mode SD​MMC should be agnostic to memory in use.

You should not​ use SDMMC / FatFs operations in a callbacks. Callbacks occur under interrupt context and need to complete quickly and predictably. Manage large aligned buffers you can flush to card in a timely manner without making them the critical path for data collection.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
M.CHN
Associate III

Thank you for your answer Clive.

I made the change for the callback function (I also changed the main() to adapt as in the code snippet). Now my callback function set a flag which indicate that I must write the data from the buffer to the sd card. The problem is that my buffer is never filled by the ADC. However it was filled when I was testing the ADC without SDMMC and FATFS on a testing program.

/*main function */
int main(void)
{
  /*Init and f_mount part)*/
	if(f_open(&SDFile, "wav1.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK){
			//Error
		printf("Error openning file\r\n");
	}
	else {
		printf("File Openned Successfully!\r\n");
 
 
		//Write to the text file
		res = f_write(&SDFile, wtext, strlen((char *)wtext), (void *)&byteswritten);
		if((byteswritten == 0) || (res != FR_OK))
		{
			printf("Failed to write file!\r\n");
		}
		else printf("File written successfully\r\n");
 
		f_close(&SDFile);
	}
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*)rtext, BUFFER);
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  if (flagToWrite) {
		  	flagToWrite=0;
		  	if(f_open(&SDFile, "wav1.TXT", FA_OPEN_APPEND | FA_WRITE) != FR_OK){
		  		printf("Error opening file\r\n");
		  	}
		  	else {
 
	  			printf("File Opened Successfully!\r\n");
		  		for (int i = 0 ; i<BUFFER; i++){
		  			sprintf(wtext2,"%hu\r\n",rtext[i]);
					res = f_write(&SDFile, wtext2, strlen((char *)wtext2), (void *)&byteswritten);
					if((byteswritten == 0) || (res != FR_OK)){
						printf("Failed to write file!\r\n");
					}
					else printf("ok\r");
				}
	  			printf("\n");
	  			f_close(&SDFile);
		  	}
	  }
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
/* Callback functions */
 
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc){
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 1);
	flagToWrite = 1;
	}
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
	HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 0);
	flagToWrite = 1;
}
 
/* USER CODE END 4 */

M.CHN
Associate III

I created a new project with the same parameters and it works. My callback functions are used and my buffer's datas are written on the proper file. However there is another matter : the datas in the file don't match with my signal waveform. First the high-state value from the ADC is near from 760 (I generate a square form signal with an ADC in 12 bit resolution) which correspond to 0.6V. I should have something near 4095. Moreover, my buffer seems to be filled even when I don't have signal in input of my ADC :grinning_face_with_sweat: .

Does someone has an idea of what it is ? Is there something that I have done wrong ?

(the new project is attached)

Best Regards

Mathieu

M.CHN
Associate III

I found the solution for this matter, It was my bad (wrong connection) and now it works properly. However does anyone know how to store the data stream from the ADC stream without loss on my µSD. I just modified my main to write the data into a .bin file to avoid sprintf() function, but I still loose data as you can see on the graph. 0693W000003C0c6QAC.jpg

Do you have any advice to store these datas ?

Best Regards

Mathieu

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_FS_PCD_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  MX_SDMMC1_SD_Init();
  MX_FATFS_Init();
  /* USER CODE BEGIN 2 */
  FATFS fs;
  FRESULT res ;
  res = f_mount(&fs, "0:", 1);
    if (res == FR_OK){
  	  HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 1);
  	  /*res = f_open(&SDFile, "wav1.CSV", FA_CREATE_ALWAYS | FA_WRITE);
  	  if (res == FR_OK){
  		HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 0);
  		res = f_write(&SDFile, wtext1, strlen((char *)wtext1), (void *)&byteswritten);
  		if((byteswritten == 0) || (res != FR_OK)){
  			HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
  		}
  		else
  			HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 1);
  		f_close(&SDFile);
  	  }*/
 
    }
  //HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
 
  if(f_open(&SDFile, "wav1.BIN", FA_CREATE_ALWAYS  | FA_WRITE) != FR_OK){ //ouvre un fichier en �criture, le cr�e s'il n'existe pas
  		  				//Error
  			  HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
  		  		}
  		  		else {
  		  			HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
  		  			HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, BUFFERLENGTH);
  		  		}
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  if (flagToWrite){
		  flagToWrite = 0;
		  res = f_write(&SDFile, adcBuffer, strlen((char*)adcBuffer), (void *)&byteswritten);
		  /*for (int i = 0 ; i<BUFFERLENGTH; i++){
		  				sample = i+1+count*BUFFERLENGTH;
		  				sprintf(time,"%e;",sample);
		  				res = f_write(&SDFile, time, strlen((char*)time), (void *)&byteswritten);
		  				if((byteswritten == 0) || (res != FR_OK)){
		  					HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
		  				}
		  				else {
		  					HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
		  				}
			  sprintf(wtext2,"%hu\r\n",adcBuffer[i]);
			  res = f_write(&SDFile, (uint8_t*)wtext2, strlen((char*)wtext2), (void *)&byteswritten);
		  				if((byteswritten == 0) || (res != FR_OK)){
		  					HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
		  				}
		  				else {
		  					HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
		  				}
		  }*/
		  count++;
		  if (count == 300){
			  f_close(&SDFile);
			  HAL_ADC_Stop_DMA(&hadc1);
			  while(1){
				  HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
				  HAL_Delay(1000);
			  }
		  }
	  }
  }
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
 
  /* USER CODE END 3 */
}