Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 10:54 26 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MM+ E100 with "Not enough memory"

     Page 1 of 5    
Author Message
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 12:35am 26 Apr 2021
Copy link to clipboard 
Print this post

Hi Everyone,
I'm writing a large program with multiple Pages for the MM+ E100. To save time in the debug-and-download cycle, I am writing this 1 or 2 Pages at a time, and debugging them separately, before then adding them into the full program.

Pre the latest 2-Page addition, the current program ran OK. Post addition, I now have a "Not enough memory" error.

This error is occurring right at the beginning of the code, where I make a Comms Check between the E100 and its partner - an Explore 28 module. The newly added code has nothing to do with this initial check - nor would have been run at this point.

Looking at memory :-
Pre-addition after Comms Check :-
Flash:
 67K (69%) Program (2539 lines)
  1K ( 1%) 1 Embedded C Routine
 28K (30%) Free

RAM:
 41K (45%) 417 Variables
 31K (33%) General
 19K (22%) Free

and Post-addition on error:-
Flash:
 76K (79%) Program (2958 lines)
  1K ( 1%) 1 Embedded C Routine
 19K (20%) Free

RAM:
 43K (47%) 470 Variables
 42K (46%) General
  6K ( 7%) Free

Prior to this error, the E100 sends a "Comms Check" command to the E28, which is echoed back successfully. It appears that the error is in building the next message to send - a 25 random-character string. The error message is :-

[1355] Tx_Str$="0"+Str$(t_msg_len%,2,0,"0")+t_msg_type$+t_msg_remain$+Space$(25-t_msg_len%)
Error : Not enough memory

Can anyone help me with identifying what memory is lacking here, as the manuals don't have this information.

With best regards, Paul.
Nothing so constant as change.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5901
Posted: 02:19am 26 Apr 2021
Copy link to clipboard 
Print this post

Try breaking that line up into smaller bites to see which part is causing the error.

It 'should' work as is but hard to diagnose with only the one line to go on.

You could also put a MEMORY command in just before the faulting line.

Jim
VK7JH
MMedit   MMBasic Help
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 08:24pm 26 Apr 2021
Copy link to clipboard 
Print this post

Hi TassyJim,
Thanks for your reply. The initial message "Comms Check" uses the error-ing line in my "Tx()" sub successfully.
Inserting "Memory" immediately before the offending line :-

For the "Comms Check" message :-

    Flash:
      76K (79%) Program (2959 lines)
       1K ( 1%) 1 Embedded C Routine
      19K (20%) Free

    RAM:
      42K (46%) 468 Variables
      43K (47%) General
       6K ( 7%) Free

For the next (error) message :-
    Flash:
      76K (79%) Program (2959 lines)
       1K ( 1%) 1 Embedded C Routine
      19K (20%) Free

    RAM:
      43K (47%) 470 Variables
      45K (49%) General
       3K ( 4%) Free

[1356] Tx_Str$="0"+Str$(t_msg_len%,2,0,"0")+t_msg_type$+t_msg_remain$+Space$(25-t_msg_len%)
Error : Not enough memory

And back at the command prompt :-
> memory
    Flash:
      76K (79%) Program (2959 lines)
       1K ( 1%) 1 Embedded C Routine
      19K (20%) Free

    RAM:
      43K (47%) 470 Variables
      42K (46%) General
       6K ( 7%) Free
>

Splitting the error-ing line such as :-
       Tx_Str$="0"+str$(t_msg_len%,2,0,"0")+t_msg_type$
       Tx_Str$=Tx_Str$+t_msg_remain$+space$(25-t_msg_len%)
or as :-
       Tx_Str$="0"
       Tx_Str$=Tx_Str$+str$(t_msg_len%,2,0,"0")
       Tx_Str$=Tx_Str$+t_msg_type$
       Tx_Str$=Tx_Str$+t_msg_remain$
       Tx_Str$=Tx_Str$+space$(25-t_msg_len%)

The pre-addition program works fine with these mods.
The post-addition version woun't even run the initial "Comms Check" message now, with messages scrambled.

I'm wondering, if with free RAM at 3K, this simply isn't enough for the interpreter to function ? ( I imagine its demands on RAM are quite dynamic as it processes program lines, especially dealing with strings.)

