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
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.
Here is what happens when I run it with a 200 microsecond delay between pixel writes.
And here is what happens when I run it without a delay.
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?
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.
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)
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.
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
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!
Or you could help Vassilis get the CDC working
Or you could help Vassilis get the CDC working
Try PMing him
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.
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.
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.
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.
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.
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.
I had to implement a PC tool for windows and a blue pill app.
The image loader shows a red filled circle on the top of the image (disconnected?).
What should I do?
The image loader shows a red filled circle on the top of the image (disconnected?).
What should I do?
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 …
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.
I added a console log line in the main.js line 70 before
if (!attached) {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);
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);
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
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.
In functions
**Edit, listed wrong function name **
uint32 usb_cdcacm_rx(uint8* buf, uint32 len) {
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 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.
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
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
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.
https://github.com/rogerclarkmelbourne/ … 85bc2a5c07
I can’t see why this commit was necessary, what problem got solved through this.
https://github.com/rogerclarkmelbourne/ … 85bc2a5c07
I can’t see why this commit was necessary, what problem got solved through this.
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.
In functions
uint16 usb_cdcacm_get_pending(void) {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.
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.
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.
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)
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 ![]()
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
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 ![]()
I’m modifying the code to read one byte at a time and see if something changes.
uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);
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
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
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).
Of course, one could optimize the code to write data to display faster.
But the point is, the USB fix works!
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
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…
Do you use the INO file I posted earlier?
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);
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);
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.
Alternatively, you could try to use the function:
Serial.read(void *buf, uint32 len);
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];
...
Alternatively, you could try to use the function:
Serial.read(void *buf, uint32 len);@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)…
@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)…
Basically, the fix is good for reading bytes one by one, but not for reading several bytes.
I used:
Serial.read(usbBuf, 60);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



![[SOLVED] Discovery STM32F100RB — Trouble with timers and library structure](https://sparklogic.ru/wp-content/uploads/2019/11/st-stm32vl-discovery-90x90.jpg)

