Serial.readBytes() doesn't accept byte type

Please tell us which board you are using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Serial.readBytes() doesn't accept byte type

Post by nullkraft »

I just received my Metro M4 express today and although I'm having several problems with it the one thing that I can't find anywhere is a problem with Serial.readBytes()

The Arduino reference https://www.arduino.cc/reference/en/lan ... readbytes/ says that Allowed data types: array of char or byte. But when I compile the following code it only works when using char* serialAsBytes.

Code: Select all

//char* serialAsBytes;
byte* serialAsBytes;

void setup() {
  Serial.begin(115200);
}

void loop() {
  while (Serial.available()) {
    Serial.readBytes(serialAsBytes, 1);
  }
}
The error I get is:

Code: Select all

/tmp/arduino_modified_sketch_144682/Blink.ino: In function 'void loop()':
Blink:11:22: error: invalid conversion from 'byte*' {aka 'unsigned char*'} to 'char*' [-fpermissive]
   11 |     Serial.readBytes(serialAsBytes, 1);
      |                      ^~~~~~~~~~~~~
      |                      |
      |                      byte* {aka unsigned char*}
In file included from /home/mark/.arduino15/packages/adafruit/hardware/samd/1.7.10/cores/arduino/Arduino.h:158,
                 from sketch/Blink.ino.cpp:1:
/home/mark/.arduino15/packages/adafruit/hardware/samd/1.7.10/cores/arduino/USB/USBAPI.h:141:25: note:   initializing argument 1 of 'size_t Serial_::readBytes(char*, size_t)'
  141 |  size_t readBytes(char *buffer, size_t length);
      |                   ~~~~~~^~~~~~
exit status 1
invalid conversion from 'byte*' {aka 'unsigned char*'} to 'char*' [-fpermissive]
I modified Stream.h and Stream.cpp to include a new function called ReadBytes() and was able to compile it using an uint8_t rather than char. Still needs testing. But I was wondering why the SAMD51 boards didn't follow the Arduino reference?

User avatar
blnkjns
 
Posts: 963
Joined: Fri Oct 02, 2020 3:33 am

Re: Serial.readBytes() doesn't accept byte type

Post by blnkjns »

I have the idea that on M0/M4 boards the types char and byte give problems. I run into similar issues when porting stuff to the micro:bit.
Use int8_t or uint8_t (unsigned) instead.
I wonder if you could add the regular Arduino terminology as defines in the M0/M4 board libraries like. Or just throw these two lines in your own code if you port from say Uno/Leonardo/MEGA etc to ATSAMD boards.

Code: Select all

#define char int8_t
#define byte uint8_t

User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Re: Serial.readBytes() doesn't accept byte type

Post by nullkraft »

Yeah, I tried that only to find out that the Arduino definition of byte is unsigned char. I tried to find out where that was in the Arduino code but I was really starting to head down that deep dark rabbit hole when I decided to ask here first.

User avatar
User_UMjT7KxnxP8YN8
 
Posts: 323
Joined: Tue Jul 17, 2018 1:28 pm

Re: Serial.readBytes() doesn't accept byte type

Post by User_UMjT7KxnxP8YN8 »

Try this:

Code: Select all

void loop() {
  while (Serial.available()) {
    Serial.readBytes((char*)serialAsBytes, 1);
  }
}

User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Re: Serial.readBytes() doesn't accept byte type

Post by nullkraft »

That causes problems for the rest of my sketch. I posted the code above as a minimal demonstration of the issue but using byte instead of char allows me to do the following:

Code: Select all

const uint8_t numBytesInSerialWord = 4;
uint32_t serialWord;                                  // Serial Word as 32 bits
uint8_t* serialWordAsBytes = (uint8_t*)&serialWord;   // Serial Word as a byte array
uint16_t* serialWordAsInts = (uint16_t*)&serialWord;  // Serial Word as a int array
This lets me treat the 32 bit serial word as either an 8 or 16 bit array. These arrays then get processed into 32 bit register values for the MAX2871 and the ADF4356 Frac-N Synthesizer/VCO IC's that we use for a 3 GHz spectrum analyzer. When I try using char I get extra garbage because the Arduino IDE seems to only read out 7 bits for char. And I need to be able to left and right shift these bytes into new positions for programming the two chips. The benefit of using this method is that I don't have to use for-loops and subscripts to access the individual bytes of the 32 bit serialWord and it also eliminates the need for the reverse methods.

