Jump to content

Well supported TFT controller + OS for STM32F103?


phofman

Recommended Posts

Hallo,

I really appreciate this incredible open-source work, thanks a lot.

I am new to ARM (STM32) development, coming from the simple arduino world. I am working on a DIY audio appliance controlled by a touch screen and am looking for a well-supported combination of TFT controller and underlying OS for 4"-7" inexpensive TFT, running on inexpensive maple mini clone (STM32F103xx). The actual audio will run on a small PC, this is for the control display and a bit of control functions.

I think for STM32F103 the only viable connection is SPI. For this TFT mid size I found out that the only controller supporting SPI is RA8875 (?). I think I would use the resources offered by ChibiOS but  this thread talks about very inefficient SPI implementation in ChibiOS.

Please may I ask for recommendation of well supported and tested combination STM32F103 + TFT 4-7" controller (usually not available with the ILIxxxx family) and the underlying OS? I do not know if bare metal would be appropriate as I would need at least threads. These TFTs cost more than a few dollars and I do not want to order stuff which will not be usable.

Thanks a lot for any suggestions/recommendations.

Best regards,

Pavel.

Link to comment
Share on other sites

The answer is that uGFX works really well with a wide range of hardware. There may be many factors that will govern the right controller for your circumstances. I will list some of those factors below...

1. Cost. Quantity production runs can mean a few cents saved per board add up to big numbers. For one-off projects there are still cost constraints but they are typically less of an issue.

2. Size (or rather display resolution). A higher resolution display requires a faster bus interface to get the same apparent performance and will typically cost more than a small display. 

3. Whether integrated touch is required.

4. Availability. You can only use what you can get. Note for production runs this can get very complex, lead times for supply might be important, and life of supply might be important. 

5. Required performance. Doing video will require a much faster controller and bus technology than simple 2d windows.

6. Available pin count. There is no point going for a display with a 16 bit parallel interface if your cpu only has 5 spare pins.

7. Available RAM. Some controllers require the user provide a framebuffer. Some controllers have a built-in framebuffer. If the user has to provide a framebuffer that RAM is then not available for application use. There may also be bandwidth considerations for the cpu in managing that framebuffer.

8. Required capabilities. Some controllers with embedded framebuffers do not allow you to read back information from the framebuffer. uGFX still works well in those circumstances however certain features are not available eg anti-aliased fonts on a non-filled background, scrolling etc

There are lots of other factors too.

From your discussion above, a couple of pointers may help...

1. A SPI interface is much slower than a 8 or 16 bit parallel interface. The required pin count is however much less. This is particularly important for larger displays for the reasons stated above.

2. Unless you want to add external RAM to your project for a framebuffer you should almost certainly be looking for a controller chip with its own embedded framebuffer.

3. Some controller chips can operate in more than one mode eg spi/8bit/16bit or external/internal framebuffer. The lcd module you buy will usually be hardwired to operate in a particular mode with no ability to change it. Make sure you get not only the controller you want but also that controller configured in the way you want to use it. Often the choice of the lcd module is what drives all the other decisions.

The above discussion is of course very generic. Knowing more about what you are trying to achieve and what your budget is, or a list of lcd modules you are thinking of, could help us give more specific advice.

Link to comment
Share on other sites

If you only want one or two, ST do some Discovery boards which include a small TFT.

An FSMC interface is certainly helpful on speed; to give you an idea, decoding and displaying a .GIF file on an 800x480 display using F4, 16-bit FSMC, SSD1963 takes of order half a second. Its also worth considering the F7; I saw 25-30% speed improvement.

The ST Nucleo series are well worth looking at as a convenient way of getting a CPU on a usable board; and there are often pin-compatible boards with different processors on them (some F4s, and F7, for example)

Link to comment
Share on other sites

One thing I'd like to add is the availability of hardware acceleration: Some display controllers provide hardware acceleration. Many (such as almost all of the SSD family) only provide hardware acceleration for rectangle drawing but that already brings a huge performance improvement when using µGFX. When sticking to your STM32F103 choice and not using a proper parallel interface (FSMC) I would strongly recommend picking a display controller that supports at least hardware rectangle drawing / area filling. This is basically a "must have" in my opinion. The performance benefits are immense.
Other than that other display controllers such as the RA8875 also provide hardware accelerated polygon drawing and similar which can further speed up your GUI and free CPU resources.

I guess @steved and @inmarket mentioned all the other important factors.

Link to comment
Share on other sites

I found the general info in this thread very useful indeed.

I've mostly used larger RA8875 based TFT's, and for smaller displays various SSD/UC based displays. Almost always SPI (once, I2C). Decisions usually due to pin counts and on the smaller pin count MCU's that is a big factor. Yet when using MCU's where the pin count is measured in the hundreds (with decent amount of memory, storage and clock speeds etc) inertia & familiarity has kept me on the SPI/I2C wagon. 

