From f2f9baff5f37ebabd9bee424b31eaa49bf66ed53 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 16 Nov 2020 17:34:22 +0100 Subject: [PATCH] cmac: Update initialization and calibration routines Make sure we initialize RF part only once, that is we only need to read trim values, TX power configuration and do full calibration once after boot. Partial calibration is done on host request in idle time when RF is not used. --- nimble/drivers/dialog_cmac/src/ble_phy.c | 1 - nimble/drivers/dialog_cmac/src/ble_rf.c | 132 ++++++++++-------- nimble/drivers/dialog_cmac/src/ble_rf_priv.h | 1 - .../include/cmac_driver/cmac_host.h | 1 + .../dialog_cmac/cmac_driver/src/cmac_host.c | 10 ++ 5 files changed, 86 insertions(+), 59 deletions(-) diff --git a/nimble/drivers/dialog_cmac/src/ble_phy.c b/nimble/drivers/dialog_cmac/src/ble_phy.c index 20c64096c..b0d8f59ae 100644 --- a/nimble/drivers/dialog_cmac/src/ble_phy.c +++ b/nimble/drivers/dialog_cmac/src/ble_phy.c @@ -1198,7 +1198,6 @@ ble_phy_init(void) #endif ble_rf_init(); - ble_rf_calibrate_once(); /* * 9_0_EQ_X can be linked to start RX/TX so we'll use this one for diff --git a/nimble/drivers/dialog_cmac/src/ble_rf.c b/nimble/drivers/dialog_cmac/src/ble_rf.c index 6197c4518..806f4ea82 100644 --- a/nimble/drivers/dialog_cmac/src/ble_rf.c +++ b/nimble/drivers/dialog_cmac/src/ble_rf.c @@ -45,6 +45,7 @@ struct ble_phy_rf_data { uint32_t trim_val1_tx_2; uint32_t trim_val2_tx; uint32_t trim_val2_rx; + uint8_t calibrate_req; }; static struct ble_phy_rf_data g_ble_phy_rf_data; @@ -324,6 +325,7 @@ ble_rf_calibration_1(void) bkp[10] = get_reg32(0x40020000); bkp[11] = get_reg32(0x40022000); + set_reg32(0x4002103c, 0x0124a21f); set_reg32(0x40020208, 0); set_reg32(0x40020250, 0); set_reg32(0x40020254, 0); @@ -388,6 +390,7 @@ ble_rf_calibration_2(void) uint32_t k1; set_reg8(0x40020005, 3); + set_reg32(0x40022000, 0x00000300); set_reg32_bits(0x40022004, 0x0000007f, 20); bkp[0] = get_reg32(0x40022040); set_reg32(0x40022040, 0xffffffff); @@ -464,6 +467,58 @@ ble_rf_calibration_2(void) g_ble_phy_rf_data.cal_res_2 = k1; } +static void +ble_rf_calibrate_int(uint8_t mask) +{ + __disable_irq(); + + ble_rf_enable(); + delay_us(20); + + ble_rf_synth_disable(); + ble_rf_synth_enable(); + ble_rf_synth_apply_settings(); + set_reg8(0x40020005, 1); + + if (mask & RF_CALIBRATION_0) { + ble_rf_calibration_0(); + } + if (mask & RF_CALIBRATION_1) { + ble_rf_calibration_1(); + } + if (mask & RF_CALIBRATION_2) { + ble_rf_calibration_2(); + } + + ble_rf_disable(); + + __enable_irq(); + +#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) + g_cmac_shared_data.debug.cal_res_1 = g_ble_phy_rf_data.cal_res_1; + g_cmac_shared_data.debug.cal_res_2 = g_ble_phy_rf_data.cal_res_2; +#endif +} + +bool +ble_rf_try_recalibrate(uint32_t idle_time_us) +{ + /* Run recalibration if we have at least 1ms of time to spare and RF is + * currently disabled. Calibration is much shorter than 1ms, but that gives + * us good margin to make sure we can finish before next event. + */ + if (!g_ble_phy_rf_data.calibrate_req || (idle_time_us < 1000) || + ble_rf_is_enabled()) { + return false; + } + + ble_rf_calibrate_int(RF_CALIBRATION_2); + + g_ble_phy_rf_data.calibrate_req = 0; + + return true; +} + static uint32_t ble_rf_find_trim_reg(volatile uint32_t *tv, unsigned len, uint32_t reg) { @@ -481,8 +536,15 @@ ble_rf_find_trim_reg(volatile uint32_t *tv, unsigned len, uint32_t reg) void ble_rf_init(void) { + static bool done = false; uint32_t val; + ble_rf_disable(); + + if (done) { + return; + } + val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode1, g_cmac_shared_data.trim.rfcu_mode1_len, 0x4002004c); @@ -520,6 +582,17 @@ ble_rf_init(void) g_cmac_shared_data.debug.trim_val2_tx = g_ble_phy_rf_data.trim_val2_tx; g_cmac_shared_data.debug.trim_val2_rx = g_ble_phy_rf_data.trim_val2_rx; #endif + + ble_rf_rfcu_enable(); + ble_rf_rfcu_apply_settings(); + g_ble_phy_rf_data.tx_power_cfg1 = get_reg32_bits(0x500000a4, 0xf0); + g_ble_phy_rf_data.tx_power_cfg2 = get_reg32_bits(0x40020238, 0x000003e0); + g_ble_phy_rf_data.tx_power_cfg3 = 0; + ble_rf_rfcu_disable(); + + ble_rf_calibrate_int(RF_CALIBRATION_0 | RF_CALIBRATION_1 | RF_CALIBRATION_2); + + done = true; } void @@ -566,65 +639,10 @@ ble_rf_is_enabled(void) return get_reg32_bits(0x40020008, 5) == 5; } -static void -ble_rf_calibrate_int(uint8_t mask) -{ - ble_rf_rfcu_enable(); - ble_rf_rfcu_apply_settings(); - ble_rf_ldo_on(); - delay_us(20); - - ble_rf_synth_disable(); - ble_rf_synth_enable(); - ble_rf_synth_apply_settings(); - set_reg8(0x40020005, 1); - - if (mask & RF_CALIBRATION_0) { - ble_rf_calibration_0(); - } - if (mask & RF_CALIBRATION_1) { - ble_rf_calibration_1(); - } - if (mask & RF_CALIBRATION_2) { - ble_rf_calibration_2(); - } - - ble_rf_ldo_off(); - ble_rf_rfcu_disable(); - -#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) - g_cmac_shared_data.debug.cal_res_1 = g_ble_phy_rf_data.cal_res_1; - g_cmac_shared_data.debug.cal_res_2 = g_ble_phy_rf_data.cal_res_2; -#endif -} - void -ble_rf_calibrate(void) +ble_rf_calibrate_req(void) { - ble_rf_calibrate_int(RF_CALIBRATION_1 | RF_CALIBRATION_2); -} - -void -ble_rf_calibrate_once(void) -{ - static bool calibrated = false; - - if (calibrated) { - return; - } - - ble_rf_rfcu_enable(); - ble_rf_rfcu_apply_settings(); - - g_ble_phy_rf_data.tx_power_cfg1 = get_reg32_bits(0x500000a4, 0xf0); - g_ble_phy_rf_data.tx_power_cfg2 = get_reg32_bits(0x40020238, 0x000003e0); - g_ble_phy_rf_data.tx_power_cfg3 = 0; - - ble_rf_rfcu_disable(); - - ble_rf_calibrate_int(RF_CALIBRATION_0 | RF_CALIBRATION_1 | RF_CALIBRATION_2); - - calibrated = true; + g_ble_phy_rf_data.calibrate_req = 1; } void diff --git a/nimble/drivers/dialog_cmac/src/ble_rf_priv.h b/nimble/drivers/dialog_cmac/src/ble_rf_priv.h index 358300d3e..50c2e4a78 100644 --- a/nimble/drivers/dialog_cmac/src/ble_rf_priv.h +++ b/nimble/drivers/dialog_cmac/src/ble_rf_priv.h @@ -28,7 +28,6 @@ bool ble_rf_is_enabled(void); void ble_rf_configure(void); void ble_rf_calibrate(void); -void ble_rf_calibrate_once(void); void ble_rf_setup_tx(uint8_t rf_chan, uint8_t mode); void ble_rf_setup_rx(uint8_t rf_chan, uint8_t mode); diff --git a/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h b/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h index 22193c74d..50d867552 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h +++ b/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h @@ -26,6 +26,7 @@ extern "C" { void cmac_host_init(void); void cmac_host_signal2cmac(void); +void cmac_host_rf_calibrate(void); #ifdef __cplusplus } diff --git a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c index d07d1279f..df81c582b 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c +++ b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c @@ -183,6 +183,16 @@ cmac_host_print_trim(const char *name, const uint32_t *tv, unsigned len) } #endif +void +cmac_host_rf_calibrate(void) +{ + cmac_shared_lock(); + g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_RF_CAL; + cmac_shared_unlock(); + + cmac_host_signal2cmac(); +} + void cmac_host_init(void) {