Because a 3 GHz spectrum analyzer needs to push a lot of data through a 16 MHz Arduino it requires that every step be highly optimized. And even though the Metro M4 express runs at 120 Mhz I don't want to give up those optimizations. Using the Metro M4 express means I could possibly turn a full 3 second sweep into 0.3 seconds or less. Ideally I'd like to do 30 sweeps per second so I'd still need the optimizations for the Metro.

I've included my sketch for reference but if you want to try running it you'll probably need the *.h files. If so then please let me know and I'll post them here.

[The extension ino has been deactivated and can no longer be displayed.]


User avatar
User_UMjT7KxnxP8YN8
 
Posts: 323
Joined: Tue Jul 17, 2018 1:28 pm

Re: Serial.readBytes() doesn't accept byte type

Post by User_UMjT7KxnxP8YN8 »

I wrote a Nixie Clock application for a board that has a Mega 2560 and an ESP8266 on it, and I communicate between the two over a serial port. I transfer binary data between the two with code like this on the Mega side:

Code: Select all

  syncPtr = (byte*)&ESP_sync_state;
  for (i = 0; i < sizeof(ESP_sync); i++) {
    *syncPtr = (byte)Serial3.read();                      // read a byte and store it into syncState struct
    syncPtr++;                                            // increment pointer
  }
I've glossed over the synchronization of I/O processing between the two processors, but you should be able to write your own functions that send a uint32_t type one byte at a time using a similar approach. In the code above, I'm transferring a struct defined as follows:

Code: Select all

struct ESP_sync {
  uint32_t secs;
  uint32_t usecs;
  uint32_t settingsChecksum;
  bool NTPsync;
  uint8_t songCount;
  bool WiFiConnected;
  bool ESPchangedSettings;
  uint32_t syncStateChecksum;
}  __attribute__((__packed__));

ESP_sync ESP_sync_state;

User avatar
westfw
 
Posts: 2010
Joined: Fri Apr 27, 2007 1:01 pm

Re: Serial.readBytes() doesn't accept byte type

Post by westfw »

Code: Select all

byte* serialAsBytes;

void loop() {
  while (Serial.available()) {
    Serial.readBytes(serialAsBytes, 1);
  }
}
Note that this is buggy beyond any type problems, because serialAsBytes doesn't actually point to any storage. Hopefully that happened just as you were cutting down the example...

User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Re: Serial.readBytes() doesn't accept byte type

Post by nullkraft »

Yeah ;) I was trying to show that the compiler would throw an error when using Serail.readBytes(byte*, size_t) instead of Serail.readBytes(char*, size_t). My sketch is attached above if you'd like to see what is really happening.

So the Arduino reference page states the following:
Syntax
Serial.readBytes(buffer, length)

Parameters
Serial: ... serial port object. See the list of available serial ports for each board on the Serial main page.
buffer: ... the buffer to store the bytes in. Allowed data types: array of char or byte.
length: ... the number of bytes to read. Allowed data types: int.
I dug into the source code and compared the readBytes() functions in Stream.h from both Arduino and Adafruit. I hit a dead end because the two functions are identical. I don't understand why one works and the other one doesn't.

User avatar
westfw
 
Posts: 2010
Joined: Fri Apr 27, 2007 1:01 pm

Re: Serial.readBytes() doesn't accept byte type

Post by westfw »

Code: Select all

I dug into the source code and compared the readBytes() functions in Stream.h from both Arduino and Adafruit.
Aha!

Apparently the Adafruit USBCDC code has its own readBytes() function for USB in USB/USBAPI.h, but does not define a version overloaded for byte* arguments. I don't understand why the Stream.h definition of readBytes for byte* doesn't get invoked instead, and I don't understand why the Arduino samd boards seem to accept the code even though it seems essentially similar. Probably C++ issues beyond my current C++ level :-(