The usual tricks of a fast SPI clock, "transactions" DMA etc are all useful techniques of course. However perhaps it's time to look at 8 (or even 16) pin parallel.

I really spent any time thinking that the performance difference would be so great. You imply it is... and I believe you.

I (and no doubt others) would greatly appreciate if more detailed info could be provided... benchmark numbers, a feature comparison of various controllers etc.

Of course that is a massive ask so it would need to be greatly simplified and perhaps added to over time. Key things such as which primitives are hardware accelerated (with the minimum being rectangle perhaps).

 

Link to comment
Share on other sites

There are 2 operations that the most critical for acceleration; a rectangular fill and a display memory copy. The display memory copy is really only useful for window scrolling but makes a huge difference in performance for that operation. The rectangular fill is of much more general use.

Note that when talking about acceleration some controllers will provide "accelerated" operations that can be slower than the cpu doing the unaccelerated operation. Sometimes they will be faster for slow busses such as spi because of the reduction in bus transfers but slower than the cpu using parallel transfers. Also some controller accelerated operations (such as arbitrary line draws) are simply of no advantage because uGFX can't use them.

What the conclusion of the above means is that a controller providing an accelerated operation does not always mean it makes sense for it to be used in a uGFX driver.

Link to comment
Share on other sites

Hello @Jim and welcome to the µGFX community,

The performance improvements from using a parallel instead of a serial interface can be calculated very easily - no magic behind that. As for other techniques it's a lot more complicated as mentioned by @inmarket. It starts by the fact that using DMA doesn't necessarily speed up anything. It just frees the CPU to do other things in the mean time.

I put writing a guide about all these things on our ToDo list. I'll guess we'll best get started by simply adding @inmarket's post to the wiki and extend from there over time.

Link to comment
Share on other sites

Hello guys, thanks a lot for all your comments. This great community is why I would like to use the open source toolkit as opposed to the closed-source ones.

To be specific - I am building a grown-up version of my player https://github.com/pavhofman/plabs-player/wiki where the display is dirt-cheap arduino mini + SPI TFT. This time I want to use touch screen with more complicated GUI (some radio buttons, perhaps virtual keyboard for text input). No video, maybe some small image icons, nothing moving. However vertical scrolling longer lists of tracks is needed. Display size around 5", resolution is not critical. Reasonably fast screen refresh (< 100ms?). Font aliasing would be nice.

No production runs, single quantities. Since the project is specifically aimed at minimum cost (small $100s total), I am really looking at an economy solution.

Please would parallel 8bit ILI9488 hooked to cheap non-FSMC STM32F103C (e.g. blue pill) cut the corner? Specifically I am looking at inexpensive but sufficiently large 4.6" touch screen https://www.aliexpress.com/store/product/4-63-inch-16-9-272-480-TFT-screen-with-Resistance-touch-and-PCB-panel-LCM/1726252_32802272563.html. Please what is the current status of hardware acceleration support for the ILI9488 or other controllers in uGFX? Actually I did not find any rectangle-fill function in its datasheet.

Or do you think even for such simple task it is worth going for the more expensive SSD-based TFT with HW acceleration? Still I cannot find any HW-accel code for SSD1963 in https://git.ugfx.io/uGFX/uGFX/src/master/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c, do I have to complete it first?

Please what is more convenient - HW acceleration controller (actually supported by the existing driver) with plain 8bit or even SPI interface or no acceleration (likely the current status?) with fast but more expensive ($10 more) FSMC interface?

Please do not take the questions about HW acceleration support as a complaint, I am just trying to learn current situation and find a reasonable solution (even if it involved me having to add the missing code to uGFX based on some other supported controller (I am a newbie in coding TFT drivers :-) ). Thanks a lot for your insight.

Edited by phofman
Link to comment
Share on other sites

Don't be concerned about hardware acceleration for 2 reasons; 1. You are not doing any particularly heavy graphics processing, and 2. Bus speed is typically far more important than acceleration in these types of devices.

That display listed looks likely to be a good choice although there are a couple of things to check...

1. It seems to have both a SPI interface (a cpu SPI port + 2 extra cpu control pins) and an 8 bit interface. Using the 8 bit interface (12 cpu pins needed) will obviously be faster than SPI but how do you configure the display to use that inferface over the SPI interface? There may be a jumper on the lcd board to configure it. You will need to ask the manufacturer or reverse engineer it from the board traces.