With regards, Paul.
Nothing so constant as change.
 
disco4now

Guru

Joined: 18/12/2014
Location: Australia
Posts: 844
Posted: 09:31pm 26 Apr 2021
Copy link to clipboard 
Print this post

  Bowden_P said  I'm wondering, if with free RAM at 3K, this simply isn't enough for the interpreter to function ? ( I imagine its demands on RAM are quite dynamic as it processes program lines, especially dealing with strings.)


I think you have it. It does need some RAM to work with while interpreting the code.
I think you will need to try to free up some RAM in your code.
Putting strings into an array so you can set the length less than 255 can help.
Latest F4 Latest H7
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 10:08pm 26 Apr 2021
Copy link to clipboard 
Print this post

Hi disco4now,
Thanks for the array suggestion. I wondered about that one too, and will have to seriously work out how to economize on RAM usage. The problem I see with putting variables into string arrays is losing the meaningful names for them! ( i.e Tx_Str$ replaced by Str_Array$(17) or something.)

It's a real shame that the LENGTH option doesn't apply to single string variables. I would use that a lot if it did. Would that be possible as an enhancement to MMBasic ?

Another option I thought of is to use DIM and ERASE where a variable is only needed in a section of code. At the moment almost all of my variables are declared at start-up. I use a fair number of LOCAL vars in subs, but that might benefit from expanding too.

My ideal solution would be an MM+ E100 with the MM Extreme chip on board. I use both CLICK sockets in my project, the 5" touch screen and micro SD socket, so the Backpack format of the E100 suits me very well.

I wonder - is anyone considering this as another MM standard ?

With regards, Paul.
Nothing so constant as change.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5725
Posted: 10:12pm 26 Apr 2021
Copy link to clipboard 
Print this post

Always use the LENGTH option when dimensioning strings and keep them as small as practicable, otherwise they will all be 256 bytes long. This is especially true with string arrays - they can guzzle memory.

Line 1355 will need enough space for each individual portion of the RHS plus the sum of them to execute. That might be adding up to more than you have available.

Can you use some FUNCTIONs with local variables to get rid of some of the complexity? That would force some of the variables to be reused. You can still maintain values as STATIC for subsequent calls, not everything has to be global.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5725
Posted: 10:21pm 26 Apr 2021
Copy link to clipboard 
Print this post

DIM a$ LENGTH n  is valid. It doesn't have to be an array.
I always DIM k$ LENGTH 1 for use in INKEY$ loops. :)

It's not worth using LENGTH on a single string variable unless the length is less than 16 bytes as you won't save memory.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 10:40pm 26 Apr 2021
Copy link to clipboard 
Print this post

Hi Mixtel90,
Yes, the LENGTH option use is stressed in the "Getting Started" manual by Geoff, and I have used it for string arrays.

Could you expand on your suggestion of using FUNCTIONs ? I have not used them to date, and would welcome some guidance on how they might apply here, especially on how they might reduce RAM usage!

I have used SUBs with arguments however, and found the passed-by-reference feature quite useful.

With regards, Paul.
Nothing so constant as change.
 
disco4now

Guru

Joined: 18/12/2014
Location: Australia
Posts: 844
Posted: 10:43pm 26 Apr 2021
Copy link to clipboard 
Print this post

Are you programing offline with MMEdit or are you using the MMBasic editor.
If using MMEdit then the #REPLACE directive from here  might help to use string arrays and keep it readable.
eg.

#REPLACE TX_STR$  SA$(17)
#REPLACE RX_STR$  SA$(18)
Latest F4 Latest H7
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3015
Posted: 11:09pm 26 Apr 2021
Copy link to clipboard 
Print this post

  Mixtel90 said  DIM a$ LENGTH n  is valid. It doesn't have to be an array.

It's valid as syntax, but it has no effect on memory allotment except on arrays. Consider:

Dim string a length 1
Dim string b length 1
Dim string c length 1
Dim string d length 1
Dim string e length 1
Dim string f length 1
Dim string g length 1
Dim string h length 1
Dim string i length 1
Dim string j length 1
Dim string k length 1
Dim string l length 1
Dim string m length 1
Dim string n length 1
Dim string o length 1
Dim string p length 1
Dim string q length 1
Dim string r length 1
Dim string s length 1
Dim string t length 1
Dim string u length 1
Dim string v length 1
Dim string w length 1
Dim string x length 1
Dim string y length 1
Dim string z length 1
memory

