diff --git a/docs/library/pyb.RTC.rst b/docs/library/pyb.RTC.rst
index eeefa100ceebe25a3fecbf02261ae57fd56cd628..cd4b28eabd6631825a603004ff60240f84000c70 100644
--- a/docs/library/pyb.RTC.rst
+++ b/docs/library/pyb.RTC.rst
@@ -57,3 +57,19 @@ Methods
       start up.
     - Bit 0x10000 is set if a power-on reset occurred.
     - Bit 0x20000 is set if an external reset occurred
+
+.. method:: rtc.calibration(cal)
+
+   Get or set RTC calibration.
+
+   With no arguments, ``calibration()`` returns the current calibration
+   value, which is an integer in the range [-511 : 512].  With one
+   argument it sets the RTC calibration.
+
+   The RTC Smooth Calibration mechanism addjusts the RTC clock rate by
+   adding or subtracting the given number of ticks from the 32768 Hz
+   clock over a 32 second period (corresponding to 2^20 clock ticks.)
+   Each tick added will speed up the clock by 1 part in 2^20, or 0.954
+   ppm; likewise the RTC clock it slowed by negative values. The
+   usable calibration range is:
+   (-511 * 0.954) ~= -487.5 ppm up to (512 * 0.954) ~= 488.5 ppm
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index e2fd0bbaf46c5e34254a3f71e3da8efcdfb4518d..a8b52f346a5a543011343d6c42645511995b59ec 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -122,6 +122,7 @@ Q(RTC)
 Q(info)
 Q(datetime)
 Q(wakeup)
+Q(calibration)
 
 // for Pin class
 Q(Pin)
diff --git a/stmhal/rtc.c b/stmhal/rtc.c
index b4fa69e862904e03c1ef1da0b21db4097b395a25..8b21c6ee507773f6e722085141d2c8f0dd3363d0 100644
--- a/stmhal/rtc.c
+++ b/stmhal/rtc.c
@@ -496,10 +496,46 @@ mp_obj_t pyb_rtc_wakeup(mp_uint_t n_args, const mp_obj_t *args) {
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_wakeup_obj, 2, 4, pyb_rtc_wakeup);
 
+// calibration(None)
+// calibration(cal)
+// When an integer argument is provided, check that it falls in the range [-511 to 512]
+// and set the calibration value; otherwise return calibration value
+mp_obj_t pyb_rtc_calibration(mp_uint_t n_args, const mp_obj_t *args) {
+    mp_int_t cal;
+    if (n_args == 2) {
+	cal = mp_obj_get_int(args[1]);
+	mp_uint_t cal_p, cal_m;
+	if (cal < -511 || cal > 512) {
+	    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+					       "calibration value out of range"));
+	}
+	if (cal > 0) {
+	    cal_p = RTC_SMOOTHCALIB_PLUSPULSES_SET;
+	    cal_m = 512 - cal;
+	} else {
+	    cal_p = RTC_SMOOTHCALIB_PLUSPULSES_RESET;
+	    cal_m = -cal;
+	}
+	HAL_RTCEx_SetSmoothCalib(&RTCHandle, RTC_SMOOTHCALIB_PERIOD_32SEC, cal_p, cal_m);
+	return mp_const_none;
+    } else {
+        // printf("CALR = 0x%x\n", (mp_uint_t) RTCHandle.Instance->CALR); // DEBUG
+	// Test if CALP bit is set in CALR:
+	if (RTCHandle.Instance->CALR & 0x8000) {
+	    cal = 512 - (RTCHandle.Instance->CALR & 0x1ff);
+	} else {
+	    cal = -(RTCHandle.Instance->CALR & 0x1ff);
+	}
+	return mp_obj_new_int(cal);
+    }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_calibration_obj, 1, 2, pyb_rtc_calibration);
+    
 STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
     { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_rtc_info_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_wakeup), (mp_obj_t)&pyb_rtc_wakeup_obj },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_calibration), (mp_obj_t)&pyb_rtc_calibration_obj },
 };
 STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
 
diff --git a/tests/pyb/rtc.py b/tests/pyb/rtc.py
index f2c96f160e0185963a254d85638304b542f57836..001553ac31c6d077fd06fa9ba941eedd806a3158 100644
--- a/tests/pyb/rtc.py
+++ b/tests/pyb/rtc.py
@@ -28,3 +28,24 @@ set_and_print((2016, 12, 31, 7, 23, 59, 0, 0))
 set_and_print((2016, 12, 31, 7, 23, 59, 1, 0))
 set_and_print((2016, 12, 31, 7, 23, 59, 59, 0))
 set_and_print((2099, 12, 31, 7, 23, 59, 59, 0))
+
+# check that calibration works correctly
+# save existing calibration value:
+cal_tmp = rtc.calibration()
+
+def set_and_print_calib(cal):
+    rtc.calibration(cal)
+    print(rtc.calibration())
+
+set_and_print_calib(512)
+set_and_print_calib(511)
+set_and_print_calib(345)
+set_and_print_calib(1)
+set_and_print_calib(0)
+set_and_print_calib(-1)
+set_and_print_calib(-123)
+set_and_print_calib(-510)
+set_and_print_calib(-511)
+
+# restore existing calibration value
+rtc.calibration(cal_tmp)
diff --git a/tests/pyb/rtc.py.exp b/tests/pyb/rtc.py.exp
index 43ea70d95ef721d98796a7618744ffb416ea2edc..d8d5e0f0a95f1c5b9c5d7914c090f5863f8ced96 100644
--- a/tests/pyb/rtc.py.exp
+++ b/tests/pyb/rtc.py.exp
@@ -14,3 +14,12 @@
 (2016, 12, 31, 7, 23, 59, 1)
 (2016, 12, 31, 7, 23, 59, 59)
 (2099, 12, 31, 7, 23, 59, 59)
+512
+511
+345
+1
+0
+-1
+-123
+-510
+-511