I was working on add the Kermit protocol to Utilities so that I could transfer files to and from my computer via serial to avoid the slow USB transfer mode when I encountered an issue. Upon selecting the file manager it froze. After a while (maybe not as long as I should have waited) I decided to remove power. However upon reapplying power the screen would not turn on.
In terms of causes I am not entirely sure. One theory I had is that I was using some code from here:
https://www.cemetech.net/downloads/files/785/x785 and I kept running into an issue where it would overwrite my VRAM_ADDR variable after running Bfile_FindFirst. In theory it could have been because of something bad earlier down the line but the issue was very consistent even when I changed the code around. I tried to study gbl08ma's code which I assumed was better and I did notice that the part I was looking at around Bfile_FindFirst was very similar to the filegui.c code. I committed the exact code I was working with here:
https://github.com/ComputerNerd/Casio-prizm-mpeg2-player/blob/master/filegui.c look around line 197. Maybe gbl08ma's code has the same issue that filegui.c has regarding memory corrupt but it was never an issue because utilities didn't use as much RAM until I added E-Kermit to utilities or maybe there is something different about my toolchain that when I build it I get this problem.
Another possible cause is I did have a small amount bare wire exposed for the serial module. Maybe I accidentally brushed it against the PCB and messed something up. The way I had this positioned though I think isn't so likely.
I hope this can be recovered via serial or some software method. Soldering the flash might be beyond me as of now (I can get SMD chips off easy. I struggle with getting them back on however) and also the calculator is almost certainty way past any warranty.
Edit: I see that there is a code I can use to possibly get into an OS recovery mode
https://prizm.cemetech.net/index.php?title=Secret_Key_Combinations#Diagnostic_mode
For me it's tough to do but I think I've done it right and nothing happened. Has anyone tried this? If so at what stage did the screen turn on? How do I know if this option is available to me or if I'm just not doing it right?
Wow that's not something you want to see, I hope you will be able to bring this calculator back.
I'm not familiar with these libraries but in my experience there aren't a lot of ways for code to overwrite supposedly unrelated variables. I can think of stack corruption, leaking stack addresses to parent or asynchronous functions, buffer overflows, incorrect linker scripts, and a handful of cases too specific to be worth looking at.
VRAM_ADDR being a global variable here, the only reasonable options in these are buffer overflows and incorrect linker script. The libfxcg linker script is very simple, it would be surprising if it hid any errors. But just in case, I suggest to look at the build map (the one you get with -Wl,-Map=file) to check where VRAM_ADDR is located and whether there is a chance that it overlapped with something else.
The stack may also be suspicious though. Things like the 271-character limit should be clear of any doubt, but of course because you've had problems this might be worth investigating. If you can disassemble the compiled version of this chdir function, it would help figuring out what memory was involved, and just in case check whether the VRAM_ADDR you were displaying really was the global variable being fetched in real-time and not a (possibly corrupted) copy on the stack or whatever.
In any case, even if the root cause of the problem can be found, how to get to the black screen would remain a mystery. There's almost no way a memory write can brick a calculator by itself; writing to RAM reverts after a reset, writing to ROM never gets through the cache, even the critical code in RS memory reverts after a reset; the only problematic things are critical peripheral registers.
A couple of them are retained during a manual reset, including the port registers, which are used indirectly to communicate with the screen. However the RTC is also retained, and the reset button is known to revert the RTC. This means the reset button is likely a power-on reset, and every single peripheral register is either initialized or undefined after this type of reset.
There might have been some sort of catastrophic chain of events leading to corruption in the Flash but that's just not something we could track.
The diagnostic mode combination is very easy to perform. Just press OPTN and EXP then keep them pressed while powering ON. When the calculator starts a popup appears, at that time release everything and just press F1 and 9 normally like in a GUI. The screen should turn on after pressing ON, the whole combination just relies on the fact that the startup code checks for the keys F1 and 9 to prompt the diagnostic mode. You probably did it right, and I don't think it would boot any differently anyway.
Do you get power (or even signal, let's have hope) from the USB bus if you plug in the cable and press the F1 key? In the event that the USB communication works, it might be possible to re-flash the OS with an official OS updater.
That's a good point to disassemble it. I'll look into that to try and prevent further issues. Also I might if possible try looking into how Bfile_FindFirst works. I know if you are wrong about what parameters a syscall takes it's possible to run into issues. Maybe Bfile_FindFirst is similar to Bfile_OpenFile_OS in that you need to pass a zero as a last argument for it work right.
For the calculator I'm pretty sure it's gone or at-least some of the data on the flash memory chip is gone. I never got the screen to come on when trying any of the key combinations and if I run dmesg and lsusb on my computer I get no signs of the calculator when plugging it in via USB. For this reason I decided to get a new fx-CG50. I didn't know this until recently but the fx-CG50 has 8 MiB of ram instead of 2 MiB. In terms of what kind of programs can be ran on the calculator that's a huge deal. Assuming we could use this additional memory in our add-ins it would open up a huge amount of opportunities not possible on the fx-CG10/20 and also reduce effort required to port software because I would not need to spend as much time fighting for every kilobyte of ram. For example in my Open JazzJackrabbit port I had to really work on it a lot to get it to use less memory but if I had closer to 8 MiB or even maybe 4 MiB of ram and a good heap I could have probably got it work with far less modifications.
We know that Bfile_FindFirst if pretty complicated. In fact,
Yatis on Planète Casio has done a lot of reverse-engineering of these syscalls recently, and for instance found how almost every Bfile call allocates 8 kiB worth of file names on the stack in order to convert file names to call into Fugue (the underlying, external FAT filesystem implementation with a more standard string encoding).
Quote:
I didn't know this until recently but the fx-CG50 has 8 MiB of ram instead of 2 MiB.
Does it though? The Graph 90+E (French fx-CG 50) has absolutely no additional RAM. The heap is still 128 kiB, the stack is still 512 kiB, etc. The closest thing I have ever seen to a RAM increase was at a CASIO tour in 2017 (« tournée pédagogique ») when the model was released, where the heap in the hidden 5/9/6/3 menu indicated 3 MiB, at the time where Python was still being tested. The heap reverted to 128 kiB in all models sold after the release.
I'm a bit worried here, because using additional RAM like this (if it exists) would make the programs definitely incompatible with the French models.
You are right that the software running on a Graph 90+E still has a 128 KiB heap and a 512 KiB stack.
My question though is regarding this picture that I found while researching this:
https://tiplanet.org/forum/gallery/image_page.php?album_id=514&image_id=8282 The image is titled as "Casio Graph 90+E". One of the IC chips on there has markings which say: "M12L64164A". Looking at the datasheet it says:
Quote:
[The M12L64164A is 67,108,864 bits synchronous high data rate Dynamic RAM organized as 4 x 1,048,576 words by
16 bits.
Why would the calculator have an 8 MiB chip in it?
I guess having an 8 MiB chip doesn't always mean 8 MiB is accessible to the processor. Could some of the address lines not be connected? Also this is only one calculator. Maybe it's changed in a hardware revision. Also of course even if all fx-CG50s and all Graph 90+Es have 8 MiB of RAM all of which is accessible to the process that doesn't necessarily mean we get to use it in our add-ins if the OS is already using it.
Also for the Bfile... syscalls that's kind of silly almost so basically in a realistic program the following happens.
1. The program has the path stored as regular 8-bit chars.
2. The program converts those to 16-bit characters using Bfile_StrToName_ncpy.
3. The program calls the Bfile syscall such as Bfile_OpenFile_OS.
4. Inside of Bfile_OpenFile_OS it undoes what the program did and step #2 and puts it back into something more like what we had in step #1.
Am I understanding this correctly?
Very sorry to hear that - where are you getting the new prizm from? Get it from somewhere with long warranty and/or easy return policy
You're observant. I had wondered about the size of the chip but didn't know about the exact size. Yes, it is possible that the RAM exists but is not normally usable in add-ins. That 3 MB heap for Python testing had to be backed by something after all; possibly these RAM chips were provisioned in case Python needed them but not changed even after the heap reverted to 128 kB.
Just like some fx-9860G models that have 512 kB RAM but only use 256 kB in the add-ins and system, it might be possible to barbarically access the area by address. But this can break with any OS update that starts using it, as it did with the fx-9860G III that started using the whole 512 kB to support Python.
Quote:
Also for the Bfile... syscalls that's kind of silly almost so basically in a realistic program the following happens.
1. The program has the path stored as regular 8-bit chars.
2. The program converts those to 16-bit characters using Bfile_StrToName_ncpy.
3. The program calls the Bfile syscall such as Bfile_OpenFile_OS.
4. Inside of Bfile_OpenFile_OS it undoes what the program did and step #2 and puts it back into something more like what we had in step #1.
Am I understanding this correctly?
Yes. Please note that the FAT filesystem is not implemented by CASIO, it is an independent program called Fugue. CASIO wants the 16-bit FONTCHARACTER encoding for file names, probably because the earliest version of the storage memory filesystem (which they implemented) were designed like that.
Later on, when moving to Fugue, they probably had to keep this format in order to maintain API compatibility, so they added this layer of translation. The string passed to Fugue is not exactly the same as the one you give to Bfile_StrToName_ncpy(), although I believe this is the case if there are only ASCII characters.
In GCC you can avoid the copy by declaring a 16-bit string literal: u"\\\\fls0\\somefile.bin" for instance.
amazonka, I see what you are saying. I didn't buy any kind of extended warranty but I believe where I bought it from has a good return policy. I would only return it if I didn't think it was my fault for breaking it.
Lephe, You are right. I didn't consider that Casio needed to maintain compatibility with their API. This makes more sense now.
Quote:
There's almost no way a memory write can brick a calculator by itself; writing to RAM reverts after a reset, writing to ROM never gets through the cache, even the critical code in RS memory reverts after a reset; the only problematic things are critical peripheral registers.
Recently, I was trying to write into internal Fugue's data structure and I had missed something, the result was that my calculator almost broke. I had to go to the Fugue's debugging menu in Diagnostic mode and perform a "low-level format" to restore de calculator because the "logical-format" throw me an error.
Note that, after modifying the information of Fugue, my calculator wasn't doing anything special until I pressed the [MENU] key (using Getkey()) to return to the main menu. This is where my calculator starting performing weirdly. After this incident, I discovered that the GetKey() syscall involve Bfile_ReadFile_OS() / Bfile_WriteFile_OS() which implies Fugue primitives. So, if somehow, internal Fugue information has been badly modified, it may not be impossible that some critical sectors has been wiped. :/
If your calculator doesn't display anything, I think that it's really dead to restore it using the "soft" way. However, it's not impossible to recover the flash, however, you need to extract the chip, dump it (to see what happened), re-flash it with a clean OS, then put it back. This is theoretical, but the flash is using the TSOP format and some NAND flash reader can be found on AlixExpress, So, why not.
Also, it may not impossible (but not probable) that the storage memory blocks the bootloader, I have disassembled the Fugue formatting Diagnostic mode menu. If you can find a way to involve the low-level format subroutine (simply a jump, I can give you the exact address, but I need your OS version), you can possibly unbrick
your calculator (but I'm not really confident with this theory).
By-the-way, some notes about the FS formatting that is performed in Diagnostic mode:
syscall %db0: int SMEM_mount(void);
syscall %1da1: int SMEM_format(void *unknown, int mode, int unknown);
syscall %1e4b: int DisplayMessage(const char *message);
syscall %db1: int SMEM_unmount(void);
How logical and low-level format is performed by Casio in debugging menu:
Code: void casio_smem_format_logical(void)
{
uint8_t buffer[0x118];
int msg = "Format Success";
int ret;
/* unmount the FS */
SMEM_unmoun();
/* Try to perform a logical format */
ret = SMEM_format(buffer, 0, 0);
msg = "Format Success"
if (ret != 0)
msg = "Format failed";
DisplayMessage(msg);
/* Try to mount the FS */
if (SMEM_Mount() == 0)
return;
DisplayMessage("Mount Failed");
}
void casio_smem_format_lowlevel(void)
{
uint8_t buffer[0x118];
int msg = "Format Success";
int ret;
/* unmount the FS */
SMEM_unmoun();
/* Try to perform a logical format */
ret = SMEM_format(buffer, 1, 0);
msg = "Format Success"
if (ret != 0)
msg = "Format failed";
DisplayMessage(msg);
/* Try to mount the FS */
if (SMEM_Mount() == 0)
return;
DisplayMessage("Mount Failed");
}
I'm currently writing a "real" documentation about Fugue, I have enough information to perform a "pseudo" file listing with meta information (like size, type, ...) of the root directory, still no data reading, but it won't be long to find. ^^
Yatis, This is very exciting! If you figure this out I probably would not use the Bfile functions again. One question the file-system is called the Fugue FAT Filesystem and when I use the USB mode it gives me something that must be close enough to the FAT filesystem such that Linux is able to handle it without any issues. Could this mean that it would be possible to use something such as FatFs to read the filesystem? Or does it have some extra data or is it arranged in a strange way such that this would not work at all or would require some additional effort besides pointing FatFs to the start of the filesystem?
Your theory regarding the executing a specific address sense. If you could force the CPU to execute an address assuming it's still on the flash memory chip that would work assuming skipping the initialization the bootloader does is fine. The only thing I'm not sure on is if there are any JTAG test pads or similar. I don't know how I could force the CPU to execute an address.
Regarding the Flash memory soldering. I am considering doing this. after confirming that there are no known test points that I could solder a wire to (I think the chance of success would be higher with this approach). Now that I bought a new calculator I would not feel too bad if I mess something up while trying to remove the chip or put back on a socket or soldering the chip back on. If there was a socket that used the same footprint as the flash memory chip that would be ideal but I'm not sure if such a thing exists. I'll need to research this more.
Quote:
Could this mean that it would be possible to use something such as FatFs to read the filesystem? Or does it have some extra data or is it arranged in a strange way such that this would not work at all or would require some additional effort besides pointing FatFs to the start of the filesystem?
You should know that the storage memory has gotten ever slower over time. The first models like the fx-9750G could save a 256 kiB file to storage memory in about a second. Today, saving 1 MiB file on my fx-CG 50 takes exactly 1 minute. This steady decrease in performance can be observed throughout the revisions.
To me, it is clear evidence that the storage memory filesystem has only gotten more heavy and convoluted over the years. The transition to Fugue, then the USB overhead, the loading step that prepares the filesystem before USB communication, all contribute to this idea.
Honestly, even if you were able to access the internal Fugue filesystem directly through USB, I'm pretty sure you'd eventually break the BFile structure and end up with trouble. Problems with the filesystem are also the hardest to resolve, and we've had an instance where someone ended up with a half-bricked calculator because of a fle with an invalid name. The invalid name prevented USB Mass Storage from working properly, so they were unable to delete the file or transfer any other file. BFile deletion calls also rejected the invalid name, preventing any access from the API. I believe to this day the calculator is still locked.
So I wouldn't put my money on this, even though I'd be very happy to have read-only access directly through the ROM as it would avoid world switch and BFile overheads in my kernel.
I should mention in my previous post I wasn't suggesting that we try and get more directly access the internal Fugue filesystem via USB. I'm interested in doing it for add-ins and I'd only be interested in read only because I wouldn't want to mess something up on someone's calculator unless we are very sure that any write code is safe.
What I was asking is how is it that when I put it in USB mode I get something that's compatible with the regular FAT filesystem? I'm speculating but don't have any proof that whatever is stored on the flash memory is either the same as the regular FAT filesystem, close to it or somehow it's at-least somewhat easy to go from the internal filesystem to something that could be accessed like a normal FAT filesystem.
Also for the person with the Bfile issues would the debugging menu that Yatis mentioned help with this problem?
Oh, sorry, I missed the point of your previous post! Fugue is a FAT/VFAT filesystem, so that's the general idea yes. Yatis, do you remember the FAT12/FAT16 models and the deviations?
Quote:
Also for the person with the Bfile issues would the debugging menu that Yatis mentioned help with this problem?
A normal reset from the SYSTEM app did not work. I don't think the low-level reset was attempted or even if we knew about it at the time. The thing is, the key combination to access this menu (OPTN+EXP+AC/ON, 5, 9, 6, 3/4) no longer works on the fx-9750G III, so we don't know how to access it.