Jump to content

suggestion about the sdram usage


Recommended Posts

Posted (edited)

Dear friends,

I'm here to ask you a suggestion about the most used way to take advantage of an external SDRAM.

my target mcu is an STM32F103 with FSMC interfaced with a tft lcd controller on a side
and the other FSMC interfaced with an external SDRAM.

the gui is already working,and now I want to add some images(custom icons, etc).
I've already tried to load static images from the internal flash and it works perfectly.
The demoboard I'm using has an external 8Mbit SRAM and an SD card reader.

now I have 3 ways:
1) Use all the external SDRAM totally as HEAP and STACK transparently to the mcu.
2) Use the external SDRAM as area where load my images from the SD card at the power on.
3) other ideas? 

usually what is better to do? what do you usually do in such situation?

I don't have to put movies or something like that, but just static images, custom icons.loaded when needed by the gui.

Thanks to everybody for the opinion,

Regards,
Spectre

Edited by spectre
Posted
On 12/12/2016 at 15:55, spectre said:

1) Use all the external SDRAM totally as HEAP and STACK transparently to the mcu.

This is largely discouraged. Access to the external SDRAM is a lot slower than access to the internal SRAM. You will loose not just a bit, but tons of performance.

 

On 12/12/2016 at 15:55, spectre said:

2) Use the external SDRAM as area where load my images from the SD card at the power on.

That is theoretically possible but maybe a waste of memory. Caching images only makes sense if you frequently need to (re)draw those images. Of course, if you have the memory to spare you can always cache all images. For a finished product you'd usually convert all your images to the NATIVE image format so that there is zero CPU overhead when rendering an image (if you can spare the memory required to store the image as it will be completely uncompressed). In that case caching an image would only be helpful if the access time to the storage location of the image is a lot longer than to your external SDRAM (that would for example be the case if the file comes off an SD-Card). Other than that, caching really makes just sense if you need to redraw the same image over and over again or if it is an image format that is very CPU intensive (and slow) to decode such as PNG.

 

On 12/12/2016 at 15:55, spectre said:

3) other ideas? 

My personal recommendation in your case is to use the external SDRAM to render stuff into pixmaps. Depending on the GDISP driver that you are using, all GDISP rendering functions are directly piped through to the display controller. The exceptions are where the GDISP driver maintains a framebuffer itself and only flushes when asked to or automatically to the actual display but that will most likely not be the case in your particular setup. When you render complex things such as a complete widgets where certain parts get overdrawn and anti-aliased fonts where some pixels get over-drawn multiple times and sometimes even require pixel read-back there's a lot of access to the framebuffer which can be very slow. Pixmaps are virtual displays (dynamic and with arbitrary sizes) that allow you to render stuff in your memory and only copy the final result to the much slower framebuffer once you're finished. As a bonus benefit, you can render the same pixmap to multiple places on the same real display if your application calls for that.

Another thing to keep in mind is the memory bus bandwidth. Your display is connected to the same bus as your SDRAM. As the display controller maintains it's own framebuffer it means that you have to copy every single pixel you want to change from your own memory (either the internal SRAM or your external SDRAM in your case) to the display controller's frame buffer. The FMC interface has a maximum bandwidth and copying data form the external SDRAM to the display controller's framebuffer will be slower because of bus turn-around times and similar things. What might sound a bit confusing could be simplified to this: Using the external SDRAM which is connected to the same bus as your display will mean that the maximum frame rate you could get out of your display will be lower. You can either access the SDRAM or your display frame buffer but never the two at the same time.
However, when using pixmaps to render stuff in RAM first you'd gain additional performance because usually display controllers that maintain their own framebuffers and hook up to the FMC interface don't expose the actual framebuffer to the memory bus. Instead, you just tell the display controller whether the thing you're currently sending should be interpreted as commands or as actual pixel data and then you setup a certain window in which you will operate and after that you can send the actual pixel values. Using a pixmap doesn't have all this overhead because each pixel can be addressed directly, there are no commands that need to be passed first, no window setups and so on - each pixel is part of the memory map of your microcontroller and you can just set it to a different color value directly.
I guess it's getting confused now, what I'm trying to say is that you have to figure out what works best for you at the end. There are many factors to consider, some I left out because they are only marginally important, some I left out because I don't have a whole lot of time right now and some I left out because I forgot about them. But never the less, my advice stays the same: Use pixmaps if your application can actually benefit from them.

Right now the more important thing for you to know is that currently µGFX doesn't provide a proper memory pooling interface. What this means is that you cannot specify to gfxAlloc() where it should take the memory from. Therefore, it would be up to you to properly setup the additional memory segments in your linker script and getting the things to where you want them to be. In the particular case of pixmaps it might even require one or two lines of modification in the creation function as, when I remember correctly, it doesn't take a GDisplay* parameter that would allow you to directly pass your own object located in the external SDRAM. But I'm not sure so don't quote me on that.

Sorry for the crowded text, I wrote this over the course of several hours jumping from one meeting to another (and yes, some coffee breaks in between to be honest). Just let us know if you have any additional questions. We're happy to help :) 

Posted

Mr. Joel,
Thanks a lot for your detailed guide,very exhaustive.

I will choose the third choice you proposed, the pixmaps. it looks like a very smart way to do the things. 
ugfx_2.6\demos\modules\gdisp\pixmap but when I enable the GDISP_NEED_PIXMAP define as TRUE I get some errors like the following:

../../App/Drivers/tft/ugfx_2.6/src/gdisp/gdisp_pixmap.c(85): error:  #20: identifier "GDISPVMT_pixmap" is undefined
../../App/Drivers/tft/ugfx_2.6/src/gdisp/gdisp_pixmap.c(115): error:  #20: identifier "LLDSPEC" is undefined
etc.

I've found on the forum someone talking about the same issue but I really don't understand what pratically I have to do to fix this small issue.
Can you give me a help?

Thanks a lot

Posted

I assume you are hitting the limitation of the single-file-inclusion mechanism as noted here. In that case you'd have to either use the make build system or resort back to the good old adding-each-file-individually technique.
Note that in case of you're using our own high-level project makefiles that we supply it might be a simple case of setting GFXSINGLEMAKE to no.

If you're not using the single-file-inclusion mechanism: Make sure that you make a clean build. If it still doesn't work

Posted

Mr. Joel,

now pixmaps mechanism now works correctly.
As you suggested I will load the virtual display inside of the external sram.

I have an 8Mbit ext.sdram and a 400x240 rgb tft,
so I suppose that I will use near half of the space for the virtual display, and the rest for bmp icons,etc..

What you think?

regards,
Spectre
 

Posted

Glad to hear that you got the pixmaps working!

The required memory size can be calculated by this equation:    

mem_bits = (pixels_width * pixels_height * num_bits_per_pixel) + overhead

Note that this equation doesn't account for pixel packing and similar things (which most likely won't be an issue in your case).
So if you're using an RGB565 format you need (400 * 240 * 2) bytes of memory for a full framebuffer plus the overhead. The overhead is totally negligible though as it's just a couple of bytes. Furthermore, µGFX allows you to use different pixel/color formats for each individual display driver. As pixmaps are implemented using the real display driver interface this means that you could theoretically use a different color format for your pixmap. However, as you'd have to push the pixels from the pixmap to your physical display at some point that would mean that each pixel would need to be recalculated which is very slow and would prohibit using DMA unless you have dedicated hardware to do that.

Depending on the application you wouldn't want to have one or more full-sized pixmaps but instead you'd just have partial, context dependent pixmaps. But that really depends on what your application does and how you implement other things.

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...