USB Serial to TFT image writing problem (buffer?)

primateio
Thu Oct 06, 2016 8:20 pm
I have been working on a project where I use a NodeJS program with node serialport to send image data over usb to a custom Maple Mini clone and the maple mini clone uses the Adafruit_ILI9341_STM library to write the image data to a tft screen. It works great except I have to slow it down to get it to work.

Essentially what I am doing is sending each 16 bit pixel split into 2 bytes. The maple reads the two bytes and combines them into an uint16_t and sets the pixel color using the Adafruit_ILI9341_STM and Adafruit GFX lib with dma transfer. If I add a 200 microsecond delay after each pixel set, it works great, just slower than id like. If I lessen the delay, or remove it completly, it kind of works. It appears to get through all the data but it misses a lot of bytes. The images are all distorted, but it does this process really fast. I love the speed, but not the dropped bits.

So I am digging into this, but before I look too far, I wanted to see if anyone had any ideas. I am thinking that the usb transfer is working fine, otherwise, it would overflow worse when I slow it down. (I could be wrong). I am assuming that the problem is on the dma transfer. I am not 100% sure how the dma transfer works, but my understanding is that you basically dump bytes to be transferred into a memory region (buffer) and the microcontroller transfers it in the “background”. Is this correct? If it is, I am assuming that the memory region, or buffer, for the dma transfer is overflowing making bytes coming in through UBS to get lost or overwritten in the buffer.

I have been scratching my head on this for a few days. Any help or ideas would be appreciated.

UPDATE

I made a program to demonstrate the problem.
https://github.com/jaretburkett/Arduino … age_Loader


martinayotte
Thu Oct 06, 2016 8:38 pm
I think you first need to isolate the issue by figuring out if it is on the USBSerial side or the SPI side.
Maybe you can print on Serial port the bytes count of the received data, with and without your added delays.
If it is the same, then the issue is most probably on SPI side.
If not, maybe USBSerial is loosing some received bytes.
In such case, maybe you can add a handshaking protocol in your transfer, even maybe a CRC check.

primateio
Fri Oct 07, 2016 3:33 am
Thanks martinayotte. I ran some tests. I am getting The right amount of bytes from the usb at full speed. It is also writing the correct amount of bytes to the tft screen (the image is the right size).

Here is what happens when I run it with a 200 microsecond delay between pixel writes.

Image

And here is what happens when I run it without a delay.

Image

As you can see, it appears to get all the pixels. Some of the 16bit codes have the MSB and LSB inverted, and groups of the pixels are in the wrong space, but at the end. It is exactly the right amount of bytes for the full image. I was just about to say that it looks like a call stack like in javascript that the calls are getting put in the wrong order. Well, I am running nodeserial from javascript to push the images to the maple, so it makes me think that might be the problem, but the whole image is put into a buffer and dumped to the port, and no one from there seems to have this issue. I am not ruling it out, but It is not my first place to look as the changes to make it work are all done on the Maple not on the nodejs script. Any ideas?


stevestrong
Fri Oct 07, 2016 4:15 am
In another project i had similar problems with large amount of bytes sent by blue pill to pc.
The issue was most likely caused by usb serial tx overflow, although the number of sent bytes, just like in your case, was correct.
As martinayotte suggested, handshacking did the trick.

RogerClark
Fri Oct 07, 2016 5:27 am
You could probably change the core to allocate more bytes to the USB serial buffer, which may be enough to write one screen buffers worth of pixels without any delay

Or perhaps read out of the USB serial buffer more quickly and implement a buffering scheme, between the incomming USB data and the data to the screen.

Doing single pixel writes to the screen is very inefficient,and slow.

You may be better off sending either whole lines of areas of the screen, so that the display lib and do things in a more optimal way and make use of DMA (albeit blocking DMA)


primateio
Fri Oct 07, 2016 1:37 pm
RogerClark wrote:You may be better off sending either whole lines of areas of the screen, so that the display lib and do things in a more optimal way and make use of DMA (albeit blocking DMA)

