PSEG Length Error

I seem to get this when my code is too big
checked .mem:

   Name             Start    End      Size     Max     
   ---------------- -------- -------- -------- --------
   PAGED EXT. RAM   0xf000   0xf100     257      256   
   EXTERNAL RAM     0xf000   0xf4e1     993     3840   
   ROM/EPROM/FLASH  0x0400   0x5607   21000    29696   

seems to be plenty of ROM/EPROM/FLASH
why is PAGED EXT.RAM filling up?
and what can I do about it?

I tried splitting the code into separate files, making functions smaller
doesn’t seem to make any difference
the only thing seems to be have less code
but there seems to be so much space free?!?

cheers
Mike

Hello.

We are using SDCC’s medium memory model which means that by default global variables will be placed in PDATA, otherwise known as PSEG or Paged External RAM. Other variables are also placed in PSEG. If a function it has more than 1 parameters, it looks like some of its parameters get placed in PSEG. If a function has a local variable that can’t be stored in registers for some reason, it gets stored in PSEG. You should take a look at your .map file in the PSEG to see what is taking up all the room. Just open it up with a text editor and search for “PSEG”. Here is an example from test_radio_signal_rx.map:

ASxxxx Linker V02.00 + NoICE + sdld,  page 70.
Hexadecimal

Area                               Addr   Size   Decimal Bytes (Attributes)
--------------------------------   ----   ----   ------- ----- ------------
PSEG                               F000   0048 =     72. bytes (REL,CON,PAG,XDATA)

      Value  Global                              Global Defined In Module
      -----  ---------------------------------   ------------------------
       0D:  F000  Ftest_radio_signal_rx$lastPacketR
       0D:  F002  LreportResults$lastReportSentTime
       0D:  F004  __divuint_PARM_2                 
       0D:  F006  G$usbComControlLineState$0$0     
       0D:  F006  _usbComControlLineState          
       0D:  F007  G$usbComSerialState$0$0          
       0D:  F007  _usbComSerialState               
       0D:  F008  Fusb_cdc_acm$lastReportedSerialSt
       0D:  F009  G$usbComLineCodingChangeHandler$0
       0D:  F009  _usbComLineCodingChangeHandler   
       0D:  F00B  LusbComRxReceive$size$1$1        
       0D:  F00B  _usbComRxReceive_PARM_2          
       0D:  F00C  LusbComTxSend$size$1$1           
       0D:  F00C  _usbComTxSend_PARM_2             
       0D:  F00D  G$controlTransferPointer$0$0     
       0D:  F00D  _controlTransferPointer          
       0D:  F00F  LusbReadFifo$count$1$1           
       0D:  F00F  _usbReadFifo_PARM_2              
       0D:  F010  LusbReadFifo$buffer$1$1          
       0D:  F010  _usbReadFifo_PARM_3              
       0D:  F012  LusbWriteFifo$count$1$1          
       0D:  F012  _usbWriteFifo_PARM_2             
       0D:  F013  LusbWriteFifo$buffer$1$1         
       0D:  F013  _usbWriteFifo_PARM_3             
       0D:  F015  LusbControlRead$source$1$1       
       0D:  F015  _usbControlRead_PARM_2           
       0D:  F017  LusbControlWrite$source$1$1      
       0D:  F017  _usbControlWrite_PARM_2          
       0D:  F019  LusbInitEndpointIn$maxPacketSize$
       0D:  F019  _usbInitEndpointIn_PARM_2        
       0D:  F01A  LusbInitEndpointOut$maxPacketSize
       0D:  F01A  _usbInitEndpointOut_PARM_2       
       0D:  F01B  LboardDetectVbus$lastCheck$1$1   
       0D:  F01C  G$timeMs$0$0                     
       0D:  F01C  _timeMs                          
       0D:  F020  __divsint_PARM_2                 
       0D:  F022  _vsprintf_PARM_2                 
       0D:  F025  _vsprintf_PARM_3                 
       0D:  F029  G$usbLastActivity$0$0            
       0D:  F029  _usbLastActivity                 
       0D:  F02A  G$usbBlinkStart$0$0              
       0D:  F02A  _usbBlinkStart                   
       0D:  F037  __print_format_PARM_2            
       0D:  F03A  __print_format_PARM_3            
       0D:  F03D  __print_format_PARM_4            
       0D:  F047  __gptrput_PARM_2

To free up room in PSEG, you can move global variables, local variables, and function parameters to XDATA by adding the “XDATA” qualifier to their definitions, or you can refactor your code to have fewer function parameters and fewer local variables.

