Skip to content

Commit a40f92e

Browse files
hw/mcu/dialog: Rework CMAC sleep calculations
Sleep time calculation on CMAC assumed incorrectly that wakeup fsm uses lpclk but in fact RC32K is used so we need to take it into account. To make things easier to handle on CMAC side we will calculate wakeup time on M33 side and pass it to CMAC instead of XTAL32M settle time. This way we don't really need to care about how wakeup fsm is configured. It's now expected that M33 will take care of RC32K calibration and will calculate proper wakeup time based on wakeup fsm settings and XTAL32M settle time, and then notify CMAC on any change so we can recalculate our min sleep time.
1 parent 1e32211 commit a40f92e

File tree

8 files changed

+89
-69
lines changed

8 files changed

+89
-69
lines changed

hw/drivers/ipc_cmac/include/ipc_cmac/shm.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ extern "C" {
3838

3939
#define CMAC_SHM_CB_MAGIC 0xc3ac
4040

41-
#define CMAC_SHM_CB_PENDING_OP_LP_CLK 0x0001
42-
#define CMAC_SHM_CB_PENDING_OP_RF_CAL 0x0002
41+
#define CMAC_SHM_CB_PENDING_OP_LPCLK_UPDATE 0x0001
42+
#define CMAC_SHM_CB_PENDING_OP_WAKEUP_UPDATE 0x0002
43+
#define CMAC_SHM_CB_PENDING_OP_RF_CAL 0x0004
4344

4445
#define CMAC_SHM_VECT_MAGIC 0xc3ac0001
4546
#define CMAC_SHM_VECT_CRASHINFO 0x00000001
@@ -58,8 +59,8 @@ struct cmac_shm_config {
5859
struct cmac_shm_ctrl {
5960
uint16_t magic;
6061
uint16_t pending_ops;
61-
uint16_t lp_clock_freq;
62-
uint16_t xtal32m_settle_us;
62+
uint16_t lpclk_freq;
63+
uint16_t wakeup_time_us;
6364
};
6465

6566
struct cmac_shm_mbox {

hw/drivers/ipc_cmac/include/ipc_cmac/shm_hs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ extern volatile struct cmac_shm_debugdata *g_cmac_shm_debugdata;
3838

3939
void cmac_host_init(void);
4040
void cmac_host_signal2cmac(void);
41+
42+
void cmac_host_lpclk_update(uint32_t freq);
43+
void cmac_host_wakeup_update(uint32_t wakeup_time_us);
4144
void cmac_host_rf_calibrate(void);
4245

4346
#ifdef __cplusplus

hw/drivers/ipc_cmac/src/shm_hs.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,7 @@ cmac_host_rand_chk_fill(void)
199199
static void
200200
cmac_host_lpclk_cb(uint32_t freq)
201201
{
202-
/* No need to wakeup CMAC if LP clock frequency did not change */
203-
if (g_cmac_shm_ctrl->lp_clock_freq == freq) {
204-
return;
205-
}
206-
207-
cmac_shm_lock();
208-
g_cmac_shm_ctrl->lp_clock_freq = freq;
209-
g_cmac_shm_ctrl->pending_ops |= CMAC_SHM_CB_PENDING_OP_LP_CLK;
210-
cmac_shm_unlock();
211-
212-
cmac_host_signal2cmac();
202+
cmac_host_lpclk_update(freq);
213203
}
214204

215205
static void
@@ -234,8 +224,7 @@ shm_configure(void)
234224
struct cmac_shm_trim *trim;
235225
uint32_t *trim_data;
236226

237-
g_cmac_shm_ctrl->xtal32m_settle_us =
238-
MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US);
227+
g_cmac_shm_ctrl->wakeup_time_us = 0;
239228

240229
trim = (struct cmac_shm_trim *)g_cmac_shm_trim;
241230
trim_data = trim->data;
@@ -444,6 +433,7 @@ cmac_host_init(void)
444433
cmac_start();
445434

446435
da1469x_lpclk_register_cmac_cb(cmac_host_lpclk_cb);
436+
cmac_host_wakeup_update(da1469x_sleep_wakeup_time_us_get());
447437

448438
#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) && MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
449439
/* Trim values are calculated on RF init, so are valid after synced with CMAC */
@@ -462,6 +452,36 @@ cmac_host_signal2cmac(void)
462452
da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
463453
}
464454

455+
void
456+
cmac_host_lpclk_update(uint32_t freq)
457+
{
458+
if (g_cmac_shm_ctrl->lpclk_freq == freq) {
459+
return;
460+
}
461+
462+
cmac_shm_lock();
463+
g_cmac_shm_ctrl->lpclk_freq = freq;
464+
g_cmac_shm_ctrl->pending_ops |= CMAC_SHM_CB_PENDING_OP_LPCLK_UPDATE;
465+
cmac_shm_unlock();
466+
467+
cmac_host_signal2cmac();
468+
}
469+
470+
void
471+
cmac_host_wakeup_update(uint32_t wakeup_time_us)
472+
{
473+
if (g_cmac_shm_ctrl->wakeup_time_us == wakeup_time_us) {
474+
return;
475+
}
476+
477+
cmac_shm_lock();
478+
g_cmac_shm_ctrl->wakeup_time_us = wakeup_time_us;
479+
g_cmac_shm_ctrl->pending_ops |= CMAC_SHM_CB_PENDING_OP_WAKEUP_UPDATE;
480+
cmac_shm_unlock();
481+
482+
cmac_host_signal2cmac();
483+
}
484+
465485
void
466486
cmac_host_rf_calibrate(void)
467487
{

hw/mcu/dialog/cmac/include/mcu/cmac_timer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ extern struct cmac_timer_ctrl g_cmac_timer_ctrl;
3535
void cmac_timer_init(void);
3636
void cmac_timer_slp_enable(uint32_t ticks);
3737
void cmac_timer_slp_disable(uint32_t exp_ticks);
38-
bool cmac_timer_slp_update(void);
38+
39+
void cmac_timer_slp_update(uint16_t lpclk_freq);
3940
bool cmac_timer_slp_is_ready(void);
4041
#if MYNEWT_VAL(MCU_SLP_TIMER_32K_ONLY)
4142
static inline uint32_t

hw/mcu/dialog/cmac/src/cmac_isr.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
* under the License.
1818
*/
1919

20+
#include <syscfg/syscfg.h>
2021
#include <CMAC.h>
2122
#include <mcu/cmac_pdc.h>
23+
#include <mcu/cmac_timer.h>
2224
#include <ipc_cmac/shm.h>
2325
#include <ipc_cmac/mbox.h>
2426
#include <ipc_cmac/rand.h>
@@ -40,8 +42,13 @@ SYS2CMAC_IRQHandler(void)
4042
cmac_mbox_read();
4143
cmac_rand_read();
4244

43-
if (pending_ops & CMAC_SHM_CB_PENDING_OP_LP_CLK) {
44-
cmac_sleep_recalculate();
45+
if (pending_ops & CMAC_SHM_CB_PENDING_OP_LPCLK_UPDATE) {
46+
cmac_timer_slp_update(g_cmac_shm_ctrl.lpclk_freq);
47+
cmac_sleep_wakeup_time_update(g_cmac_shm_ctrl.wakeup_time_us);
48+
}
49+
50+
if (pending_ops & CMAC_SHM_CB_PENDING_OP_WAKEUP_UPDATE) {
51+
cmac_sleep_wakeup_time_update(g_cmac_shm_ctrl.wakeup_time_us);
4552
}
4653

4754
if (pending_ops & CMAC_SHM_CB_PENDING_OP_RF_CAL) {

hw/mcu/dialog/cmac/src/cmac_priv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern "C" {
3030
extern int8_t g_cmac_pdc_cmac2sys;
3131

3232
void cmac_sleep(void);
33-
void cmac_sleep_recalculate(void);
33+
void cmac_sleep_wakeup_time_update(uint16_t wakeup_time_us);
3434

3535
#ifdef __cplusplus
3636
}

hw/mcu/dialog/cmac/src/cmac_sleep.c

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ static uint32_t g_retained_regs_val[ ARRAY_SIZE(retained_regs) ];
7272
static uint32_t g_mcu_wait_for_swd_start;
7373

7474
/* Minimum time required to go to sleep (until switch to SLP) and then wake up */
75-
static uint32_t g_mcu_wakeup_usecs_min;
75+
static uint32_t g_mcu_sleep_time_us_min;
7676

77-
static bool
78-
cmac_sleep_is_switch_allowed(void)
77+
static inline bool
78+
cmac_sleep_is_slp_allowed(void)
7979
{
8080
return (ble_phy_xcvr_state_get() == 0) &&
8181
!os_arch_cmac_pending_irq() &&
@@ -98,6 +98,10 @@ sub27(uint32_t x, uint32_t y)
9898
static bool
9999
cmac_sleep_is_deep_sleep_allowed(void)
100100
{
101+
if (g_mcu_sleep_time_us_min == 0) {
102+
return false;
103+
}
104+
101105
/*
102106
* We wait for SWD attach until high part of LL Timer increases by 2 which
103107
* is anywhere in 1-2ms range which is enough.
@@ -170,42 +174,31 @@ cmac_sleep_wait4xtal(void)
170174

171175
#define T_USEC(_t) (_t)
172176
#define T_LPTICK(_t) ((_t) * cmac_timer_slp_tick_us())
173-
#define T_LPTICK_U(_t) (T_LPTICK(_t) * 15 / 10)
174177

175-
static void
176-
cmac_sleep_calculate_wakeup_time(void)
178+
void
179+
cmac_sleep_wakeup_time_update(uint16_t wakeup_time_us)
177180
{
178-
assert(g_cmac_shm_ctrl.xtal32m_settle_us);
181+
if (wakeup_time_us == 0) {
182+
g_mcu_sleep_time_us_min = 0;
183+
return;
184+
}
179185

180-
g_mcu_wakeup_usecs_min =
186+
g_mcu_sleep_time_us_min =
181187
/*
182-
* We need ~12us to prepare for sleep before starting switch to SLP.
188+
* We need ~15us to prepare for sleep before starting switch to SLP.
183189
* Switch to SLP is done by switching SLP clock to LPCLK first and then
184190
* enabling SLP. The former has to be synchronized with negative edge of
185191
* LPCLK and the latter happens on positive edge of LPCLK so we just
186192
* assume 2 LPCLK ticks in worst case.
187193
*/
188-
T_USEC(12) + T_LPTICK(2) +
194+
T_USEC(15) + T_LPTICK(2) +
189195
/*
190-
* On wake up we assume fast wake up mode which has 3 phases that take
191-
* up to 2, 2 and 3 LPCLK ticks respectively (need to add some margin
192-
* here for worst-worst case). XTAL32M is started at 3rd phase and we
193-
* need to wait for it to settle before switch back to LLT. This is done
194-
* by disabling SLP and then switching SLP clock to PCLK. Both actions
195-
* are synchronized with LPCLK negative edge so take 2 LPCLK ticks in
196-
* worst case. Finally, LLP compensation takes around 50us.
196+
* After wakeup (this includes XTAL32M settling) we need to switch back
197+
* to LLT. This is done by disabling SLP and then switching SLP clock to
198+
* PCLK. Both actions are synchronized with LPCLK negative edge so take
199+
* 2 LPCLK ticks in worst case. Finally, LLT compensation takes ~50us.
197200
*/
198-
T_LPTICK_U(2) + T_LPTICK_U(2) +
199-
max(T_LPTICK_U(3), T_USEC(g_cmac_shm_ctrl.xtal32m_settle_us)) +
200-
T_LPTICK(2) + T_USEC(50);
201-
}
202-
203-
void
204-
cmac_sleep_recalculate(void)
205-
{
206-
if (cmac_timer_slp_update()) {
207-
cmac_sleep_calculate_wakeup_time();
208-
}
201+
T_USEC(wakeup_time_us) + T_LPTICK(2) + T_USEC(50);
209202
}
210203

211204
extern bool ble_rf_try_recalibrate(uint32_t idle_time_us);
@@ -234,7 +227,7 @@ cmac_sleep(void)
234227
* happen so need to make sure we can be up and running on time.
235228
*/
236229

237-
sleep_usecs = wakeup_at - cmac_timer_read32() - g_mcu_wakeup_usecs_min;
230+
sleep_usecs = wakeup_at - cmac_timer_read32() - g_mcu_sleep_time_us_min;
238231
if ((int32_t)sleep_usecs <= 0) {
239232
switch_to_slp = false;
240233
deep_sleep = false;
@@ -245,14 +238,15 @@ cmac_sleep(void)
245238
goto skip_sleep;
246239
}
247240

248-
sleep_lp_ticks = cmac_timer_usecs_to_lp_ticks(sleep_usecs);
241+
/* XXX off by one? */
242+
sleep_lp_ticks = cmac_timer_usecs_to_lp_ticks(sleep_usecs) - 1;
249243
if (sleep_lp_ticks <= 1) {
250244
switch_to_slp = false;
251245
deep_sleep = false;
252246
goto do_sleep;
253247
}
254248

255-
if (!cmac_sleep_is_switch_allowed()) {
249+
if (!cmac_sleep_is_slp_allowed()) {
256250
switch_to_slp = false;
257251
deep_sleep = false;
258252
} else if (!cmac_sleep_is_deep_sleep_allowed()) {

hw/mcu/dialog/cmac/src/cmac_timer.c

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
(CMAC_CM_EV_LATCHED_REG_EV1C_CLK_1US_X1_Msk << ((_num) - 1)))
3333

3434
struct cmac_timer_slp {
35-
uint32_t freq;
35+
uint16_t lpclk_freq;
3636
#if !MYNEWT_VAL(MCU_SLP_TIMER_32K_ONLY)
3737
uint32_t conv;
3838
uint32_t tick_ns;
@@ -334,36 +334,30 @@ cmac_timer_slp_disable(uint32_t exp_ticks)
334334
assert(CMAC->CM_LL_INT_STAT_REG == 0);
335335
}
336336

337-
bool
338-
cmac_timer_slp_update(void)
337+
void
338+
cmac_timer_slp_update(uint16_t lpclk_freq)
339339
{
340-
uint32_t lp_clock_freq;
341-
342-
lp_clock_freq = g_cmac_shm_ctrl.lp_clock_freq;
343-
344-
if (lp_clock_freq == g_cmac_timer_slp.freq) {
345-
return false;
340+
if (lpclk_freq == g_cmac_timer_slp.lpclk_freq) {
341+
return;
346342
}
347343

348-
g_cmac_timer_slp.freq = lp_clock_freq;
344+
g_cmac_timer_slp.lpclk_freq = lpclk_freq;
349345

350346
#if !MYNEWT_VAL(MCU_SLP_TIMER_32K_ONLY)
351-
if (g_cmac_timer_slp.freq) {
352-
g_cmac_timer_slp.conv = g_cmac_timer_slp.freq * 32768 / 1000000;
353-
g_cmac_timer_slp.tick_ns = 1000000000 / g_cmac_timer_slp.freq;
347+
if (g_cmac_timer_slp.lpclk_freq) {
348+
g_cmac_timer_slp.conv = g_cmac_timer_slp.lpclk_freq * 32768 / 1000000;
349+
g_cmac_timer_slp.tick_ns = 1000000000 / g_cmac_timer_slp.lpclk_freq;
354350
}
355351
#endif
356-
357-
return true;
358352
}
359353

360354
bool
361355
cmac_timer_slp_is_ready(void)
362356
{
363357
#if MYNEWT_VAL(MCU_SLP_TIMER_32K_ONLY)
364-
return g_cmac_timer_slp.freq == 32768;
358+
return g_cmac_timer_slp.lpclk_freq == 32768;
365359
#else
366-
return g_cmac_timer_slp.freq;
360+
return g_cmac_timer_slp.lpclk_freq != 0;
367361
#endif
368362
}
369363

0 commit comments

Comments
 (0)