|
|
View previous topic :: View next topic |
Author |
Message |
batacarco
Joined: 23 Apr 2014 Posts: 5
|
Why there is not enough space on the RAM? PIC18F4550 |
Posted: Tue Apr 29, 2014 6:25 pm |
|
|
I have this program in which I want to draw a circle on a GLCD and show word "circle" in the virtual USB port. However, it does not compile because it has not enough RAM for variables. I visited the site and I http://www.todopic.com.ar/foros/index.php?topic=27379.0 regards pic18_usb.h driver I have to use only the endpoints needed to release the reserved space in USB RAM, but I have version 4.125 and the code is not the same.
What should I do to optimize the RAM?
Here's the code:
Code: | #include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#define FAST_GLCD // Try commenting this out to see the differences
#include "HDM64GS12.c"
#include "graphics.c"
//#include <math.h>
//#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7)
//#use fast_io(C)
#include <stdio.h>
#include "usb_cdc.h"//Siempre va antes del include usb_desc_cdc.h
#include "usb_desc_cdc.h"
//#include "usb_bootloader.h"
void main() {
usb_cdc_init();
usb_init(); //inicializamos el USB
//enable_interrupts(global); // Habilita interrupciones
usb_task();
usb_wait_for_enumeration();//Esta linea espera hasta que el usb esté conectado
while (true)
{
if(usb_enumerated())
{
if (usb_cdc_kbhit())
{
printf(usb_cdc_putc,"CIRCULO");
glcd_init(ON); // Must initialize the LCD
glcd_circle(64, 32, 24, NO, ON);
glcd_update();
}
}
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Apr 30, 2014 2:30 am |
|
|
Realistically, save RAM, and don't use FAST_GLCD....
The problem is the transfer buffers for USB. USB reserves a lump of the RAM in the PIC equivalent to nearly 1KB of the available RAM on this chip. So your chip drops from having 2KB of useable RAM, to 1KB as soon as USB is enabled. This 'lost space' is not shown in the 'memory used' by the compiler (since it is not variables as such). Now FAST_GLCD, requires a 1KB buffer, but also a few dozen extra bytes are used for addressing, and in the functions. If you compile the graphic library on it's own, with FAST_GLCD enabled, the amount of memory needed jumps up by about 1.05KB (about 53%). The USB code itself uses about 24% of the RAM, so to compile both together in your chip, you need:
50% (USB buffers)
24% (code variables etc.).
53% (for FAST_GLCD).
127% total.....
Doesn't fit.
Now it is annoying that the compiler doesn't tell you about this 'hidden loss', but it is inherent in the way the USB hardware works. If you look at the data sheet, this is the figure 'Implementation of USB RAM in data memory space'. They show the area used as 0x400 to the top of RAM.
Basically you can reckon that as soon as you load the USB drivers, just over half the memory of this chip is 'in use'. As such with only 2KB to begin with, just less than 1KB for other things. Since FAST_GLCD requires 1KB just for it's buffer, you can tell at the start it isn't going to fit.
You either need to not use FAST_GLCD, or switch to a chip with more RAM.
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Wed Apr 30, 2014 5:12 am |
|
|
Another possible option is to use a USB<->TTL module instead of the internal USB peripheral.For the $2 cost of the module you eliminate the USB driver and gain 1K of RAM. As well, you gain about 1/3 of the code space back.As I recall the USB drivers take up a lot of code space.From a hardware view you need a USB connector anyway,so you save a bit there as well.
I've used 'generic' USB<--->TTL modules for years, never had any issues either hardware or software.The ones I use have LEDs for power and data.I remove the power LED as it's too bright and wastes energy.Another advantage is the same module can be used with ANY PIC.
just an option
Jay |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Apr 30, 2014 7:29 am |
|
|
complete solidarity with Mr. temtronic here.
every instrument i design with a PIC core uses a communication bridge circuit, that offers simultaneous USB and RS-232 connectivity.
an FTDI chip for the USB portion, MAX232 for RS-232 and a single quad AND gate for the connectivity "bridge".
the PIC connects via its TTL level ports to the bridge.
Each port talks and listens to the other two.
my business partner, on the fabrication side standardized the circuit to a tiny module that mounts on the back panel and offers the USB port and a choice of male or female DB-9.
my communication decisions consist of the
#USES rs232 statement in CCS code.
IN the 4550 too much code and ram space is chewed up by the USB function from the "get go"
So long as you are creating a slave device design , I can't see
why anyone bothers with the misery of PIC imbedded USB at all.
just my 2.5 cents worth....
dp
Last edited by asmboy on Wed Apr 30, 2014 4:57 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Apr 30, 2014 2:37 pm |
|
|
I use chips with USB a lot. Thing is that for anything over perhaps a dozen units, it is a lot cheaper, and uses less board space.
However I hardly use the 4550 at all. The internal USB, is much better suited to chips with a lot more RAM. Tend to use the x6J50, or one of the PIC24's.
An understanding of just how much space you use, says immediately, that to do anything worthwhile you need a bigger chip....
Best Wishes |
|
|
batacarco
Joined: 23 Apr 2014 Posts: 5
|
|
Posted: Tue May 06, 2014 6:30 pm |
|
|
Thank you all,
Ttelmah: I understand that part of the GLCD I can not reduce RAM, however Will there be any way to reduce USB RAM buffer? (perhaps reducing the number of endpoints or redirecting memory spaces) This idea rely on the code pic18_usb.c and the url (http://www.todopic.com.ar/foros/index.php?topic=27379.0).
Temtronic, I understand that adding the FTDI not use RAM space for USB, but my idea was not to add it, but if the other option is not so I will, but my project was communicating with an RS232 to USB converter cable so I feel would come to the same.
Ttelmah, I was looking at the datasheet of the PIC18F46J50, PIC18F47J53 and I see that the RAM is 3.8k, which cover my requerimentos but want to see if there is even the possibility to optimize the RAM to not replace the PIC18F4550.
I was trying to reduce RAM and USB endpoints in this part of the driver code pic18_usb.c
Code: | #define __USB_4550__
#define USB_TOTAL_RAM_SPACE ((unsigned int16)0x400)
#define USB_RAM_START 0x400
#define USB_NUM_UEP 16
#define USB_LAST_ALLOWED_ENDPOINT 16 |
By moving this line:
Code: | # define USB_RAM_START 0x400 |
by :
Code: | # define USB_RAM_START 0x426 |
Move the USB RAM 426h and 545H to compile the program with 73 % RAM, however, did not see anything on the GLCD or no data in the Virtual COM .
Could you give me an idea? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Tue May 06, 2014 6:36 pm |
|
|
divide and win !!
break your program down into the 'graphics task' and the 'serial communications'.
Use good old 'RS-232' and see if the graphics task actually works. This eliminates the huge USB demand for RAM.
Once this step is done, then you KNOW the 'graphics' works fine....
As for the USB section, again, I'd add a simple USB<->TTL module, then prove serial communications works.
Once you've proven that ,then try to get the onboard USB to function.
hth
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed May 07, 2014 1:36 am |
|
|
You can reduce it a small bit.
There is an option in the USB 'USB_OPT_FOR_ROM'. Set this to false before loading the USB drivers, and it'll slightly reduce the RAM usage, but use more ROM. However not much. Only a couple of percent, and this isn't going to help for you. It's useful when an existing project just 'scrapes' over size.
They turned down the number of endpoints and space used on this chip around 2009. For exactly this reason. If you compile with old compilers, the use is worse than with the current ones. They actually already re-use the RX and TX buffer, and cut to three endpoints automatically....
The problem is that I can't see you reducing the space that much. I suspect with a lot of work, you could probably save a few hundred bytes. However at present you don't even have much graphics code actually being used, and even if you could reduce the overall sizes to 'squeeze it in', as soon as you start actually sending stuff to the display, the code size will shoot up again....
Temtronic's comment is spot on. Build your graphic code without the USB. See how big it is.
However I realise the error message is misleading!....
The compiler doesn't actually run out of RAM!....
The reason it has problems is the 'monolithic' nature of the displayData buffer. A single 1KB 'lump'. The location of the USB buffer is fixed by the hardware, and there isn't quite enough space to fit the buffer either below it, or above it. Looking at the GLCD code, it's very easy to split this to use two separate arrays. There are six locations where it talks to 'displayData'. Just change these so that instead of 'displayData.Right', and 'displayData.left', it talks to 'displayDataLeft', and 'displayDataRight', and change the array declaration to two separate arrays.
unsigned int8 displayDataleft[512];
unsigned int8 displayDataRight[512];
Just done this, and the code compiles with 74% RAM usage!.
I realised what was happening, when I compiled with the array reduced in size, and looked at the symbol table.
With the #define USB_OPT_FOR_ROM FALSE, this drops to 73% |
|
|
batacarco
Joined: 23 Apr 2014 Posts: 5
|
|
Posted: Wed May 07, 2014 6:18 pm |
|
|
Ttelmah
I understand that i need to split into 2 parts (1Kb) so i have to put 512 on the left side and one on the right.
Originally located in the CCS this code:
Code: | #ifdef FAST_GLCD
struct
{
unsigned int8 left[512];
unsigned int8 right[512];
} displayData;
#endif |
And I think that every talk is the following (actually two talks)
Code: | void glcd_fillScreen(int1 color)
#ifdef FAST_GLCD
{
unsigned int8 data;
unsigned int8 *p1, *p2;
unsigned int16 i;
p1 = displayData.left;
p2 = displayData.right;
data = 0xFF * color;
for(i=0; i<512; ++i)
{
*p1++ = data;
*p2++ = data;
}
}
#else |
I do not understand what I should change?
I get the impression that is already done.
what´s your opinion, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Thu May 08, 2014 1:27 am |
|
|
I've already told you what needs to change.
A bit of understanding....
The declaration:
Code: |
struct
{
unsigned int8 left[512];
unsigned int8 right[512];
} displayData;
|
Declares a _single_ displayData structure, containing two arrays.
One structure, one block in memory.
You have to change this to two separate arrays. So:
Code: |
unsigned int8 displayDataLeft[512];
unsigned int8 displayDataRight[512];
|
And the accesses have to change to talk to the separate arrays:
Code: |
p1 = displayDataLeft;
//instead of
p1 = displayData.left;
//etc..
|
Six places where the arrays are accessed, instead of six structure accesses.
The 'point' of the structure is it gives one nice block. Ideal for keeping things together, but we need to keep the stuff apart.....
It's like the difference between two onions, tied together with a piece of string, and two separate onions. We need to cut the string, so the compiler can deal with two separate entities. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|