2025-05-29 7:04 AM - last edited on 2025-05-29 7:16 AM by mƎALLEm
@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!
2025-05-29 10:22 AM
Have you considered using subroutines for repetitious code?
Why does the scanning routine constantly reinitialize GPIO's ? Couldn't you do that just once?
My expectation is that you'll need to debug, and determine if it's the logic in your code failing, or a miss exit condition.
Would recommend instrumenting Error_Handler() better, perhaps passing __FILE__,__LINE__ info so you can quickly identify if it's getting there, and from where.
Look for other infinite while(1) loops
2025-05-29 11:43 AM
@Tesla DeLorean Thank you for helping me out!!
I am changing the GPIO configuration to read the touch screen (I am changing it to read x axis and then to read y axis). This is the first time I am driving a touch screen and did not figure another way to do it. Regarding the code logic, I assumed it works because it was working as expected before introducing the threads. I know it is not an infinite loop because I would see the print statements in the terminal. Then I will do as you said and get better in using the Error_Handler() and __FILE__,__LINE__ to extract more information.
Note: Is there another way you would recommend to set up the touch screen reading?
Thank you as always!!
2025-05-29 1:10 PM
>>Note: Is there another way you would recommend to set up the touch screen reading?
Set up Once, Change the pins as you need too.
>>I do not know why. but for some reason it gets stuck when trying to do my scan_ function.
Stop in the debugger, and make a determination as to where it's stuck, and from there to why.
How are you managing ownership of the UART8 resource?
2025-05-29 1:31 PM
@Tesla DeLorean At first, I thought it was getting stuck because of the UART8 being used in different threads, so I used mutex to lock it, but the issue persisted. This version is not using the mutexes to lock the UART8 resource because it did not solve the issue, but I will do it again.
So far, the code is getting stuck this way:
I - It stuck within the while loop in the scan_, but it does not perform an infinite loop (it stops printing)
II - It gets better if I increase the osDelays within the loop, but it still gets stuck randomly.
I will perform a series of printing to better visualize it.
>> Set up Once, Change the pins as you need too.
Ans: I considered configuring the GPIOs just once, but I need to reconfigure them dynamically. The reason is that two of the touchscreen pins (left and right) need to be set as ADC inputs for position sensing, while the other two (up and down) drive current during the scanning process. Since the roles of the pins change depending on whether I'm reading the X or Y axis, I keep reconfiguring them accordingly. (Did I understand it wrong?)