cancel
Showing results for 
Search instead for 
Did you mean: 

FreeRTOS - how to give ADC and DAC DMA buffers to task?

NNagy.1
Senior

I'm trying to test reading data from the ADC DMA buffer, and writing it to the DAC DMA buffer, in one of my tasks.

ADC_HandleTypeDef hadc2;
ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc2;
DMA_HandleTypeDef hdma_adc3;
 
DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac1;
 
osThreadId_t processAudioBluHandle;
const osThreadAttr_t processAudioBlu_attributes = {
  .name = "processAudioBlu",
  .stack_size = 128,
  .priority = (osPriority_t) osPriorityRealtime
};
 
osThreadId_t uiTaskHandle;
const osThreadAttr_t uiTask_attributes = {
  .name = "uiTask",
  .stack_size = 128,
  .priority = (osPriority_t) osPriorityNormal
};
 
osMessageQueueId_t audioQueueHandle;
const osMessageQueueAttr_t audioQueue_attributes = {
  .name = "audioQueue"
};
 
#define BUFFER_LEN 256
#define HALF_BUFFER_LEN BUFFER_LEN>>1
 
static uint16_t adcBuffer[BUFFER_LEN] = {0};
static uint16_t dacBuffer[BUFFER_LEN] = {0};
 
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_ADC3_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
  MX_ADC2_Init();
  MX_FMC_Init();
  MX_TIM7_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim2);
  HAL_TIM_Base_Start_IT(&htim6);
  HAL_TIM_Base_Start_IT(&htim7);
  HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&potBuffer, 6);
  HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&adcBuffer, BUFFER_LEN);
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)&dacBuffer, BUFFER_LEN, DAC_ALIGN_12B_R);
 
  /* USER CODE END 2 */
  /* Init scheduler */
  osKernelInitialize();
 
  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */
 
  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */
 
  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */
 
  /* Create the queue(s) */
  /* creation of audioBufPtrQueue */
  audioQueueHandle = osMessageQueueNew (1, sizeof(uint16_t), &audioQueue_attributes);
 
  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */
 
  /* Create the thread(s) */
  /* creation of processAudioBlu */
  processAudioBluHandle = osThreadNew(StartProcessAudioBufferTask, NULL, &processAudioBlu_attributes);
 
  /* creation of uiTask */
  uiTaskHandle = osThreadNew(StartUITask, NULL, &uiTask_attributes);
 
  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */
 
  /* Start scheduler */
  osKernelStart();
 
  /* We should never get here as control is now taken by the scheduler */
 
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
#define ADC_HALF_FLAG 0
#define ADC_FULL_FLAG 1
 
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
	if (hadc->Instance == ADC3) {
		uint16_t flag = ADC_HALF_FLAG;
		osMessageQueuePut(audioInQueueHandle, &flag, 0U, osWaitForever);
	}
}
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	if (hadc->Instance == ADC3) { 
		uint16_t flag = ADC_FULL_FLAG;
		osMessageQueuePut(audioInQueueHandle, &flag, 0U, osWaitForever);
	}
}
 
void StartProcessAudioBufferTask(void *argument)
{
  /* USER CODE BEGIN 5 */
	uint16_t flag;
	uint16_t * inBufferPtr, * outBufferPtr;
  /* Infinite loop */
  for(;;)
  {
	  osStatus_t status = osMessageQueueGet(audioInQueueHandle, &flag, NULL, osWaitForever);
	  if (osOK == status) {
		  if (flag == ADC_HALF_FLAG) {
			  inBufferPtr = &adcBuffer[0];
			  outBufferPtr = &dacBuffer[HALF_BUFFER_LEN];
		  } else {
			  inBufferPtr = &adcBuffer[HALF_BUFFER_LEN];
			  outBufferPtr = &dacBuffer[0];
		  }
		  for (int i = 0; i < HALF_BUFFER_LEN; i++) {
			  outBufferPtr[i] = inBufferPtr[i]);
		  }
	  }
      osDelay(1);
  }
  /* USER CODE END 5 */
}

If I run the above code with a stack size 128 for the AudioBufferTask, the program reaches the Default_Handler

If I increase the stack size, the above code runs, but never seems to enter the loop in StartProcessAudioBufferTask (I can't even break at the osMessageGet() line)

Does anybody know why this could be, or does anyone have a better way that I could send the DMA buffers to and from a task?

#RTOS​ #ADC​ #DMA​ 

4 REPLIES 4
TDK
Guru

> If I run the above code with a stack size 128 for the AudioBufferTask, the program reaches the Default_Handler

Likely you are triggering an ISR that doesn't have a routine implemented. Read the VECTACTIVE bits in SCB->ICSR to determine what ISR it's in.

If you feel a post has answered your question, please click "Accept as Solution".

The VECTACTIVE bits are 0x3. Which looks like it's the RTC Wakeup interrupt? I wasn't expecting to need to implement a wakeup routine

https://www.st.com/resource/en/reference_manual/dm00224583-stm32f76xxx-and-stm32f77xxx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

Subtract 16, so that gives -13, which I believe is the hard fault handler. Examine SCB to determine the cause. Call stack is also informative. Likely a memory issue somewhere.
If you feel a post has answered your question, please click "Accept as Solution".

I checked the SCB registers, and it does look like it's a hard fault, even though the call stack and breakpoint don't show this.

Unfortunately the call stack doesn't give me much to work with:

WWDG_IRQHandler()
<signal handler called>() at 0xfffffffd
prvPortStartFirstTask()
xPortStartScheduler()

It looks like the bottom three are consistent no matter where I break (before the program crashes)

I think you're right that this is most likely a memory problem. I'll look into it some more tomorrow