How do I make a port of MicroPython for Casio calculators?

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Zezombye
Posts: 33
Joined: Mon Jul 30, 2018 8:29 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by Zezombye » Tue Nov 13, 2018 6:31 pm

On PC, I can do things like printing fact(500), even though this number is hundreds of digits long. Obviously there is some kind of trick, as I assume python doesn't have a type for what is probably a 1 kb digit.

I looked around in MPy, but I've only found these long-int implementations:
- MICROPY_LONGINT_IMPL_NONE (int is limited to 2^31 bits)
- MICROPY_LONGINT_IMPL_LONGLONG (can't use it as Casio doesn't have 64-bit, and no long long)
- MICROPY_LONGINT_IMPL_MPZ (no idea what it is, throws a preprocessor error "incompatible MICROPY_LONGINT_IMPL")

Is there a way to enable "infinite size ints", or at least increase the int size beyond 2^31 bits?

User avatar
dhylands
Posts: 2905
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: How do I make a port of MicroPython for Casio calculators?

Post by dhylands » Tue Nov 13, 2018 8:32 pm

The MICROPY_LONGINT_IMPL_MPZ is what you want. MPZ implement arbitrary precision integers. You can find the support files in the py directory:
https://github.com/micropython/micropyt ... r/py/mpz.h
https://github.com/micropython/micropyt ... r/py/mpz.c

I'm not sure where the incompatible error message is coming from. Can you include the complete error message?

Zezombye
Posts: 33
Joined: Mon Jul 30, 2018 8:29 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by Zezombye » Wed Nov 14, 2018 6:02 am

It comes from build/_frozen_mpy.c:

Code: Select all

#if MICROPY_LONGINT_IMPL != 0
#error "incompatible MICROPY_LONGINT_IMPL"
#endif
Apparently MPy believes that any implementation of long int is incompatible. Why is that? I looked inside mpz.c and 32-bit seems to be supported.

Zezombye
Posts: 33
Joined: Mon Jul 30, 2018 8:29 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by Zezombye » Thu Nov 15, 2018 7:23 pm

Found the solution thanks to https://github.com/adafruit/circuitpython/issues/130

In the makefile, replace "none" with "mpz":

