Reputation: 53
I'm using strstr to search for the beginning and end of brackets so I can filter out incorrect entries sent on the UART from information I actually want/need.
I have my UART interrupt storing characters into an array and incrementing the counter. Below is the code in my main function:
volatile char UART_RX_Buffer[128]; // updated in UART
volatile uint16_t UART_Byte_Counter = 0; // updated in UART
while (1)
{
if(strstr(&UART_RX_Buffer[0], "{") != NULL)
{
if(strstr(&UART_RX_Buffer[0], "}") != NULL)
{
char *ret;
int startindex;
ret = strstr(&UART_RX_Buffer[0], "{");
startindex = (ret - UART_RX_Buffer);
// Clear out UART array and counter
char Empty_Buffer[128] = {0};
memcpy (UART_RX_Buffer, Empty_Buffer, sizeof(UART_RX_Buffer));
UART_Byte_Counter = 0;
}
}
}
So if I send it, say 012{345,678}, it will set the startindex as 3 (which is what I want). It's successfully entering the loop, setting startindex, and clearing the UART_RX_Buffer and counter correctly.
What's odd is it only works the first time through. If I send it a second time, I can see the buffer is holding the same data as the first time around . . . but it's not entering the first loop, recognizing the "{" character. I can see an issue if I'm not doing things correctly with the UART interrupt and the buffer isn't being filled correctly . . . but that doesn't appear to be the case. I don't really understand why I would get different results with what appears to be the same data (especially if I can confirm the data is in the UART buffer when trying to run that line).
Clearly I'm missing something. Any ideas what might be causing this? If it helps, it's an STM32L4R5ZI chip (though I would assume this is a C issue and not device specific). I'll include screenshots from the debugger all the same in case it helps. Thanks in advance!
Upvotes: 1
Views: 237
Reputation: 215305
The root of all your problems is nothing mentioned so far. But merely the fact that strings send over UART, from example through a PC terminal, are unlikely to be null terminated. They are not C strings! Far more likely, they are terminated by a single line feed '\n'
or in case of Windows perhaps carriage return + line feed, \r\n
.
This means that standard library string handling functions cannot be used. Forget about strstr
, strchr
and similar. You can only use those on null terminated strings (aka "C strings").
If you know the length of the data received - you should know this by counting the bytes received - you could use memchr
. Or alternatively just parse the data manually, which might be the most efficient if you are looking for a particular format anyway.
But before doing anything else, figure out how you know where a string ends. Is there line feed, null termination, perhaps a size counter in the UART packet etc. Don't just assume one particular format - programming cannot be done through guessing.
Furthermore, this code here is not "thread safe", or interrupt safe in this case. You cannot read directly from a buffer that an ISR is filling up at any moment - not without some means of synchronization. A busy flag, disabling the ISR temporarily etc. Interrupts are difficult to work with and sometimes it seems that barely any programmer implements them correctly.
There are three sensible ways to implement UART Rx functionality:
memcpy
that way.Upvotes: 2
Reputation: 4618
strstr issue in c
No, it is always your code issue. strstr
, the compiler, linker and the silicon are OK.
(especially if I can confirm the data is in the UART buffer when trying to run that line).
But it is not the data you think you have :)
The C sting is empty as it starts with the null terminating character.
strstr
sees the empty string. Your buffer-filling algorithm is definitely broken.
I can even tell you that you have not updated the index or pointer of the current buffer position as '0'
goes to the place where the previous transition ended:
Upvotes: 4