3

I am attempting to read an incoming stream of data from UART, and trying to add each character received to an array of char until characters \r and \n are received (in that order).

I have written a function (char read_uart()) to wait for then return when a single character is received. This function properly receives and returns the single character, as it should.

On top of this function, I have tried creating another which is supposed to read every character and add them to an array until the termination combination is received. This is it:

void read_full_uart(char *message[4096])
{
    char previousTwo[2] = {'\0', '\0'};
    for (uint16_t i = 0; !(previousTwo[0] == '\r' && previousTwo[1] == '\n'); i++)
    {
        char currentValue = read_uart();
        *(message + i) = currentValue;

        previousTwo[0] = previousTwo[1];
        previousTwo[1] = currentValue;
    }
}

and this is how I am calling it:

char message[4096];
read_full_uart(&message);

However, when transmitting "bitcoin" for example, this is what message turns out to be:

b\000\000\000i\000\000\000t\000\000\000c\000\000\000o\000\000\000i\000\000\000n\000\000\000\r\000\000\000\n\000\000\000

The characters are received intact, but have three \000 characters appended to them.

I am wondering why this is happening, and how it can be adjusted so that these additional characters are not being inserted.

Starman
  • 168
  • 1
  • 11
  • 2
    Your function expects to get an array of 4096 pointers to `char`. (Actually a pointer to an array of 4096 pointers to `char`) You pass an array of 4096 `char`. Also `*(message+i)=currentValue;` is same as `message[i] = currentValue;` which assigns a `char` to a `char*`. Your compiler should show some warnings for these type mismatches. – Gerhardh Jun 08 '21 at 15:55
  • How did you manage to get `*(message + i) = currentValue;` to compile? You are assigning a `char` (`currentValue`) to a `char*` (`*(message+i)`) – Wyck Jun 08 '21 at 15:55
  • 5
    `char *message[4096]` in function signature is most likely an error. My crystal ball is quite sure you need `char message[4096]`, which is the same as `char message[]`, with corresponding change on the call site: `read_full_uart(message);`. Also, always always always compile your code with all warnings enabled (`-Wall -Wextra` in gcc) and have them as error: `-Werror`) – SergeyA Jun 08 '21 at 15:56
  • 1
    @Wyck probably with the famous "Implicitely making pointer from integer" warning ... – Gerhardh Jun 08 '21 at 15:56
  • 3
    Pro-tip: _treat warnings as errors_. – Wyck Jun 08 '21 at 15:57

1 Answers1

1

There are two issues here.

First, what you're passing to the function isn't what it's expecting. &message has type char (*)[4096], i.e. a pointer to an array of size 4096 of char. The function meanwhile is expecting a char *[4096], i.e. an array of size 4096 of char *. This is a type mismatch.

The second is that on this line:

*(message + i) = currentValue;

Or equivalently:

message[i] = currentValue;

You're assigning a char to an array of type char *. This is also a type mismatch.

This issues should have been picked up by the compiler as warnings. If not, turn up the warning level by passing the options -Wall -Wextra (assuming gcc) and treat warnings as errors.

You can fix these errors by changing the function to take an array of char:

void read_full_uart(char message[4096])

Or equivalently:

void read_full_uart(char *message)

And by passing the array directly to the function:

read_full_uart(message);
dbush
  • 205,898
  • 23
  • 218
  • 273