martinayotte
Fri Oct 07, 2016 2:08 pm
I don’t think there is any buffer overrun somewhere, otherwise the bytes count would be erroneous.
To prove that, maybe you should try sending a defined pattern for the whole scan line and check if the pattern is broken at reception.
If pattern is not broken, but still inverted/swapped on the display across different scan lines, this means the swapping corruption is the transfer to LCD.

ahull
Fri Oct 07, 2016 3:33 pm
You could also generate the data programatically for the whole image, i.e. send a checkerboard of data based on the output of a couple of for loops. This would eliminate the USB side of things completely.

primateio
Fri Oct 07, 2016 3:58 pm
ahull wrote:You could also generate the data programatically for the whole image, i.e. send a checkerboard of data based on the output of a couple of for loops. This would eliminate the USB side of things completely.

RogerClark
Fri Oct 07, 2016 8:02 pm
have you just tried sending a incremented counter via usb and just read it via usb, as it would be easy to see if its dropping bytes etc.

primateio
Sat Oct 08, 2016 6:06 am
RogerClark wrote:have you just tried sending a incremented counter via usb and just read it via usb, as it would be easy to see if its dropping bytes etc.

RogerClark
Sat Oct 08, 2016 6:27 am
OK
I’ve not sent a lot of data to the device, I’ve only used it to send back data to the PC
Thats always worked fine, albeit, it goes faster if you don’t send newlines. I’m not sure why it slows down if you send a newline too often e.g. intially I was sending some numbers as text separated by tabs, so I could paste the data into a speadsheet

I was sending X,Y,Z acceleration then a newline, but this was slow, so I ended up sending
X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z
X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z,X,Y,Z

