Strange String Corruption Bug

I’m an engineering student and very new to FreeRTOS and embedded programming as a whole, so please forgive my ignorance.

I’m making a digital alarm clock project with RTC and FreeRTOS on an STM32F401RE NUCLEO board. I am also using an older version of SEGGER SystemView.

This is the strangest bug I’ve ever experienced. Essentially, I’m trying to print a string to an LCD. Every time I call the lcdSendString() function, it prints some string found elsewhere in the build. I’ve even hard coded “hello world” in the print task handler, but the bug persists.

rtcUpdateTimerCallback and the print task are synchronized with a queue, but as I’ve implemented it for now, the queue does nothing more than that.

There is a possibility that my LCD driver is responsible as I made it myself, but from what I’ve seen it prints strings correctly.

printTaskHandler:

void printTaskHandler(void *parameters){
	uint32_t *str;
	while(1){
		xTimerStop(rtcUpdateTimerHandle, portMAX_DELAY);

		xQueueReceive(printQueueHandle, &str, portMAX_DELAY); 

		lcdClear();
		lcdMoveCursor(0, 0);

		lcdSendString("hello world");

		xTimerStart(rtcUpdateTimerHandle, portMAX_DELAY);
	}
}

rtcUpdateTimerCallback:

void rtcUpdateTimerCallback(TimerHandle_t xTimer){
	static int counter = 0;
	static const char* msg1 = "Hello";
	static const char* msg2 = "World";

	while (1){
		if (counter % 2 == 0){
			xQueueSend(printQueueHandle, (void*) &msg1, portMAX_DELAY);
		}
		else {
			xQueueSend(printQueueHandle, (void*) &msg2, portMAX_DELAY);
		}
		counter++;
	}
}

LCD Driver:
lcdSendString:

void lcdSendString(char *str){
	for(uint8_t i = 0; i < strlen(str) || i < 100; i++){
		lcdSendData(str[i]);
	}
}

lcdSendData:

static void lcdSendData(char data){

	//send 4 MSBs
	lcdSend( (data >> 4) & 0x0f, RS_DATA );

	//send 4 LSBs
	lcdSend( (data >> 0) & 0x0f, RS_DATA );
}

Example of Corrupted String:

void lcdSendString( char *pcString )
{
    /* When you call strlen() in a for loop, it may happen that strlen()
     * is called during every loop, which is a waste of time.
     */
     
    size_t uxLength = strlen( pcString );
    /* Your code used the OR operator `||`,
     * I think you want to use the AND operator `&&`.
     */
    for(size_t uxIndex = 0;
        ( uxIndex < uxLength ) && ( uxIndex < 100U );
        uxIndex++)
    {
        lcdSendData( pcString[ uxIndex ] );
    }
}

Have a try with this version

2 Likes

your strings are local to your callback function, but you pass pointers to them to other tasks. Beginner’s fallacy. Either pass the strings themselves to the queue, or make the strings to print global if they are constant.

In the code I posted, the print task does not try to access the address from the queue. The queue is only for synchronization. I am trying to print “hello world” hard coded.

Also, I tried dynamically allocating and making the strings global, but the issue persists.

Ah, such a simple mistake. This works. Thanks!

Even if your mistake is simple, please share it. Other developers may learn from it :slight_smile: