Today, I made some progress in running code from the Prizm ILRAM and the other two on-chip RAM areas of the CPU. This work is based on the progress at http://www.cemetech.net/forum/viewtopic.php?t=8076&start=0 .
First, I successfully changed my linker script to include the new memory areas. Then I modified the crt0.S code on libfxcg, for it to copy the code from those sections on the g3a into the proper memory areas. And then, using GCC's section attribute features, I started specifying functions and global variables to run from these areas.
It works fine, as long as we don't move out of our add-in. If I start using timer hacks to have code run outside of my add-in (i.e. when it is not even mapped into memory), weird things start happening. But first I'll show my code...
Code:
The code above is the timer handler for the timer I'll be installing and starting on the snippet below.
Code:
As you can see, everything is set to be outside of the add-in stack or heap: a buffer goes on one of the on-chip ram areas and the timer handle goes on the ILRAM (both can't go on the ilram because then GCC will start complaining about section type conflicts. I think I understand why this happens, look up Google if you don't know).
On the timer handler, nothing is called that belongs to the add-in: DefineStatusMessage is a syscall and thus, supposedly it should be available from anywhere in the OS... right?
(by the way, yes we know for sure the OS doesn't mess with the ILRAM or the other on-chip RAM)
The timer is installed and started from the add-in stack, but that shouldn't matter. The timer is installed on slot 3 which is a "system" slot and doesn't get uninstalled on app change.
Now some good news: as long as we don't take the add-in out of the current stack mapping (that is, we can go to the Main Menu, as long as we don't open another app), the timer works fine and does what it's supposed to do.
Now the bad news: If we start another non-add-in app, well, we don't get a straight system error like we would get if we merely used the add-in stack as the place for the code (because by the time the timer would run, the memory contents would be different). But we get all sorts of weirdness. Sometimes the OS just locks up. With a more elaborate code on the timer handler (which involved using itoa and incrementing a variable on on-chip RAM), a funny thing would happen: the g3p file selection screen would pop up every time the timer ran, and the timer handler wouldn't do what it was supposed to...
If we (acting fast enough to avoid a system error due to so many Pict screens being open) return to the add-in we left, the our ILRAM-based timer handler works fine again. If we launch another add-in... I could only make the calculator reboot without error.
I'm unsure on which conclusion I should take:
- Outside of add-ins, syscalls aren't to be called like we usually call them, and lead to weirdness.
- Although I told GCC to put everything related to the timer handler on memory sections not related to my add-in, it is still linking these against my add-in for some reason, leading to the weirdness. Related to this: I understand this kind of investigation is much better done when coding entirely in assembly, so that we can be sure where the code goes and where it jumps to... but unfortunately I'm not knowledgeable enough with asm to do it.
Any suggestions on what I may be doing wrong, or other things to investigate?
EDIT:
I made the timer handle just increment the value of an integer variable located in one of the additional on-chip RAM areas*, and nothing else. With INSIGHT I inspected that area, and it appears the timer keeps running without problem, as the variable is incremented as it should.
So the problem is, I would say, with calling syscalls. I think I already know why: GCC is putting the syscall calling macro on the add-in-specific memory areas. I need to move that macro to ILRAM too, or else I won't be able to use syscalls in the timer handler.
* sorry, don't know what else to call it. On my setup I call these areas ocram and ocram2.
EDIT2: I'm already having some fun.
The "small" problem is, I had to change memory addresses directly in order to change the statusbar settings (hint: look near address 0x8804F48A), and even had to implement a separate strcpy to have it run from ILRAM, too, as the usual one is either a syscall or in libfxcg, and thus still unavailable for use.
In theory it should be possible to put the syscall calling macro on ILRAM too, but how?
First, I successfully changed my linker script to include the new memory areas. Then I modified the crt0.S code on libfxcg, for it to copy the code from those sections on the g3a into the proper memory areas. And then, using GCC's section attribute features, I started specifying functions and global variables to run from these areas.
It works fine, as long as we don't move out of our add-in. If I start using timer hacks to have code run outside of my add-in (i.e. when it is not even mapped into memory), weird things start happening. But first I'll show my code...
Code:
char buffer1[10] __attribute__((section(".ocram"))); // this can't go on ilram along with the void below because it causes a "section type conflict"
void dbgtimerhandler() __attribute__((section(".ilram")));
void dbgtimerhandler() {
DefineStatusMessage((char*)buffer1, 1, 0, 0);
}
The code above is the timer handler for the timer I'll be installing and starting on the snippet below.
Code:
strcpy(buffer1, "test msg");
int dtm = Timer_Install(3, dbgtimerhandler, 5000);
if (dtm > 0) { Timer_Start(dtm); }
As you can see, everything is set to be outside of the add-in stack or heap: a buffer goes on one of the on-chip ram areas and the timer handle goes on the ILRAM (both can't go on the ilram because then GCC will start complaining about section type conflicts. I think I understand why this happens, look up Google if you don't know).
On the timer handler, nothing is called that belongs to the add-in: DefineStatusMessage is a syscall and thus, supposedly it should be available from anywhere in the OS... right?
(by the way, yes we know for sure the OS doesn't mess with the ILRAM or the other on-chip RAM)
The timer is installed and started from the add-in stack, but that shouldn't matter. The timer is installed on slot 3 which is a "system" slot and doesn't get uninstalled on app change.
Now some good news: as long as we don't take the add-in out of the current stack mapping (that is, we can go to the Main Menu, as long as we don't open another app), the timer works fine and does what it's supposed to do.
Now the bad news: If we start another non-add-in app, well, we don't get a straight system error like we would get if we merely used the add-in stack as the place for the code (because by the time the timer would run, the memory contents would be different). But we get all sorts of weirdness. Sometimes the OS just locks up. With a more elaborate code on the timer handler (which involved using itoa and incrementing a variable on on-chip RAM), a funny thing would happen: the g3p file selection screen would pop up every time the timer ran, and the timer handler wouldn't do what it was supposed to...
If we (acting fast enough to avoid a system error due to so many Pict screens being open) return to the add-in we left, the our ILRAM-based timer handler works fine again. If we launch another add-in... I could only make the calculator reboot without error.
I'm unsure on which conclusion I should take:
- Outside of add-ins, syscalls aren't to be called like we usually call them, and lead to weirdness.
- Although I told GCC to put everything related to the timer handler on memory sections not related to my add-in, it is still linking these against my add-in for some reason, leading to the weirdness. Related to this: I understand this kind of investigation is much better done when coding entirely in assembly, so that we can be sure where the code goes and where it jumps to... but unfortunately I'm not knowledgeable enough with asm to do it.
Any suggestions on what I may be doing wrong, or other things to investigate?
EDIT:
I made the timer handle just increment the value of an integer variable located in one of the additional on-chip RAM areas*, and nothing else. With INSIGHT I inspected that area, and it appears the timer keeps running without problem, as the variable is incremented as it should.
So the problem is, I would say, with calling syscalls. I think I already know why: GCC is putting the syscall calling macro on the add-in-specific memory areas. I need to move that macro to ILRAM too, or else I won't be able to use syscalls in the timer handler.
* sorry, don't know what else to call it. On my setup I call these areas ocram and ocram2.
EDIT2: I'm already having some fun.
The "small" problem is, I had to change memory addresses directly in order to change the statusbar settings (hint: look near address 0x8804F48A), and even had to implement a separate strcpy to have it run from ILRAM, too, as the usual one is either a syscall or in libfxcg, and thus still unavailable for use.
In theory it should be possible to put the syscall calling macro on ILRAM too, but how?