I am seeing strange errors when using the C API to write files from a coroutine using @NaOH’s playdate-coroutines library. I have not found a definitive pattern yet, but it seems like the first write call that goes over 1023 unflushed bytes fails with "I/O error", and after that, the filesystem driver is in a broken state where also other calls like stat or listfiles fail with errors like "unknown uC-FS error: 0302" (numbers vary). When I write small enough chunks (500 bytes seems to work) and call flush after every write, the problem does not occur and I can write as much as I want. This only happens on the device (HW A, OS 3.0.0), not in the simulator on macOS. I am not sure why it only happens in a coroutine, the only thing that is different there that I can think of is that the stack is in a different place.
Is this a bug in the OS, or a bug in the coroutine library, or am I simply doing anything wrong?
The actual project I am seeing this in is PewPew: Python games on Playdate (WIP) and I am calling the filesystem API functions from Python, which needs to run in a coroutine.
I found this bug as well. The problem seems to occur when the stack pointer is outside the normal stack area in TCM (0x20000000). I found the solution is to invoke IO operations only from the main thread.
I was hoping to avoid the complexity of dispatching IO operations to the main thread… for now I think I’ll wait and see if the bug bites in any other situations, for my current problem (copying example games from the pdx into the data area) I have a workaround with the frequent flushing, and PewPew games probably don’t write large files all that often.
By the way, have you ever experimented with putting the coroutine stack in TCM as well? I was wondering whether having the stack in external RAM may be the reason why my Python code runs slower than I would expect from an STM32.
I'll see if I can add a workaround to force file IO to occur in TCM.
And yes, not being in TCM would cause your code to run slower. There are only 10 kb of user stack IIRC, and another 12kb of TCM in the screen buffer. So, not a lot to work with. I can add funcitonality for custom stack addresses. Give me a few hours.
Okay, well, when you get back into this project, check out the intercept branch I made in the playdate-coroutines repo. It’s WIP and I am encountering some problems with my playdate which means I won’t be able to easily make much more progress. But essentially, it reroutes the file IO functions to use the main stack.
You should also pretty easily be able to add a function to the API to use a specified address+size for the coroutine’s stack instead of a malloc’d region.
Thanks, I’ll take a look! That branch branches off from a rather old version of main so I’ll probably have to merge at least my macOS fixes in, but we’ll see.