(which was much faster albeit, i had to process the data to turn it back into

X,Y,Z
X,Y,Z


primateio
Sat Oct 08, 2016 1:52 pm
I have now ruled out it being a problem with node serialport, within a degree of certainty. What I did was console log the byte array for the image. I then wrote a python script using pyserial. I copied the byte array in there and sent it using pyserial. I am getting absolutely identical results. Works great with a small delay. Scrambled without one.

stevestrong
Sat Oct 08, 2016 2:04 pm
I also had issues with NodeJS serial from HTML and Javascript, so I finally abandoned that.
Instead, I wrote my small utility program in Processing which, among other things, sends and receives the data to/from maple mini over serial.
More flexible and, which is more important: more reliable!

primateio
Sat Oct 08, 2016 7:44 pm
Update: I decided to try the same sketch with the Teensy. It works flawlessly at full speed. First I’m going to check how teensy is using the ILI9341 library and edit it if needed. If that is not the problem I’m going to look at porting the teensy cdc to the STM32, or at least some of it. I’m really hoping the problem lies in the ILI9341 lib because rewriting the cdc will be a much bigger project and i know many people would not want to make such a major modification to the core in the repository, understandably.

RogerClark
Sat Oct 08, 2016 7:52 pm
If the problem is the CDC you could wait for Vassilis to finish adding CDC to the new STM core, as that uses the official STM CDC
Or you could help Vassilis get the CDC working

primateio
Sat Oct 08, 2016 7:54 pm
RogerClark wrote:If the problem is the CDC you could wait for Vassilis to finish adding CDC to the new STM core, as that uses the official STM CDC
Or you could help Vassilis get the CDC working

RogerClark
Sat Oct 08, 2016 8:03 pm
I dont think so.

Try PMing him


stevestrong
Sat Oct 08, 2016 8:06 pm
One could try increasing the size of the usb serial Rx buffer on maple mini.
Reason: the nodejs serial may send the bytes as pairs of bytes, but those will be first grouped to a larger pack by the serial driver and then sent.
That means that there are always more than 2 bytes comming from the pc. If the buffer is smaller than this byte number, overflow will happen, although the byte count may be correct.

primateio
Sat Oct 08, 2016 8:45 pm
stevestrong wrote:One could try increasing the size of the usb serial Rx buffer on maple mini.
Reason: the nodejs serial may send the bytes as pairs of bytes, but those will be first grouped to a larger pack by the serial driver and then sent.
That means that there are always more than 2 bytes comming from the pc. If the buffer is smaller than this byte number, overflow will happen, although the byte count may be correct.

stevestrong
Sun Oct 09, 2016 9:14 am
If you could share some code for blue pill and some PC tool how to reproduce, I would be glad to double-check.

primateio
Sun Oct 09, 2016 2:14 pm
There is a ton of code on both sides. The image loading is a tiny part of it, but I can throw together a complete pc code/arduino tft image loading project pretty quick and open source it on github. Give me a few hours and i’ll post back with a link.

primateio
Sun Oct 09, 2016 5:08 pm
Here is a link to a quick program I whipped up. It is a simple image loader. It should open a program with an image section and browse button. It looks for the STM32 serial port based on vid pid. There is a circle on the top that turns green when connected and the image box is automatically adjusted. You will have to have nodeJS. Instructions are on the readme. It is currently set with the delay. Information on removing the delay is in the readme. You can remove it and add it to try both so you can see what I am talking about.

https://github.com/jaretburkett/Arduino … age_Loader

Let me know if you have an install issue. I can walk you through it. Should work on Mac, Win, Linux. Linux, you need the maple udev rules, but you have probably already done that if you are using Arduino on there.

Edit: I am using my custom port of the AdafruitILI9341, but it should work with the one in the STM32duino repo as well. I just run an updated version of it. It should also work with any TFT screen/lib combo that uses the Adafruit GFX lib.


stevestrong
Tue Oct 11, 2016 8:52 am
Well, I am not a Linux friend, so I could not use your environment.
I had to implement a PC tool for windows and a blue pill app.
On the STM32 side there is a command interpreter which receives commands over USB serial to handle the display driven by Adafruit lib (8 bit parallel) adapted to STM32 (posted in one thread).
On the PC side there is a Processing-based sketch which generates some of those commands.
So, I open a picture with Processing, and send the pixel data to the pill.
In my test I converted the picture to grayscale to send only one byte per pixel. However, these bytes were sent one by one without any delay, no buffering on the Processing sketch side, just read from image pixel buffer and send it directly to the serial port.
The pill receives the bytes, converts them one by one (as received) to color565 format (two bytes) and writes them to the display using the pushColors() function.

Results:
I tried two resolutions.
1. 100×100 pixels (bytes) sent in less then 1 second, all pixels displayed correctly.
2. 240×320 pixels (bytes) sent in less then 7 seconds, all pixels displayed correctly.

I ran the tests several times, each time without any misplaced pixel.
As you can see, I could not reproduce your problem.


stevestrong
Tue Oct 11, 2016 11:58 am
Now that I compare my comment and your information, I realized that the problem my be the endianess of the received data.
It my happen in your case that, on the PC side, the bytes are collected and transmitted by the USB serial driver in packets consisting of several bytes.
But the number of bytes in a packet can vary. If it is odd, the endianess of the received and processed bytes can be disturbed…

I will check in my application to send the pixel data in color565 format (two bytes per pixel).
Alternatively, you could also try to send the pixel data in grayscale (1 byte per pixel) format and convert it with the STM32 chip.


primateio
Tue Oct 11, 2016 2:18 pm
stevestrong wrote:Now that I compare my comment and your information, I realized that the problem my be the endianess of the received data.
It my happen in your case that, on the PC side, the bytes are collected and transmitted by the USB serial driver in packets consisting of several bytes.
But the number of bytes in a packet can vary. If it is odd, the endianess of the received and processed bytes can be disturbed…

I will check in my application to send the pixel data in color565 format (two bytes per pixel).
Alternatively, you could also try to send the pixel data in grayscale (1 byte per pixel) format and convert it with the STM32 chip.


primateio
Tue Oct 11, 2016 2:39 pm
stevestrong wrote:Well, I am not a Linux friend, so I could not use your environment.
I had to implement a PC tool for windows and a blue pill app.

stevestrong
Tue Oct 11, 2016 4:51 pm
The .exe runs, opens an image, the LCD displays black background showing “Waiting for Image from USB”, but then nothing else happens.
The image loader shows a red filled circle on the top of the image (disconnected?).
What should I do?

primateio
Tue Oct 11, 2016 5:13 pm
stevestrong wrote:The .exe runs, opens an image, the LCD displays black background showing “Waiting for Image from USB”, but then nothing else happens.
The image loader shows a red filled circle on the top of the image (disconnected?).
What should I do?

primateio
Tue Oct 11, 2016 5:32 pm
Ok, You just need elevated permissions for some reason. Ill work on a fix, but for now, you can run the program as administrator.

stevestrong
Tue Oct 11, 2016 5:37 pm
OK, I restarted the PC and it seems to work now.
I can see sporadic pixel group errors, just like yours. In one line, consecutive ~20 pixels are wrong.
In my case, the error is there although the delay is still active.

EDIT
Hm, it did work only for one session. I removed the delay, and now if If I close the loader, at next start the circle goes green for a second, then it turns and stays red.
The TFT detects the connection, and the background turns and stays black. But no data transmission takes place.

I will now modify my software to check the 2 byte/pixel version.

EDIT 2
A power cycle (go to standby and wake up) and restart the loader helps the loader to stay green.
With the removed delay, the picture is uploaded in a second! WOW! But, unfortunately, totally distorted …


primateio
Tue Oct 11, 2016 6:18 pm
Thanks for all the effort. I really appreciate it. And sorry my program is still buggy, I kind of just threw it together real quick to demonstrate the issue. I pushed an update so you dont have to reparse the image every time. I just updated the release. I am not having the need to restart issue so I am not sure how to fix that. Any idea what could be gong on here? There seems to be some blank pixels sometimes at the bottom, but it is not just a pixel or two getting off. It is a whole line (around 20 px), that seems to get moved around and distorts the whole process.

stevestrong
Tue Oct 11, 2016 6:28 pm
primateio wrote:There seems to be some blank pixels sometimes at the bottom, but it is not just a pixel or two getting off. It is a whole line (around 20 px), that seems to get moved around and distorts the whole process.

RogerClark
Tue Oct 11, 2016 7:30 pm
primateio wrote:stevestrong wrote:Now that I compare my comment and your information, I realized that the problem my be the endianess of the received data.
It my happen in your case that, on the PC side, the bytes are collected and transmitted by the USB serial driver in packets consisting of several bytes.
But the number of bytes in a packet can vary. If it is odd, the endianess of the received and processed bytes can be disturbed…

I will check in my application to send the pixel data in color565 format (two bytes per pixel).
Alternatively, you could also try to send the pixel data in grayscale (1 byte per pixel) format and convert it with the STM32 chip.


stevestrong
Tue Oct 11, 2016 9:56 pm
I looked a bit to the loader app, it seems that it tries to open COM4 several times consecutively, and of course, it fails from the second time, since it was opened at the first time. That’s why I see the circle in green only for one second.
I added a console log line in the main.js line 70 before if (!attached) {

stevestrong
Tue Oct 11, 2016 10:36 pm
OK, I think I have found the bug.
In your sketch for STM32 you are reading two consecutive bytes from serial, but you are not checking before whether serial byte is available or not.
So what happens is that you are reading invalid bytes form serial.
If you insert the delay, new bytes become available during that time, so that even if you don’t check availability, the bytes are most probably available, ready to be read.
I changed your code:

for (uint16_t y = 0; y < tft.height(); y++) {
for (uint16_t x = 0; x < tft.width(); x++) {
while ( Serial.available()<=0 ); // wait till byte is available
b1 = Serial.read(); // MSB
while ( Serial.available()<=0 ); // wait till byte is available
b2 = Serial.read(); // LSB
// combine bytes to a 16 bit
uint16_t pixColor = b1 << 8 | b2;
tft.drawPixel(x, y, pixColor);


primateio
Tue Oct 11, 2016 10:51 pm
I think I know what is going on. I have the scan running in an interval. So it forces another scan before your scan is complete if it takes longer than a second, then hell breaks loose. I just pushed a new release and updated the repo so it sets a timeout scan AFTER it is done scanning. Should fix your issue. Sorry about that. It is the old programmer problem “well it works on my system” ha ha. I appreciate you working out the bugs in my crappy loader app so you can see the issue.

primateio
Tue Oct 11, 2016 10:59 pm
stevestrong wrote:OK, I think I have found the bug.
In your sketch for STM32 you are reading two consecutive bytes from serial, but you are not checking before whether serial byte is available or not.
So what happens is that you are reading invalid bytes form serial.
If you insert the delay, new bytes become available during that time, so that even if you don’t check availability, the bytes are most probably available, ready to be read.
I changed your code:

for (uint16_t y = 0; y < tft.height(); y++) {
for (uint16_t x = 0; x < tft.width(); x++) {
while ( Serial.available()<=0 ); // wait till byte is available
b1 = Serial.read(); // MSB
while ( Serial.available()<=0 ); // wait till byte is available
b2 = Serial.read(); // LSB
// combine bytes to a 16 bit
uint16_t pixColor = b1 << 8 | b2;
tft.drawPixel(x, y, pixColor);


stevestrong
Tue Oct 11, 2016 11:05 pm
primateio wrote:So this worked for you without the delay?

stevestrong
Tue Oct 11, 2016 11:20 pm
I checked the update, unfortunately is still trying to open twice the serial port:

main.js:76 Device Found:
main.js:77 {"comName":"COM4","manufacturer":"Microsoft","pnpId":"USB\\VID_1EAF&PID_0004\\6&7F0CE88&0&2"}
main.js:76 Device Found:
main.js:77 {"comName":"COM4","manufacturer":"Microsoft","pnpId":"USB\\VID_1EAF&PID_0004\\6&7F0CE88&0&2"}
main.js:89 Error: Error {message: "Opening COM4: Access denied"}
main.js:90 Device Error


stevestrong
Wed Oct 12, 2016 12:01 am
If you say that with Teensy it was working without delay and without checking serial available, this means that the STM32 USBCDC is much slower than the Teensy USBCDC.

I decided to toggle a pin at tft pixel write to see how often is this called.
Well, using my Processing tool, the data is written evenly distributed in time. In the first 11..12 ms the average pulse distribution was at each 400microsecs, afterwards it was at each ~150microsecs till the end of transmission. This explains why your delay (150microsecs !) made the thing work, without loosing bytes.

Now the question is: why Teensy USB serial reception is faster than this?

In the same context, the DFU upload speed for STM32 also seems to be much higher than this.


primateio
Wed Oct 12, 2016 12:06 am
It appears to be having an error opening at that point. Are you running as administrator?

primateio
Wed Oct 12, 2016 2:13 am
I GOT IT. But it comes with a problem. I had to change 2 lines in the usb_cdcacm.c file. I am now writing the entire screen in about 1 second. The two lines changed are the same code in 2 places.

In functions
**Edit, listed wrong function name **
uint32 usb_cdcacm_rx(uint8* buf, uint32 len) {


stevestrong
Wed Oct 12, 2016 9:43 am
I’ll try this change today later on.

primateio wrote: The simple work around is the while loop for serial not available. But if you don’t put it on quick reads, you will miss bytes.


primateio
Wed Oct 12, 2016 11:46 am
stevestrong wrote:I’ll try this change today later on.

primateio wrote: The simple work around is the while loop for serial not available. But if you don’t put it on quick reads, you will miss bytes.


rexnanet
Wed Oct 12, 2016 1:17 pm
I’m trying to load images to a Flash (SST26) via Serial port using (modified) SerialFlash and the Python script included in the extras but I was also facing some data loss.

After some trial and error I’ve finally decided to creat a sketch and a python script to test the serial connection.
I’m trying to send 4000 bytes at a time to the STM32 but I only get 39xx most of the times.
Tried to set the baud rate to a lower speed (115200) but the problem persists.
Maybe I’ll try the USB CDC code fix posted here…

serial_python_test_STM32.ino
(7.83 KiB) Downloaded 160 times

primateio
Wed Oct 12, 2016 1:37 pm
rexnanet wrote:I’m trying to load images to a Flash (SST26) via Serial port using (modified) SerialFlash and the Python script included in the extras but I was also facing some data loss.

After some trial and error I’ve finally decided to creat a sketch and a python script to test the serial connection.
I’m trying to send 4000 bytes at a time to the STM32 but I only get 39xx most of the times.
Tried to set the baud rate to a lower speed (115200) but the problem persists.
Maybe I’ll try the USB CDC code fix posted here…

serial_python_test_STM32.ino


rexnanet
Wed Oct 12, 2016 1:48 pm
I don’t have any issues with the flash now. I’ve made the support for it and tested it and it works fine.
The display also works fine, no issues there.
So I wen’t and started to see if the info was arriving correctly to the STM32.

I had to modify the original code from rawfile_uploader.py because the way it processed the “escape” bytes that would change some bytes and “corrupt” the image. I’ve changed the “end loop condition” to receive the number of bytes corresponding to the file size instead.

But I wasn’t getting the full file size on the STM32 although the python script said it had sent them all.

So I made this small test and found that there really is a problem somewhere on the serial communication path.

Ok, thanks for the help.


stevestrong
Wed Oct 12, 2016 1:57 pm
It looks like the part of code you changed back was committed on 25 Jan 2015 to the repo.
https://github.com/rogerclarkmelbourne/ … 85bc2a5c07
I can’t see why this commit was necessary, what problem got solved through this.

primateio
Wed Oct 12, 2016 2:08 pm
stevestrong wrote:It looks like the part of code you changed back was committed on 25 Jan 2015 to the repo.
https://github.com/rogerclarkmelbourne/ … 85bc2a5c07
I can’t see why this commit was necessary, what problem got solved through this.

stevestrong
Wed Oct 12, 2016 4:31 pm
I can acknowledge: applying the proposed change the USB serial Rx data rate increased considerably.

Console log from Processing:

Serial port COM4, 115200, 8, 'N', 1 opened successfully.
W240;
H320;
W240;
H320;
> sending 76800 image pixels ...
filling buffer with pixel data...(153600 bytes in 46 millis) done.
sending buffer ...(1079 millis) done.
> image transmission done.


rexnanet
Wed Oct 12, 2016 5:44 pm
primateio wrote:

In functions uint16 usb_cdcacm_get_pending(void) {

rexnanet
Wed Oct 12, 2016 5:49 pm
stevestrong wrote:I can acknowledge: applying the proposed change the USB serial Rx data rate increased considerably.

stevestrong
Wed Oct 12, 2016 6:02 pm
I have attached the used sources.

The INO file must be adapted to the used TFT library.

The Processing PDE sketch starts with displaying the woof picture. You should click on it and press two times “0” (zero) (check the console window).
Then press “s” for the transmission of the image to pill.


RogerClark
Wed Oct 12, 2016 8:14 pm
I will action the PR later.

BTW.

It may be worth contacting Tim, who did the PR which introduced the problem, as he may remember what bug was fixed.

There was probably a thread on the forum about this, perhaps someone could search on Tim’s postings to see if it sheds any light on things.


stevestrong
Wed Oct 12, 2016 9:17 pm
Roger, i can only find this thread:
http://forum.arduino.cc/index.php?topic=265904.1200
but i could not identify the problem behind.

Also, i cannot find any (open or closed) PR related to this.


RogerClark
Wed Oct 12, 2016 10:26 pm
Steve

I suspect I had to manually merge Tim’s files.

I’ll PM him via the Arduino forum as I don’t know if Tim ever registed on this forum. (He’s definitely not active on it now)


rexnanet
Wed Oct 12, 2016 10:29 pm
The “fix” had no effect on my setup :(

Surprisingly USB seems to like less delay between block transfers.
If I put a sleep (on the python side) of 0.1sec between 128 byte frames (to give time to save data to flash when it gets to 4kbytes) data transfer hangs after a few blocks (about 2K total). But if I send them all together (only a print between them) it gets to 152K (only a few hundreds less than the 153600 bytes of the image size).
Still some bytes are missing… And I don’t know which and why with this setup.

@stevestrong Thanks! I’ll have a look at it :)


RogerClark
Wed Oct 12, 2016 10:34 pm
It looks like Tim has not posted on Arduino.cc for over a year.

I can’t recall if he has an account here, as people don’t need to give their real names. All I can access is email add and often people use cryptic gmail addresses

Anyway, he may reply to my PM on Arduino.cc


RogerClark
Wed Oct 12, 2016 10:36 pm
rexnanet wrote:The “fix” had no effect on my setup :(

Surprisingly USB seems to like less delay between block transfers.
If I put a sleep (on the python side) of 0.1sec between 128 byte frames (to give time to save data to flash when it gets to 4kbytes) data transfer hangs after a few blocks (about 2K total). But if I send them all together (only a print between them) it gets to 152K (only a few hundreds less than the 153600 bytes of the image size).
Still some bytes are missing… And I don’t know which and why with this setup.

@stevestrong Thanks! I’ll have a look at it :)


rexnanet
Wed Oct 12, 2016 10:45 pm
The first thing I noticed is that you use Serial.read() reading a byte at a time while in SerialFlash the whole buffer is read each time.

I’m modifying the code to read one byte at a time and see if something changes.


rexnanet
Wed Oct 12, 2016 11:16 pm
I don’t believe it!!!!!!!!!!!!!!!!!!!!!!!!!!!

uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);


RogerClark
Wed Oct 12, 2016 11:58 pm
Looks good

BTW.

Are you guys using DMA to the display yet?

I know its currently blocking, but it would be relatively easy (I hope) to add non-blocking DMA, so as long as you can send at least 1 line at at time to the display, its going to be significantly faster than non DMA

Even blocking DMA is faster, because its not wasting time (lines of C code) checking the SPI status reg’s


primateio
Thu Oct 13, 2016 1:58 am
RogerClark wrote:Looks good

BTW.

Are you guys using DMA to the display yet?

I know its currently blocking, but it would be relatively easy (I hope) to add non-blocking DMA, so as long as you can send at least 1 line at at time to the display, its going to be significantly faster than non DMA

Even blocking DMA is faster, because its not wasting time (lines of C code) checking the SPI status reg’s


RogerClark
Thu Oct 13, 2016 3:47 am
Writing individuals has a massive overhead, because from what I recall the X, Y of each pixel needs to be transferred to the display followed by the pixel data (colour).

The code is not at all optimised and aside from having to send probably 3 times as much data as needed to the display, the code would also have multiple call overheads etc etc.

I’d definitely recommend that you send whole lines at a minimum, and if you have enough ram, send multiple lines, (though its going to be diminishing returns as you increase the number of lines).


stevestrong
Thu Oct 13, 2016 8:33 am
I am using the Adafruit_TFTLCD_STM32 lib, works with 8 bit parallel.
Of course, one could optimize the code to write data to display faster.
But the point is, the USB fix works!

rexnanet
Thu Oct 13, 2016 8:46 am
RogerClark wrote:Looks good

BTW.

Are you guys using DMA to the display yet?

I know its currently blocking, but it would be relatively easy (I hope) to add non-blocking DMA, so as long as you can send at least 1 line at at time to the display, its going to be significantly faster than non DMA

Even blocking DMA is faster, because its not wasting time (lines of C code) checking the SPI status reg’s


stevestrong
Thu Oct 13, 2016 9:38 am
rexnanet wrote:
But, regarding USB fix, for me it didn’t impact the results. Even when I was reading the whole buffer at a time. Maybe python script is slower than the Processing code and I can’t see this problem…?
With Python I got around 30KB/s. This equals the max. baud rate of 250000bps I see on the dropdown options, so must be pretty close to full USB serial speed…

rexnanet
Thu Oct 13, 2016 9:57 am
stevestrong wrote:
Do you use the INO file I posted earlier?

stevestrong
Thu Oct 13, 2016 10:34 am
@rexnanet,
can you say that the fix has an (any) effect on your system?
Please pay attention to send data in large blocks. Can the python script send data in large blocks?

Btw, the INO is originating from @primateio, I just added the wait for serial available before serial read byte.

rexnanet wrote:
uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);


primateio
Thu Oct 13, 2016 11:29 am
stevestrong wrote:@rexnanet,
can you say that the fix has an (any) effect on your system?
Please pay attention to send data in large blocks. Can the python script send data in large blocks?

Btw, the INO is originating from @primateio, I just added the wait for serial available before serial read byte.

rexnanet wrote:
uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);


rexnanet
Thu Oct 13, 2016 12:51 pm
stevestrong wrote:@rexnanet,
can you say that the fix has an (any) effect on your system?
Please pay attention to send data in large blocks. Can the python script send data in large blocks?

Btw, the INO is originating from @primateio, I just added the wait for serial available before serial read byte.


stevestrong
Thu Oct 13, 2016 2:04 pm
Hmmm, I have to check this.

Alternatively, you could try to use the function:
Serial.read(void *buf, uint32 len);


primateio
Thu Oct 13, 2016 2:25 pm
rexnanet wrote:
With data loss:
//We assume the serial receive part is finished when we have not received something for 3 seconds
while(Serial.available() || (lastReceiveTime + 10000 > millis()) ){
uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);
if (available){
lastReceiveTime = millis();
}
Serial2.print("available:");
Serial2.println(available);

for (uint16_t usbBufferIndex = 0; usbBufferIndex < available; usbBufferIndex++){
uint8_t b = usbBuffer[usbBufferIndex];
...


rexnanet
Thu Oct 13, 2016 2:58 pm
stevestrong wrote:
Alternatively, you could try to use the function:
Serial.read(void *buf, uint32 len);

primateio
Thu Oct 13, 2016 3:20 pm
rexnanet wrote:
@primateio Ok, but isn’t that handled by “available”? If I only get 1 byte available I would only read 1 byte to “usbBuffer” and will only process that byte.
And then wait for the next byte(s)…

rexnanet
Thu Oct 13, 2016 4:08 pm
primateio wrote:rexnanet wrote:
@primateio Ok, but isn’t that handled by “available”? If I only get 1 byte available I would only read 1 byte to “usbBuffer” and will only process that byte.
And then wait for the next byte(s)…

stevestrong
Sun Oct 16, 2016 2:46 pm
There is some new development on this topic, also added here.
Basically, the fix is good for reading bytes one by one, but not for reading several bytes.
I used:
Serial.read(usbBuf, 60);

primateio
Sun Oct 16, 2016 4:31 pm
I would think the issue would be in the Serial read into a buffer function. Since, all it is doing is reading one byte at a time into a buffer, I’ll look into it.

stevestrong
Thu Oct 20, 2016 3:19 pm
Just as info, I posted here a new version of the USB serial file, where I also added buffered Tx functionality.

rasmus
Sat Oct 22, 2016 1:59 pm
The error occurred because of a race condition with the NVIC_USB_LP_CAN_RX0 interrupt, which only occurred during high-bandwidth transfers.

It is corrected in:
https://github.com/rogerclarkmelbourne/ … 6fabb3092c

I have posted a PR.

The tx-buffer work by stevestrong seems like a good idea, but I think my rx-buffer fix is the way to go. Comments are welcome.

Regards
Rasmus Friis Kjeldsen


Leave a Reply

Your email address will not be published. Required fields are marked *