summaryrefslogtreecommitdiff
path: root/stmhal/modpyb.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-12-08 21:32:55 +0000
committerDamien George <damien.p.george@gmail.com>2014-12-08 21:32:55 +0000
commit008251180d860f0bdf1b23c2772a2a7bfdc736fb (patch)
tree13a423594fd0dc815d658b48c3f6f82367a68e99 /stmhal/modpyb.c
parent46c3ab20049af16e97863e90e5761fae329f872a (diff)
stmhal: Enhance pyb.freq to configure bus (AHB, APB1, APB2) freqs.
This is useful if you need precise control over the speed of peripherals (eg SPI clock).
Diffstat (limited to 'stmhal/modpyb.c')
-rw-r--r--stmhal/modpyb.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 46ce0e098..98fa62ac2 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -173,15 +173,25 @@ STATIC mp_obj_t pyb_unique_id(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_unique_id_obj, pyb_unique_id);
-/// \function freq([sys_freq])
-///
-/// If given no arguments, returns a tuple of clock frequencies:
-/// (SYSCLK, HCLK, PCLK1, PCLK2).
-///
-/// If given an argument, sets the system frequency to that value in Hz.
-/// Eg freq(120000000) gives 120MHz. Note that not all values are
-/// supported and the largest supported frequency not greater than
-/// the given sys_freq will be selected.
+// get or set the MCU frequencies
+STATIC mp_uint_t pyb_freq_calc_ahb_div(mp_uint_t wanted_div) {
+ if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; }
+ else if (wanted_div <= 2) { return RCC_SYSCLK_DIV2; }
+ else if (wanted_div <= 4) { return RCC_SYSCLK_DIV4; }
+ else if (wanted_div <= 8) { return RCC_SYSCLK_DIV8; }
+ else if (wanted_div <= 16) { return RCC_SYSCLK_DIV16; }
+ else if (wanted_div <= 64) { return RCC_SYSCLK_DIV64; }
+ else if (wanted_div <= 128) { return RCC_SYSCLK_DIV128; }
+ else if (wanted_div <= 256) { return RCC_SYSCLK_DIV256; }
+ else { return RCC_SYSCLK_DIV512; }
+}
+STATIC mp_uint_t pyb_freq_calc_apb_div(mp_uint_t wanted_div) {
+ if (wanted_div <= 1) { return RCC_HCLK_DIV1; }
+ else if (wanted_div <= 2) { return RCC_HCLK_DIV2; }
+ else if (wanted_div <= 4) { return RCC_HCLK_DIV4; }
+ else if (wanted_div <= 8) { return RCC_HCLK_DIV8; }
+ else { return RCC_SYSCLK_DIV16; }
+}
STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
@@ -273,9 +283,23 @@ STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) {
// directly set the system clock source as desired
RCC_ClkInitStruct.SYSCLKSource = sysclk_source;
}
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+ wanted_sysclk *= 1000000;
+ if (n_args >= 2) {
+ // note: AHB freq required to be >= 14.2MHz for USB operation
+ RCC_ClkInitStruct.AHBCLKDivider = pyb_freq_calc_ahb_div(wanted_sysclk / mp_obj_get_int(args[1]));
+ } else {
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ }
+ if (n_args >= 3) {
+ RCC_ClkInitStruct.APB1CLKDivider = pyb_freq_calc_apb_div(wanted_sysclk / mp_obj_get_int(args[2]));
+ } else {
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
+ }
+ if (n_args >= 4) {
+ RCC_ClkInitStruct.APB2CLKDivider = pyb_freq_calc_apb_div(wanted_sysclk / mp_obj_get_int(args[3]));
+ } else {
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+ }
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
goto fail;
}
@@ -314,7 +338,7 @@ STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) {
__fatal_error("can't change freq");
}
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_freq_obj, 0, 1, pyb_freq);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_freq_obj, 0, 4, pyb_freq);
/// \function sync()
/// Sync all file systems.