2. Is that controller chip supported by uGFX (i can't currently check for you as i am on my phone).

Link to comment
Share on other sites

Note: FMSC is a STM32 cpu facility that makes a block of cpu pins act as a parellel bus with programmable timings. It is not a slave device bus type but a way for the cpu to create a bus from gpio pins.

It is not essential, anything that can be done with a FMSC interface can be done with gpio pins directly. It is not even necessarily faster. What it does provide is more accurate timing than gpio "bit bashing" and it (very slightly) simplifies the code to access the device at the expense of a more complicated initialisation sequence. That is, FMSC is a nice feature in a cpu but definitely not mandatory or even important. 

Link to comment
Share on other sites

inmarket, thanks a lot for your important information. According to the LCD vendor (rather active chinese manufacturer/reseller ruija) the TFT is based on ILI9486. That chip is currently not supported by uGFX directly. The datasheet is freely available on internet http://www.displayfuture.com/Display/datasheet/controller/ILI9486L.pdf , would it be difficult to add to uGFX? Perhaps it is similar to the already supported ILI9488.

I will ask about the interface support, IMO it is parallel 8bit (optimal for my case). Please what kind of interface is supported in the current ILI9488 driver? How can I configure assignment of the individual GPIOs?

I very much appreciate your help.

Link to comment
Share on other sites

7 hours ago, inmarket said:

Don't be concerned about hardware acceleration for 2 reasons; 1. You are not doing any particularly heavy graphics processing, and 2. Bus speed is typically far more important than acceleration in these types of devices.

While I agree with this I'd like to point out that the support for rectangle drawing / area filling is a huge performance booster when using a slow interface such as SPI. uGFX uses solid filled rectangles wherever possible because they are often supported by the display controller. Many drawing operations are broken down to area filling wherever possible to take advantage of this.
Keep in mind that when you have a GUI where you have multiple display pages (different "views" / pages with completely different widgets on them, basically like menus) you have to clear the display when switching between them. This means that the entire display needs to be filled with a solid color -> rectangle filling. When the hardware doesn't support this your CPU has to do it. This means that your CPU needs to manually set width * height pixel values. When using an interface such as SPI this will be anything but fun.

 

2 hours ago, phofman said:

That chip is currently not supported by uGFX directly. The datasheet is freely available on internet http://www.displayfuture.com/Display/datasheet/controller/ILI9486L.pdf , would it be difficult to add to uGFX? Perhaps it is similar to the already supported ILI9488.

It's very easy to add support for new display controllers - especially as these are almost always very closely related to each other (often just differences in the maximal resolution).

 

2 hours ago, phofman said:

I will ask about the interface support, IMO it is parallel 8bit (optimal for my case). Please what kind of interface is supported in the current ILI9488 driver? How can I configure assignment of the individual GPIOs?

You can use any interface you want. The µGFX GDISP driver doesn't care about that. That is what the board files are there for. You configure your microcontroller's peripherals and GPIOs in the board_init() function in the board file.
On a side note: +1 for using the 8-bit parallel interface instead of SPI.

Link to comment
Share on other sites

Joel, I very much appreciate your help. Currently I am discussing the LCD details with the seller - it is not going easy, so far I have been given three different answers :-)