RAM usage:    8K ( 7%) 26 Variables

Dim string a length 255
Dim string b length 255
Dim string c length 255
Dim string d length 255
Dim string e length 255
Dim string f length 255
Dim string g length 255
Dim string h length 255
Dim string i length 255
Dim string j length 255
Dim string k length 255
Dim string l length 255
Dim string m length 255
Dim string n length 255
Dim string o length 255
Dim string p length 255
Dim string q length 255
Dim string r length 255
Dim string s length 255
Dim string t length 255
Dim string u length 255
Dim string v length 255
Dim string w length 255
Dim string x length 255
Dim string y length 255
Dim string z length 255
memory

RAM usage the same:    8K ( 7%) 26 Variables

Dim string a(26) length 1
Memory

RAM usage: 1K ( 1%) 1 Variable

I don't have an E100, so this is on an F4, but I think behavior is the same across micromites.

~
Edited 2021-04-27 09:13 by lizby
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 12:24am 27 Apr 2021
Copy link to clipboard 
Print this post

I have just done a similar experiment on my E100, with the same conclusion, unfortunately.
i.e. As per the manual the LENGTH option doesn't reduce RAM usage for single string variables, only string arrays.

With regards, Paul.
Nothing so constant as change.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5725
Posted: 07:46am 27 Apr 2021
Copy link to clipboard 
Print this post

Interesting...
The manuals for both the Micromite and the CMM2 appear (to me anyway) to suggest that LENGTH works on simple strings. I must admit I hadn't actually tested it.
Although it looks messy you could still set up a single dimension length-limited array for short strings though. It might be worth it to save memory.

Another approach is to poke into strings. It needs some thought, but it can work really well. Providing you aren't going to output the string or process it in any way (only use it for storage) you can poke it with all characters - even invalid ones. :)


My point with using Functions is that, unlike Subs, they can return a value.

Function add$(a$,b$,c$)
add$ = a$+b$+c$
end function

a$, b$ & c$ act like variables but are local to the function.

a$ = add$("A","B","C") will set the global variable a$ to "ABC"

All the memory space used by a$, b$ and c$ was cleared when the function closed, without affecting any global variables of those names.

Calling the same function again with

b$ = add$(str$(1),str$(2),str$(3)) will make b$="123" and release all the used memory again, including that used by the string conversions.

The less global variables you have the better really. While not in use they simply sit there using up RAM.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5725
Posted: 07:57am 27 Apr 2021
Copy link to clipboard 
Print this post

Ah - found the bit about LENGTH not working with non-array strings in the Micromite manual. Sorry! :)

It does work on the CMM2 but doesn't save memory unless the length is less than 16 bytes, in which case it improves performance too.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3015
Posted: 11:27am 27 Apr 2021
Copy link to clipboard 
Print this post

Re gaining more memory, if you have a lot of flags (1-bit variables which will occupy 8 bytes on the micromite (maybe 4 bytes on some of them)), you can save space using Captain Boing's Fruit of the Shed bit manipulation routines.

They don't save any execution time, and generally aren't worth the trouble if you have enough memory, but if you have 9 flag variables, you could save 2K by using them (with 64-bit integers). If you have 17 of them, you could save 4K.

~
Edited 2021-04-27 21:27 by lizby
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 08:09pm 27 Apr 2021
Copy link to clipboard 
Print this post

Hi disco4now Mixtel90 and lizby,
Thanks for all your posts.
Yes disco4now, I use MMEdit almost exclusively for program preparation, so the #REPLACE feature looks to be very useful for me. Keeping the code readable in the PC environment is a must, but losing some readability if I use the MMBasic editor will be worth it - I have put lots of time into this project, and don't want to leave it incomplete now.

Mixtel90 - I'll have to check if FUNCTION usage can help too. Thanks for the examples.

The flag manipulation coding is interesting, lizby. I have 67 flags used in 380 odd places and know the RAM they are using is out of proportion to the data stored! I will look at Captain Boing's code for that. I don't quite follow your saving figures however - 9 flag vars will use 72 bytes, 17 - 136 bytes. I guess you save where the name is concerned!

Time for some study !!

In the past I have cut down name lengths with beneficial effect on Flash usage, but till now left the "_" characters in. i.e t_msg_len%,t_msg_type%, which I find aids readability. Perhaps time to consider removing these, especially with Globals, where I capitalize the first letters. i.e Tx_Str$ to TxStr$. I use all lower case for LOCALs, so this scheme is more awkward there. Usage must run into several thousands !

With all compromises, gains in one place result in losses elsewhere !

In case you were wondering what this "project" is - its a Thrust Meter for measuring the performance of motors for model aircraft, be they electric, I.C. or turbine, but primarily electric.

With regards, Paul.
Edited 2021-04-28 07:00 by Bowden_P
Nothing so constant as change.
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3015
Posted: 09:07pm 27 Apr 2021
Copy link to clipboard 
Print this post

  Bowden_P said  I have 67 flags used in 380 odd places and know the RAM they are using is out of proportion to the data stored! I will look at Captain Boing's code for that. I don't quite follow your saving figures however - 9 flag vars will use 72 bytes, 17 - 136 bytes.

Ah, you're right--I had the 256-bytes per string variable stuck in my mind.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5725
Posted: 09:37pm 27 Apr 2021
Copy link to clipboard 
Print this post

The actual usable length of a string is 255 bytes. There is one byte allocated to storing the string length.

If you are prepared to do some jiggery pokery it's quite possible to use every bit of a string as a flag. Even if you use 1 byte per flag (easy if you poke strings) that's 255 flags stored in one string.
a$="" is just a simple 256-byte string
you can do things like
poke VAR a$,100,1  to set the 100th byte of a$ to 1
p=peek(VAR a$,100) will return the value of the 100th byte

Variable names affect how fast your code runs! MMBasic scans the name from the left character (I think it's in groups of 2 characters - Peter did mention it somewhere), so it's not good to use something like screen01 and screen02 as variables, it's faster to use sc1screen and sc2screen as it requires less searching to find them.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 3839
Posted: 09:56pm 27 Apr 2021
Copy link to clipboard 
Print this post

  Mixtel90 said  ... If you are prepared to do some jiggery pokery it's quite possible to use every bit of a string as a flag ...


You can also use INTEGER arrays (or FLOATs if that floats your boat), each element of the former being 8 bytes.

Option Base 0
Dim a%((200 \ 8 ) - 1) ' Array of 200 bytes
Poke Var a%,100,1      ' Set the 100th byte of a% to 1
p = Peek(Var a%, 100)  ' Return the value of the 100th byte


  Quote  Variable names affect how fast your code runs! MMBasic scans the name from the left character (I think it's in groups of 2 characters - Peter did mention it somewhere), so it's not good to use something like screen01 and screen02 as variables, it's faster to use sc1screen and sc2screen as it requires less searching to find them.


I believe this is no longer the case. As mentioned by Peter earlier in this thread MMBasic on the CMM2 uses hash lookup of variable and function/subroutine names.

Best wishes,

Tom
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8578
Posted: 09:56pm 27 Apr 2021
Copy link to clipboard 
Print this post

Every variable on a Micromite takes a minimum of 59 bytes for the variable descriptor irrespective of the length of the name. String variables (whether simple or arrays) take a minimum of 315 bytes
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 162
Posted: 10:18pm 27 Apr 2021
Copy link to clipboard 
Print this post

Ouch! Peter - that's a revelation on RAM usage!

I'm doing my best to follow the discussion on the search for variable names :-
  Quote  Variable names affect how fast your code runs! MMBasic scans the name from the left character (I think it's in groups of 2 characters - Peter did mention it somewhere), so it's not good to use something like screen01 and screen02 as variables, it's faster to use sc1screen and sc2screen as it requires less searching to find them.


Doesn't the interpreter have to match ALL the characters of a variable to ensure accuracy, so the exact order of differences woun't affect finding it ? Apologies if I'm showing my ignorance !

Paul.
Nothing so constant as change.
 
     Page 1 of 5    
Print this page
© JAQ Software 2024