I think you can also use the __reentrant modifier on functions to put their parameters on the stack.

–David

I’d like to add that this was the main reason we couldn’t easily compile the petite fat file system for the Wixel. Almost every function starts with this line:

FATFS *fs = FatFs;

First of all, creating the fs pointer is wasteful; it uses up 3 bytes of PSEG for every function it appears in. Second of all, if you really have to create a pointer on the Wixel, then you should make it be a pointer to XDATA space instead of a generic pointer so it only takes up 2 bytes.

FATFS * fs;       // Generic pointer, 3 bytes where 1 byte specifies the memory type.
FATFS XDATA * fs;  // XDATA pointer, 2 bytes, where memory type is known at compile time.

The CC2511 has a unified memory space, which means (almost) every part of XDATA/DATA/PDATA/CODE memory can be read/written to using MOVX instructions, which is the kind of instruction SDCC uses to read or write from an XDATA * pointer. Therefore we don’t need SDCC’s generic pointers, and should try to avoid them as much as possible because they are less efficient. Unfortunately, we have to use them sometimes because the standard C library expects them as parameters to certain functions (e.g. the first parameter of printf).

–David

thanks
that very useful

off to butcher some code now!

ah
just seen your second post too
I suspect the vast amount of printf statements is what’s killing my code

very useful when debugging
managed to #define them away as I finish each library

will just have to write smaller!

just tried removing all the structure pointers in function calls
:smiley: :smiley: :smiley: bunny[happy] = true!!!

have I finally hit a wall?
it seems I can choose (well maybe not as accurate as that) to have errors in
PSEG
OSEG
or
DSEG
it’s frustrating because there is still memory spare

should I be using a different memory model?
how would I go about doing that

I did have hopes that I could run entire projects using just the Wixel
rather than using it as another xbee
it’s so close, but just out of reach!

Have you tried manually putting function parameters and variables into XDATA?

For example:

void foo(uint8 XDATA arg)
{
    uint16 XDATA bar;
    ...
}

If that’s not enough, you could try changing the Wixel SDK’s Makefile to use the large memory model. That would put all the variables in the plentiful XDATA space instead of the limited PDATA space by default, but it might break some of the Wixel library code, particularly the delayMicroseconds function which is written in assembly (but I’m not sure).

Other than that, I don’t have any specific advice. You should look at the generated assembly and get a feeling for what C statements take up RAM. Then look carefully at all of the code included in your app, making little changes to free up ram. Whenever you make a change, you should check to see how many bytes of RAM you freed up. The .map and .mem files will be useful to you. You can try deleting unused library functions or putting them in separate .c files so they don’t get linked in.

I’m curious, what are you trying to do with your Wixel? What are all the different libraries you are using and how much PDATA does each library take up? Are there any libraries or functions that are taking more than they need?

–David

Hello David
thanks for the extensive reply

what I’m aiming for is a remote control camera trigger, with sound recording
I started out coding up in an Arduino, just using the Wixel for the radio comms
then I realise dthat the Wixel is better than that
so decided to try the whole thing using just a Wixel

good news:
the camera end is working just fine

more good news:
I have implemened an SPI and an SD card interface
almost got the FAT32 filing system working too!

then I kept hitting the wall
every time I tried to add something, another segment started whinging

slept on it and had a few senior moments…

a) supporting multiple SPI devices is unlikely
so just support one

b) same for multiple SD cards
so just support one

c) which in turn means only one filing system

d) the reality is I only need one file at a time
so just support one

e) followed your example - and #define which USART to use

I think I’m now back in happy land

code works and there is space to move!

how would I implement another memory model - in case I need to go down that route?

oh - and finally
I’m surprised you guys aren’y pushing the Wixel as a standalone a bit like an Arduino
It hasn’t got quite so much RAM, but it is fairly capable

and I do like the high clock rate - hoping I can manage to sppol audio to SD card

thanks for listening
Mike

PS
I found that making everything __rentrant saved a lot
as much as I can is now in XDATA, too

You would find the part of the Makefile that says “–model-medium” and change it to “–model-large”.

The Wixel actually has twice as much RAM as the Arduino Uno: 4KB vs 2KB.

Another cool feature of the Wixel for your application is the I2S interface. If you get an I2S microphone it would free up the Wixel’s ADC to do other things and probably improve the sound quality, though I’m not sure. Personally I’ve never worked with any I2S devices and thought it would be fun to learn.

Thanks for sharing your project idea with us, it sounds cool!

–David