Posté le 03/12/2024 22:32
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 73 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd
Citer : Posté le 03/12/2024 22:41 | #
Welcome back! I recognize your avatar but haven't seen it in a while. :o
About 90-100 kB is available on the G-III, up to 600-700 kB for the CG-50. On the CG-50 there are also large swaths of unused RAM of which we commonly grab 2-3 MB but that technically total 6 MB.
The OS malloc is known to be a bit unreliable with fragmentation on the fx-CG, but most of the default heap memory is managed by gint anyway. On the G-III I don't have clean reports of fragmentation issues, however almost all the heap you can get is from the OS, so you don't have as much control over it and no statistics.
This is a great resource on the G-III, the largest one you have access to, although hard to use efficiently at the same time. You can read this documentation page about SPU memory.
The easiest piece of SPU memory to use is called PRAM0 and it's quite normal except that you can only use 32-bit accesses. So you can't use it to store, e.g., strings for strlen() and co., which frequently use 8-bit accesses. In practice, this means you are limited to using this memory with code that you write yourself.
The rest is XRAM0, YRAM0 and YRAM1, and they work the same except that when you write 32 bits of data only 24 bits are retained.
*YRAM0 = 0x11223344;
*YRAM0; // 0x11223300
I have yet to see these used in an add-in. It's feasible, but a pain.
As per the runtime contract, nothing. The OS doesn't spend time needlessly clearing out memory so you're likely to find scraps of previous executions' data. But that's not a behavior you should rely upon. You can store data safely using the filesystem, or if you want more speed, the main memory (but gint has no wrappers for MCS syscalls, you'll need to world switch and call them manually).
It remains unavailable until the add-in exits, then it is recovered by the OS. "Recovery" is however a misleading term here. The heap just ceases to exist when the add-in quits, and then it is recreated anew on top of whatever there is in memory when another add-in starts.
The add-in is mapped by the MMU directly from Flash at no cost in RAM usage. The add-in file is limited to 512 kB (G-III) / 2 MB (CG-50) after which it does not show up in the main menu anymore, and if you need more room you need to start using external files and loading them to RAM yourself, at which point there is a cost in RAM usage.
You can use the standard POSIX file API (open() and co) or the standard libc API (fopen() and co) on both the G-III and CG-50. Do remember however to world switch during file operations, otherwise the add-in can crash.
Citer : Posté le 03/12/2024 22:43 | #
Hey, welcome here
- You can't have more than the standard heap on G-III (and the SPU only is for the G-III/ fx-CGs), though you can have an extra ~2MB on the CG50 (and on it the heap is already 512KiB)
- It's complicated, but it's not the case anywhere you should use (Basically it only persists if you corrupt important stuff )
- The OS recovers all memory from leaks because it's not the OS that handles it (and with the old SDK i think it just resets malloc()s anyways)
- The addin is loaded into RAM but in a reserved area so you can't lose/gain heap/stack(See Lephe's message)- For Python file I/O, you would have to look at Slyvtt's experimental branch of PythonExtra (community python). It works though, just don't forget to .close() your files because the garbage collection seems a bit flaky
In general, i would recommend not searching too hard for more RAM, but rather just optimizing your program
Edit : i misunderstood the last question, you have standard C I/O with gint/fxlibc (see stdio.h)
Caltos : G35+EII, G90+E (briquée )
Citer : Posté le 03/12/2024 22:54 | #
I've been using malloc and it seems good. There might be a better method, but what I do to get the largest contiguous block of RAM is start from 64KB on FX (can test GINT_HW_FX) otherwise 512KB (CG). Then I try to malloc in a loop, decrementing by 1KB each time malloc fails. Then once it succeeds, I free it, add 1024 and then loop from there, this time decrementing with the alignment I actually wanted (4 bytes, 8 bytes, etc). This seems to be quite fast. Example: https://git.planet-casio.com/calamari/Duvet/src/branch/main/src/sheet.c#L168
Of course if you're allocating a linked list or such then you can just malloc each element individually. Although, I ended up not doing that in Duvet in order to minimize overhead, hence the single large allocation.
I'd recommend to avoid exiting at all, unless you really need to exit due to a fatal error or such. If you exit, then they have to run something else before they can run your add-in again. Instead, allow them to go back to the main menu, for example by pressing MENU. Check out getkey_opt and gint_osmenu. When they're at the main menu, if they choose run something else, your memory is "freed" automatically. Otherwise, they can come back to your add-in and your memory is intact. There are some display details you'll have to deal with when they come back, but it's manageable. Here's how I did it in a recent add-in: https://git.planet-casio.com/calamari/Duvet/src/branch/main/src/kbd.c#L85
“They call me the king of the spreadsheets, got 'em all printed out on my bedsheets.” — “Weird Al” Yankovic
Citer : Posté le 05/12/2024 22:06 | #
Welcome back! I recognize your avatar but haven't seen it in a while. :o
You mentioned that you haven't seen any add-ins use the 24-bit SPU memory. What about the OS? I was wondering if I could leave data there after my add-in ends and expect it to stay there unchanged until it starts again (assuming a second add-in doesn't overwrite it).
Can you explain or link me to a little more about world switching?
Citer : Posté le 05/12/2024 22:22 | #
The OS uses a fixed amount of RAM and what you can get from the OS malloc() is also a fixed amount. That much is not a variable. Fragmentation is this issue where if you fill the heap then over the next cycles of freeing and allocating you end up with swiss cheese with no large blocks and you might be unable to get large allocations. This is a concern you might have on the G-III where gint's heap (which is the default) is small and you quickly end up using the OS heap. By contrast, this is less of a problem on the CG-50 because gint's heap and other extra memory is much larger than the OS heap.
If you want small bits of RAM, use malloc(). It will handle things for you. If you need a large chunk or RAM early on and hold on to it to make sure you keep access to large blocks, then :
- On the G-III, do a single malloc() of the largest size you can, which I'm expecting will be ~90 kB. No point in allocating multiple times as the buffers won't be contiguous. If that's not enough, address directly in PRAM0, but you'll need to stick to 32-bit accesses.
- On the CG, use gint's kmalloc_max() function to get the largest block available in the _uram arena if ~400 kB is enough for you. Otherwise, address directly at 0x8c200000 where you have a few MB.
I don't think the OS uses it, but other add-ins might. And it disappears the moment you press OFF. I advise against relying on long-term storage in RAM in general.
Basically gint is its own mini-OS and you can't use arbitrary official-OS functions while using gint. Usually this comes up when using the filesystem or when using specific syscalls for which gint has no equivalent. To use such functions, you need to leave gint temporarily, run them, then come back into gint, a maneuver known as a world switch. The world switch mechanism, which is hidden from users, ensures that gint and the official OS won't try to use the same piece of hardware at the same time.
In practice, you just have to isolate your file-manipulation code in dedicated functions and call these functions through gint_world_switch() instead of directly.
Citer : Posté le 06/12/2024 01:53 | #
Ok, great. That's just about everything I was wondering about. On the G-III, do I need a world switch to malloc the ~90K from the OS heap instead of gint's heap? Where is gint's heap? Thanks!
Citer : Posté le 06/12/2024 08:27 | #
You don't need to world switch to use malloc(). By default, malloc() will take memory from gint's heap and go to the OS heap when that is full. You can control which heap ("arena") to allocate from by using gint's slightly-lower-level kmalloc() function directly.