FreeRTOS & ADC
@Tesla DeLorean @Amel NASRI @Andrew Neil
Hi! I am starting to implement RTOS in my program, and I wonder if someone could help me to figure out what is happening with my MCU routine.
I am starting my program with baby steps. I initiated four threads that I intend to use (Main - UART - LCD - ADC). At first the code worked just fine and suddenly stopped working. The way the MCU is behaving seems to vary and is giving me a hard time to understand why. My threads are the following:
void mainFunction(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
char msg8[100];
sprintf(msg8,"Main Function ###### MAIN #####\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1000);
osDelay(500);
}
/* USER CODE END 5 */
}void uartFunction(void *argument)
{
/* USER CODE BEGIN uartFunction */
/* Infinite loop */
for(;;)
{ char msg8[100];
sprintf(msg8,"Uart Function ###### UART #####\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1000);
osDelay(200);
}
/* USER CODE END uartFunction */
}
void lcd_function(void *argument)
{
/* USER CODE BEGIN lcd_function */
/* Infinite loop */
for(;;)
{ char msg8[100];
sprintf(msg8,"LCD Function ###### LCD #####\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1000);
osDelay(400);
}
/* USER CODE END lcd_function */
}
The osDelay in these tasks are higher than it was at first. At the beginning, the code was working as expected with lower osDelays, and then stopped as if it was getting a segmentation fault or all the threads stuck for some reason. However, increasing the osDelay solved the issue for a few moments, but then the same problem occurred. An example of the print statements is:
WORKING:
ENTERED SCAN_ while loop1
ENTERED SCAN_ while loop2
X: 3753 | Y: 3352
LOOPING #6
ENTERED SCAN_ while loop1
ENTERED SCAN_ while loop2
X: 3762 | Y: 3352
LOOPING #7
ENTERED SCAN_ while loop1
ENTERED SCAN_ while loop2
X: 3762 | Y: 3350
LOOPING #8
ENTERED SCAN_ while loop1
ENTERED SCAN_ while loop2
X: 3759 | Y: 3352
LOOPING #9
ENTERED SCAN_ while loop1
ENTERED SCAN_ while loop2
X: 1883 | Y: 4086
LOOPING #10
LOOPING #10
INCREASE BUTTON
ACQUIRING adcConLEFT SCAN WITH SUCCESS
LCD Function ###### LCD #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
LCD Function ###### LCD #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
LCD Function ###### LCD #####
ADC Function ###### ADC #####
STUCK:
ADC Function ###### ADC #####
LCD Function ###### LCD #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
LCD Function ###### LCD #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
ADC Function ###### ADC #####
ADC Function
I do not know why. but for some reason it gets stuck when trying to do my scan_ function.
void scan_(uint32_t frameBuffer) {
int x_reading[SAMPLE_SIZE] = {0};
int y_reading[SAMPLE_SIZE] = {0};
int result[2] = {0};
int x_ = 2500, y_ = 500, i=0;
char msg8[100], msg[100];
sprintf(msg8,"ENTERED SCAN_\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
GPIO_InitTypeDef GPIO_InitStruct = {0};
ADC_ChannelConfTypeDef sConfig = {0};
while (x_ > 2100 && i < SAMPLE_SIZE) {
// === READ X POSITION ===
// Y+ (PC2) → VCC
GPIO_InitStruct.Pin = GPIO_PIN_2;
sprintf(msg8,"ENTERED SCAN_ while loop1\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET);
// Y− (PC0) → GND
GPIO_InitStruct.Pin = GPIO_PIN_0;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
// X+ and X− floating (PC1 + PB1)
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
osDelay(20);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
osDelay(20);
sprintf(msg8,"ENTERED SCAN_ while loop2\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
// ADC CHANNEL 9 - PB1 (X read)
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) Error_Handler();
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK){
y_ = HAL_ADC_GetValue(&hadc1);
y_reading[i] = y_;}
else {
printf_(frameBuffer, "Y ADC Timeout");
continue;
}
HAL_ADC_Stop(&hadc1);
// === READ Y POSITION ===
// X+ (PB1) → VCC
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
// X− (PC1) → GND
GPIO_InitStruct.Pin = GPIO_PIN_1;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
// Y+ and Y− floating (PC2, PC0)
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
osDelay(10);
// ADC CHANNEL 12 - PC2 (Y read)
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) Error_Handler();
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK){
x_ = HAL_ADC_GetValue(&hadc1);
x_reading[i] = x_;}
else {
printf_(frameBuffer, "X ADC Timeout");
continue;
}
HAL_ADC_Stop(&hadc1);
// Print values
//sprintf(msg, "X: %d | Y: %d", x_, y_);
//printf_(frameBuffer, msg);
sprintf(msg8,"X: %d | Y: %d\n", x_, y_);
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
i++;
sprintf(msg8,"LOOPING #%d\n", i);
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
}
// === Compute average (or call a better filtering function) ===
if(i < (SAMPLE_LOWER_CUT + SAMPLE_UPPER_CUT + 1)) return;
get_value(x_reading, y_reading, result, i);
if (result[0] == 0 || result[1] == 0){
sprintf(msg8,"SCAN_ RETURNING ALREADY\n");
osMutexAcquire(adcMutexHandle, osWaitForever);
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
osMutexRelease(adcMutexHandle);
return;
}
sprintf(msg, "RESULT -> X2: %d | Y2: %d", result[0], result[1]);
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 100);
uint16_t x = (uint16_t) result[0];
uint16_t y = (uint16_t) result[1];
osMutexAcquire(adcMutexHandle, osWaitForever);
read_pad(frameBuffer, &pressed, x, y); //
get_button(&button, &pressed); //
// 1 - 2 - SET - STOP
if(button.value == 1){ // Decrease
sprintf(msg8,"DECREASE BUTTON\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1);
ADC_THREAD_CONTROL_BIT |= SET_DECREASE;
button.data -= 1;
}
else if(button.value == 2){ // Increase
sprintf(msg8,"INCREASE BUTTON\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1);
button.data += 1;
ADC_THREAD_CONTROL_BIT |= SET_INCREASE;
}
else if(button.value == -4){ // Run or Set
sprintf(msg8,"RUN BUTTON\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1);
ADC_THREAD_CONTROL_BIT |= START;
}
else if(button.value == -5){ // Stop
sprintf(msg8,"STOP BUTTON\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1);
ADC_THREAD_CONTROL_BIT |= IDLE;
}
ADC_THREAD_CONTROL_BIT |= TOUCH;
sprintf(msg8,"ACQUIRING adcControllerMutexHandle\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1);
osMutexRelease(adcMutexHandle);
osMutexAcquire(adcControllerMutexHandle, osWaitForever);
MAIN_THREAD_ADC_CONTROL_BIT |= ADC_THREAD_CONTROL_BIT; // -> Carry bit flags to the main thread
osMutexRelease(adcControllerMutexHandle);
osMutexAcquire(adcMutexHandle, osWaitForever);
ADC_THREAD_CONTROL_BIT = 0x00; // Reset bits
sprintf(msg8,"LEFT SCAN WITH SUCCESS\n");
HAL_UART_Transmit(&huart8, (uint8_t *)msg8, strlen(msg8), 1);
osMutexRelease(adcMutexHandle);
}
Other print statements showed me that it get stuck when trying to init the ADC. I just wanted to know what I am missing. So my questions are:
- Is it possible that frequent GPIO reconfiguration is interfering with ADC behavior in RTOS?
- I also noticed that when this issue started, my amp draw increased (+- 15mA), does it have something to do with it?
- Could shorter osDelay times or thread starvation cause this ADC stall? Should I prioritize some threads
- Are there known conflicts between HAL_ADC_Start() and RTOS when used heavily in threads?
Thank you!