Code: Select all

	$(Q)$(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@

Zezombye
Posts: 33
Joined: Mon Jul 30, 2018 8:29 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by Zezombye » Sat Nov 24, 2018 9:44 pm

I would like to allow the user to get out of an infinite loop. At the moment this is impossible: as MPy is not waiting for a key, all keys are ignored, and the only way to interrupt the loop is by pressing the hardware reset button.

I could put a timer that listens separately for the [EXIT] key and exits the app completely when that key is pressed, however I'd like to just break the loop by raising a KeyboardInterrupt (or at least exit MPy completely so that my app returns to the editor).

How can I raise a KeyboardInterrupt exception from a hardware timer? I looked at https://docs.micropython.org/en/latest/ ... rules.html but I didn't understand much.

Zezombye
Posts: 33
Joined: Mon Jul 30, 2018 8:29 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by Zezombye » Thu Nov 29, 2018 3:06 pm

Hi,

Unfortunately I have 2 more problems with Micropython.

The first one is that, for some reason, my app crashes when I call a recursive function with too much depth. For example, this simple recursive function:

Code: Select all

def r(n):
  if n == 0:
    return 0
  else:
    return 1+r(n-1)
Calling up to r(63) works fine, but calling r(64) to r(85) makes the screen completely blank for some reason (though I can still exit the app via the [MENU] key), and when I press [EXIT] to return to the editor, it crashes with apparently a buffer overflow (writing to an address that is not allocated to the app).
Calling r(86) and further straight up throws a system error, interestingly r(86) throws a different error than r(87) and above.

Note that, when I call other functions, the behavior is slightly different (for example, I tested with a recursive factorial function, it also began crashing at f(64) but calling f(83) or f(84) made the shell hang a bit, then blank screen, but I couldn't do anything this time; another function with a lot more code crashes at around 20 calls, with another different error).

Any idea of what causes this?

Second problem is with the shell. The REPL implementation calls the mp_hal_stdout_tx_strn() function once per char, instead of once per string. As my shell display is updated at every printed string (and when the cursor is moved), this leads to visual "glitches" (for example, when inserting a character at the beginning of a long string, the cursor is seen moving to the end of the string then back to the beginning).

Is there a way to make the REPL call the mp_hal_stdout_tx_strn() once per string (essentially basing the "length" argument on the \0) ?

jickster
Posts: 546
Joined: Thu Sep 07, 2017 8:57 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by jickster » Thu Nov 29, 2018 9:45 pm

Zezombye wrote:
Thu Nov 29, 2018 3:06 pm
Hi,

Unfortunately I have 2 more problems with Micropython.

The first one is that, for some reason, my app crashes when I call a recursive function with too much depth. For example, this simple recursive function:

Code: Select all

def r(n):
  if n == 0:
    return 0
  else:
    return 1+r(n-1)
Calling up to r(63) works fine, but calling r(64) to r(85) makes the screen completely blank for some reason (though I can still exit the app via the [MENU] key), and when I press [EXIT] to return to the editor, it crashes with apparently a buffer overflow (writing to an address that is not allocated to the app).
Calling r(86) and further straight up throws a system error, interestingly r(86) throws a different error than r(87) and above.

Note that, when I call other functions, the behavior is slightly different (for example, I tested with a recursive factorial function, it also began crashing at f(64) but calling f(83) or f(84) made the shell hang a bit, then blank screen, but I couldn't do anything this time; another function with a lot more code crashes at around 20 calls, with another different error).

Any idea of what causes this?
Yes. Recursion in Python uses memory just like in any other language.
Don't use recursion unless you have to; recursion is nice because it keeps track of state "automatically" but at a huge cost of memory.
You can keep track of the state without recursion and use much less memory.

Zezombye
Posts: 33
Joined: Mon Jul 30, 2018 8:29 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by Zezombye » Fri Nov 30, 2018 3:44 pm

I can't really do without recursion though (in algorithms class, recursive functions are almost always studied).

Sure, recursion eats memory, however MPy handles regular out-of-memory just fine:

Code: Select all

l = []
while True:
  l.append("12345678")
Image

Also, if the error is caused by being out of memory, it seems weird because I allocated 32kio (as seen in the screenshot) but that would mean each call costs 32ko/64 = 512 bytes? Seems like a lot for such a small function. Even if it runs out of memory, why doesn't it throw an exception inside Python?

jickster
Posts: 546
Joined: Thu Sep 07, 2017 8:57 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by jickster » Fri Nov 30, 2018 3:51 pm

Zezombye wrote:
Fri Nov 30, 2018 3:44 pm
I can't really do without recursion though (in algorithms class, recursive functions are almost always studied).
Practicing algorithms on a constrained device is a terrible idea . . . as you've seen.

If you want to do recursive algorithms in Python, do it on the PC.


Zezombye wrote:
Fri Nov 30, 2018 3:44 pm
Sure, recursion eats memory, however MPy handles regular out-of-memory just fine:
You must not have defined

Code: Select all

MICROPY_STACK_CHECK

jickster
Posts: 546
Joined: Thu Sep 07, 2017 8:57 pm

Re: How do I make a port of MicroPython for Casio calculators?

Post by jickster » Fri Nov 30, 2018 3:55 pm

Zezombye wrote:
Fri Nov 30, 2018 3:44 pm

Also, if the error is caused by being out of memory, it seems weird because I allocated 32kio (as seen in the screenshot) but that would mean each call costs 32ko/64 = 512 bytes? Seems like a lot for such a small function. Even if it runs out of memory, why doesn't it throw an exception inside Python?
It appears you don't know how a stack works.
"Stack" is an area in RAM wherein the execution stack should stay within.
At the software level, you don't "run out" of stack but merely start overflowing into other areas of RAM and overwriting stuff and eventually causing a crash.

That's why uPy added MICROPY_STACK_CHECK. In recursive C-functions in uPy, a function is called to check the size of the stack.

https://github.com/micropython/micropyt ... ctrl.c#L51

Post Reply