diff --git a/py/mpconfig.h b/py/mpconfig.h
index 94e2737de0d933603e52aba4b39e23ef290bcd71..d561f80790205aa37e3a2eb14eac38514cd8e0c0 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -125,11 +125,19 @@
 #define MICROPY_QSTR_BYTES_IN_LEN (1)
 #endif
 
-// Avoid using C stack when making Python function calls.
+// Avoid using C stack when making Python function calls. C stack still
+// may be used if there's no free heap.
 #ifndef MICROPY_STACKLESS
 #define MICROPY_STACKLESS (0)
 #endif
 
+// Never use C stack when making Python function calls. This may break
+// testsuite as will subtly change which exception is thrown in case
+// of too deep recursion and other similar cases.
+#ifndef MICROPY_STACKLESS_STRICT
+#define MICROPY_STACKLESS_STRICT (0)
+#endif
+
 /*****************************************************************************/
 /* Micro Python emitters                                                     */
 
diff --git a/py/runtime.h b/py/runtime.h
index 8666ce10750d0f22f83dc565b73fb91cd07a03e5..a36f1b1bd78129d34a84e0dd7be1cdf066e1f62b 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -130,6 +130,7 @@ void mp_import_all(mp_obj_t module);
 
 // Raise NotImplementedError with given message
 NORETURN void mp_not_implemented(const char *msg);
+NORETURN void mp_exc_recursion_depth(void);
 
 // helper functions for native/viper code
 mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
diff --git a/py/stackctrl.c b/py/stackctrl.c
index 7d7bbc1be13dc38534bd5b6b4eafabbfe3a97a6f..4c516537270a1c822383f5ea2d3dace8656e07f7 100644
--- a/py/stackctrl.c
+++ b/py/stackctrl.c
@@ -27,6 +27,7 @@
 #include "py/mpstate.h"
 #include "py/nlr.h"
 #include "py/obj.h"
+#include "py/runtime.h"
 #include "py/stackctrl.h"
 
 void mp_stack_ctrl_init(void) {
@@ -46,10 +47,14 @@ void mp_stack_set_limit(mp_uint_t limit) {
     MP_STATE_VM(stack_limit) = limit;
 }
 
+void mp_exc_recursion_depth(void) {
+    nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
+        MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
+}
+
 void mp_stack_check(void) {
     if (mp_stack_usage() >= MP_STATE_VM(stack_limit)) {
-        nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
-            MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
+        mp_exc_recursion_depth();
     }
 }
 
diff --git a/py/vm.c b/py/vm.c
index 291e707c1f7ff634067e40421e7672d83065f070..dc4f9c2739a7b26ba67f014cc2cd31deccda5d8f 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -880,6 +880,12 @@ unwind_jump:;
                             nlr_pop();
                             goto run_code_state;
                         }
+                        #if MICROPY_STACKLESS_STRICT
+                        else {
+                        deep_recursion_error:
+                            mp_exc_recursion_depth();
+                        }
+                        #endif
                     }
                     #endif
                     SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
@@ -912,6 +918,11 @@ unwind_jump:;
                             nlr_pop();
                             goto run_code_state;
                         }
+                        #if MICROPY_STACKLESS_STRICT
+                        else {
+                            goto deep_recursion_error;
+                        }
+                        #endif
                     }
                     #endif
                     SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
@@ -941,6 +952,11 @@ unwind_jump:;
                             nlr_pop();
                             goto run_code_state;
                         }
+                        #if MICROPY_STACKLESS_STRICT
+                        else {
+                            goto deep_recursion_error;
+                        }
+                        #endif
                     }
                     #endif
                     SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
@@ -973,6 +989,11 @@ unwind_jump:;
                             nlr_pop();
                             goto run_code_state;
                         }
+                        #if MICROPY_STACKLESS_STRICT
+                        else {
+                            goto deep_recursion_error;
+                        }
+                        #endif
                     }
                     #endif
                     SET_TOP(mp_call_method_n_kw_var(true, unum, sp));