I  found a tested combination for reasonable price (https://www.aliexpress.com/item/5-0-inch-HD-IPS-TFT-LCD-module-resistance-touch-with-PCB-adapter-board-854-480/32666829945.html ,https://www.aliexpress.com/item/1pcs-STM32F103C8T6-ARM-STM32-Minimum-System-Development-Board-Module-For-arduino/32653883227.html ) with arduino driver available https://github.com/ZinggJM/GxTFT/blob/master/GxIO/GxIO_STM32F103C8T6_P16_TIKY/GxIO_STM32F103C8T6_P16_TIKY.h  . But the LCD is high-resolution 854x470 which I am afraid will be too slow on ILI9806 without the rectangle fill acceleration (even though it runs over 16bit parallel) - somewhere I read about 300ms for screen fill which seems visually slow to me.

Thanks a lot.

Link to comment
Share on other sites

You can make an estimation as 854 x 470 x 2 bytes/pixel / 2 bytes per cycle (16 bit bus) x cycle time. Note the cycle time can be estimated from the cpu speed (allow say 20 instructions per cycle) and the maximum speed of the display controller bus.

Note in practice, except for video, 300ms per full screen would be perfectly acceptable performance. 

Link to comment
Share on other sites

Given my own question a few posts/days back I just thought I'd take a look at the ILI9486L controller mentioned to see how fast (in theory) 16bit was in the above Use Case vs SPI.

So 854px * 470px * 16bit colour depth = 802,760 bytes

However the datasheet says the ILI9486L is a 320x480 controller so not sure if things have changed in the last week or so? In anycase the clock timings are fairly typical so I suppose as an exercise the following isn't completely useless....

Parallel

I see on page pp212 of the datasheet  that the Parallel Clock Cycle (write) has a minimum of 50ns with 15ns high/low pulses also. (there are other timings, but they seem to over & underlap those so are superfluous I think?)

So that gives:

8080 Parallel (16bit) = 6,422,080 bits in 16 bit bursts = 401,380 bursts (of 16 bits per burst aka parallel) * 50ns (1 * 15ns + 15ns setup but subject to a minimum write cycle of 50ns) = 20.069 ms

SPI

Of course there isn't a theoretical SPI clock speed, just limited by the MCU and display controller but ~16MHz (~63ns) on the controller side seems to be a theme in many.

I see on pp214 of the datasheet  that the SPI Clock Cycle (write) has a minimum of 66ns with 15ns high/low pulses & 15ns setup time.

SPI = 6,422,080 bits in 16 bit bursts = 401,380 bursts (of 16 bits) * 255ns (16 * 15ns + 15ns setup) = 102,352 ms

Conclusion

Assuming I'm correct (and some of those 0ns minimum timings seem suspect to me. There may be "waits" between bursts that need factoring in?), then in this Use Case 16bit parallel is five times faster than SPI. That makes sense as I see from anecdotal forum posts that 16bit parallel is about 5 times faster. 8bit parallel would be 2-3 times faster. Gut feeling says that's about right to me.

With a display controller that can accept faster SPI then the gap would narrow of course.

(Whilst I do have a Logic Analyser I don't have that MCU nor display controller so can't double check understanding of datasheets personally). 

I'm sure Joel/Inmarket/others will point out the flaws in the working out (please do!) :D

 

Link to comment
Share on other sites

Worth adding that if my maths is right (give or take) then the 16bit parallel gives a very healthy 50fps... even assuming there are some other timings to be added in and that drops to 30-40fps then that's still very good for full screen video at a relatively high resolution.

 

Link to comment
Share on other sites

You have not taken chip-select times into account. Many display controllers require you to pull high the CS line after a frame has been transmitted to reset their internal byte counter. This allows for a much simpler statemachine and therefore a smaller & cheaper chip. The parallel interfaces don't have these constrains which mean that you can usually keep the CS low for as long as you want given that there are no other bus members. Although this is just a matter of toggling a GPIO it's still going to take some time. You have to pull it low prior to start sending data and pull it back up to high once you finished. While the µGFX board files usually inline those functions there are still several nested function calls required to perform a GPIO toggle so the time you loose is definitely not negligible. I do have a logic analyzer screenshot at the office that I took a few days back, I'll post it here tomorrow. The delays you get from that are unfortunately large (like 25% to 50% of the actual frame transmission time).
The reason I have that screenshot is because I ran exactly into that issue where the CS line was not being toggled between transmissions which lead to corrupt data.

I have worked with many different setups in the past couple of years and I assure you that your 16-bit FSMC will be more like 30 times faster than you SPI. Also keep in mind that 16-bit FSMC is more than twice as fast as 8-bit FSMC as you don't have the additional setup & settling times between the two bytes.

Additionally I'd like to point out that many (not sure about this one) display controllers allow for a faster bus speed when using the parallel instead of the serial interface.

Link to comment
Share on other sites

17 hours ago, Jim said:

However the datasheet says the ILI9486L is a 320x480 controller so not sure if things have changed in the last week or so?

That linked 854x480  LCD has ILI9806 which is not added to uGFX yet but has a working driver for arduino environment.

https://github.com/ZinggJM/GxTFT/blob/master/GxCTRL/GxCTRL_ILI9806/GxCTRL_ILI9806.cpp

Edited by phofman
Link to comment
Share on other sites

@Jim: Here's the screenshot:

 deleteme.png.64b66ed5a2965a08f73cb0e553bb7ff0.png

This is with manually controlling the CS line because the used SPI module didn't provide the necessary functionalities to satisfy the needs (or rather requirements) of the display controller. It would be better if the SPI peripheral would handle the CS but you'd still loose a significant amount of time which you didn't take into account in your calculations.

Link to comment
Share on other sites

Good old Saleae.

Thanks for the follow up info.

Ah, so a software SPI like on some of the vanilla Arduinos. I see, yes that wouldn't be very efficient at all.

So really there are at least three categories: Software SPI Hardware SPI & Parallel (not counting I2C and variations of Parallel of course).

I suppose it would be interesting if you could do a screenshot, under the most similar circumstances you can, from an MCU with hardware SPI. Just so those looking in the future and coming across this thread can see the info for themselves? (or this goes into the Wiki).

Edited by Joel Bodenmann
Removed unnecessary quote of complete previous post
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...