diff --git a/stmhal/Makefile b/stmhal/Makefile
index 31686754240508c1dfd5e294a6bd5bcb99196f99..9f8c13a87e7f11fecff4dad442d0d92c19670682 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -330,6 +330,7 @@ $(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c
 
 GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h
 GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h
+GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h
 CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]')
 CMSIS_MCU_HDR = cmsis/devinc/$(CMSIS_MCU_LOWER).h
 
@@ -338,7 +339,7 @@ $(BUILD)/modstm.o: $(GEN_STMCONST_HDR)
 # make both modstm_const.h and modstm_qstr.h
 $(HEADER_BUILD)/%_const.h $(BUILD)/%_qstr.h: $(CMSIS_MCU_HDR) make-stmconst.py | $(HEADER_BUILD)
 	$(ECHO) "Create stmconst $@"
-	$(Q)$(PYTHON) make-stmconst.py --qstr $(GEN_STMCONST_QSTR) $(CMSIS_MCU_HDR) > $(GEN_STMCONST_HDR)
+	$(Q)$(PYTHON) make-stmconst.py --qstr $(GEN_STMCONST_QSTR) --mpz $(GEN_STMCONST_MPZ) $(CMSIS_MCU_HDR) > $(GEN_STMCONST_HDR)
 
 $(GEN_CDCINF_HEADER): $(GEN_CDCINF_FILE) $(FILE2H) | $(HEADER_BUILD)
 	$(ECHO) "Create $@"
diff --git a/stmhal/make-stmconst.py b/stmhal/make-stmconst.py
index 79e69a3bf42687f716dbc0d6fab5a5ef456485f3..e9fbb477c9b035e404e62d1c50fb555844c891f6 100644
--- a/stmhal/make-stmconst.py
+++ b/stmhal/make-stmconst.py
@@ -111,16 +111,27 @@ def parse_file(filename):
 
     return periphs, reg_defs
 
-def print_periph(periph_name, periph_val, needed_qstrs):
+def print_int_obj(val, needed_mpzs):
+    if -0x40000000 <= val < 0x40000000:
+        print('MP_OBJ_NEW_SMALL_INT(%#x)' % val, end='')
+    else:
+        print('(mp_obj_t)&mpz_%08x' % val, end='')
+        needed_mpzs.add(val)
+
+def print_periph(periph_name, periph_val, needed_qstrs, needed_mpzs):
     qstr = periph_name.upper()
-    print('{ MP_OBJ_NEW_QSTR(MP_QSTR_%s), MP_OBJ_NEW_SMALL_INT(%#x) },' % (qstr, periph_val))
+    print('{ MP_OBJ_NEW_QSTR(MP_QSTR_%s), ' % qstr, end='')
+    print_int_obj(periph_val, needed_mpzs)
+    print(' },')
     needed_qstrs.add(qstr)
 
-def print_regs(reg_name, reg_defs, needed_qstrs):
+def print_regs(reg_name, reg_defs, needed_qstrs, needed_mpzs):
     reg_name = reg_name.upper()
     for r in reg_defs:
         qstr = reg_name + '_' + r[0]
-        print('{ MP_OBJ_NEW_QSTR(MP_QSTR_%s), MP_OBJ_NEW_SMALL_INT(%#x) }, // %s-bits, %s' % (qstr, r[1], r[2], r[3]))
+        print('{ MP_OBJ_NEW_QSTR(MP_QSTR_%s), ' % qstr, end='')
+        print_int_obj(r[1], needed_mpzs)
+        print(' }, // %s-bits, %s' % (r[2], r[3]))
         needed_qstrs.add(qstr)
 
 # This version of print regs groups registers together into submodules (eg GPIO submodule).
@@ -161,18 +172,21 @@ def main():
     cmd_parser.add_argument('file', nargs=1, help='input file')
     cmd_parser.add_argument('-q', '--qstr', dest='qstr_filename', default='build/stmconst_qstr.h',
                             help='Specified the name of the generated qstr header file')
+    cmd_parser.add_argument('--mpz', dest='mpz_filename', default='build/stmconst_mpz.h',
+                            help='the destination file of the generated mpz header')
     args = cmd_parser.parse_args()
 
     periphs, reg_defs = parse_file(args.file[0])
 
     modules = []
     needed_qstrs = set()
+    needed_mpzs = set()
 
     print("// Automatically generated from %s by make-stmconst.py" % args.file[0])
     print("")
 
     for periph_name, periph_val in periphs:
-        print_periph(periph_name, periph_val, needed_qstrs)
+        print_periph(periph_name, periph_val, needed_qstrs, needed_mpzs)
 
     for reg in (
         'ADC',
@@ -203,7 +217,7 @@ def main():
         'RNG',
         ):
         if reg in reg_defs:
-            print_regs(reg, reg_defs[reg], needed_qstrs)
+            print_regs(reg, reg_defs[reg], needed_qstrs, needed_mpzs)
         #print_regs_as_submodules(reg, reg_defs[reg], modules, needed_qstrs)
 
     #print("#define MOD_STM_CONST_MODULES \\")
@@ -216,5 +230,12 @@ def main():
         for qstr in sorted(needed_qstrs):
             print('Q({})'.format(qstr), file=qstr_file)
 
+    with open(args.mpz_filename, 'wt') as mpz_file:
+        for mpz in sorted(needed_mpzs):
+            assert 0 <= mpz <= 0xffffffff
+            print('STATIC const mp_obj_int_t mpz_%08x = {{&mp_type_int}, '
+                '{.neg=0, .fixed_dig=1, .alloc=2, .len=2, ' '.dig=(uint16_t[]){%#x, %#x}}};'
+                % (mpz, mpz & 0xffff, (mpz >> 16) & 0xffff), file=mpz_file)
+
 if __name__ == "__main__":
     main()
diff --git a/stmhal/modstm.c b/stmhal/modstm.c
index 74fae32550eb8526f0ed42b54c72f27bbd57381c..005cd824aef085d0bf2d6a30430ae8eb4a703bc1 100644
--- a/stmhal/modstm.c
+++ b/stmhal/modstm.c
@@ -34,6 +34,9 @@
 #include "extmod/machine_mem.h"
 #include "portmodules.h"
 
+#include "py/objint.h"
+#include "genhdr/modstm_mpz.h"
+
 STATIC const mp_map_elem_t stm_module_globals_table[] = {
     { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_stm) },