User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Re: Serial.readBytes() doesn't accept byte type

Post by nullkraft »

!@#$ yeah! How on earth did you find that?

Since I compared the Arduino and Adafruit Stream.h files I decided to compare the two USBAPI.h files.

It turns out that Arduino does have readBytes() in their version of USBAPI.h but they also have the byte/uint8_t version.

Code: Select all

	size_t readBytes(char *buffer, size_t length);
	size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
That was all I needed. A little copy-&-paste and Bob's your uncle. It now compiles and works as defined in the Arduino reference. I wonder if Adafruit saw the second definition and mistakenly thought it was a duplicate? Which can't be because you'd get the compiler complaining. Oh well. It's really good for me that you found it. Thanks a million. :)

Now, can anybody tell me where I might post the bug report?

User avatar
westfw
 
Posts: 2010
Joined: Fri Apr 27, 2007 1:01 pm

Re: Serial.readBytes() doesn't accept byte type

Post by westfw »

can anybody tell me where I might post the bug report?
here: https://github.com/adafruit/ArduinoCore-samd/issues

Heh. The fix for this in the Arduino "master" branch is in fact VERY recent. https://github.com/arduino/ArduinoCore- ... 94356a4782
I don't know if Adafruit is aggressive at pulling in Arduino changes, but I am not at all surprised that they don't have a 6-day out patch!
How on earth did you find that?
Might be TMI, but I really like a set of tools called the GNU Id Utils
They let you (for one) take the source code find all the occurrences of "readBytes":

> gid readBytes

Code: Select all

cores/arduino/Stream.h:96:  size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
cores/arduino/Stream.h:97:  size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
cores/arduino/Stream.h:101:  size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
cores/arduino/USB/USBAPI.h:141: size_t readBytes(char *buffer, size_t length);
libraries/Adafruit_TinyUSB_Arduino/examples/WebUSB/webusb_rgb/webusb_rgb.ino:90:  usb_web.readBytes(input, 7);
cores/arduino/Stream.cpp:204:size_t Stream::readBytes(char *buffer, size_t length)
cores/arduino/Stream.cpp:217:// as readBytes with terminator character
cores/arduino/USB/CDC.cpp:190:size_t Serial_::readBytes(char *buffer, size_t length)

User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Re: Serial.readBytes() doesn't accept byte type

Post by nullkraft »

Very nice and not TMI. I just installed and ran the gnu id utils. Wonderful!

Sorry to hit you with another request but you linked directly to the issue on the Adafruit github which was very handy, thank you. The reason I mention it was because I found myself manually scrolling through hundreds of issues. I tried github's search but no matter how I formed the query I kept getting zero results.

So how did you find the issue on github? Did you do it with github's search features?

User avatar
westfw
 
Posts: 2010
Joined: Fri Apr 27, 2007 1:01 pm

Re: Serial.readBytes() doesn't accept byte type

Post by westfw »

So how did you find the issue on github?
If you look at a single file with github, there are "history" buttons. But they turn out not to be very useful. There is also a "BLAME" button, and THAT will list changed lines of the code with tags as to which commit actually changed them...
Screen Shot 2022-02-28 at 3.27.58 PM.png
Screen Shot 2022-02-28 at 3.27.58 PM.png (63.97 KiB) Viewed 176 times
Screen Shot 2022-02-28 at 3.29.04 PM.png
Screen Shot 2022-02-28 at 3.29.04 PM.png (75.77 KiB) Viewed 176 times

User avatar
nullkraft
 
Posts: 10
Joined: Wed Feb 23, 2022 12:49 am

Re: Serial.readBytes() doesn't accept byte type

Post by nullkraft »

Ahh, I see. You used gnu id utils to identify the file and then just looked at the file on github. I was starting at the list of issues on github. Not too helpful.

Thank you again. Very much

Locked
Please be positive and constructive with your questions and comments.

Return to “Metro, Metro Express, and Grand Central Boards”