Skip to content

Commit 7799be6

Browse files
committed
PSOC: Modify lp_ticker to 32 bit
Needed for PSoC to deep-sleep for more than 2 seconds Max sleep with 16 bit lp_ticker (before this change) : 2sec Max sleep with 32 bit lp_ticker (after this change) : 36hours
1 parent 4af3c38 commit 7799be6

File tree

1 file changed

+63
-32
lines changed

1 file changed

+63
-32
lines changed

targets/TARGET_Cypress/TARGET_PSOC6/lp_ticker.c

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,29 +40,38 @@
4040
#define LPT_INTERRUPT_PRIORITY 6
4141
#define LPT_INTERRUPT_SOURCE srss_interrupt_mcwdt_1_IRQn
4242
#endif
43-
#define LPT_MCWDT_DELAY_WAIT 0 // Recommended value is 93, but then we fail function execution time test.
44-
43+
#define LPT_MCWDT_DELAY_WAIT 93 // Recommended value is 93, but then we fail function execution time test.
44+
#define LPT_MCWDT_DELAY_NO_WAIT 0
4545
#if !defined (CY_CFG_SYSCLK_CLKLF_FREQ_HZ)
4646
#define CY_CFG_SYSCLK_CLKLF_FREQ_HZ 32768UL /* Default to 32K ILO */
4747
#endif /* CY_CFG_SYSCLK_CLKLF_FREQ_HZ */
4848

49+
#define MCWDT_COUNTER0_MAX_COUNT (0xffffUL)
50+
#define MCWDT_COUNTER1_MAX_COUNT (0xffffUL)
51+
#define MCWDT_COUNTER2_MAX_COUNT (0xffffffffUL)
52+
#define MAX_MCWDT_DURATION_SEC (35UL*60UL*60UL*1000UL)
53+
#define PLATFORM_MAX_DEEP_SLEEP_TICKS (MAX_MCWDT_DURATION_SEC*CY_CFG_SYSCLK_CLKLF_FREQ_HZ)
54+
#define MAX_MCWDT_COUNTER0_DURATION_SEC ((MCWDT_COUNTER0_MAX_COUNT + 1)/(CY_CFG_SYSCLK_CLKLF_FREQ_HZ))
55+
#define LPT_MCWDT_CTRL (CY_MCWDT_CTR0 | CY_MCWDT_CTR1 | CY_MCWDT_CTR2)
56+
4957
static const ticker_info_t lp_ticker_info = {
5058
.frequency = CY_CFG_SYSCLK_CLKLF_FREQ_HZ,
51-
.bits = 16UL,
59+
.bits = 32UL,
5260
};
5361

5462
static bool lpt_init_done = false;
63+
5564
// Timer h/w configuration.
5665
static cy_stc_mcwdt_config_t config = {
57-
.c0Match = 0,
58-
.c1Match = 0,
66+
.c0Match = MCWDT_COUNTER0_MAX_COUNT,
67+
.c1Match = MCWDT_COUNTER1_MAX_COUNT,
5968
.c0Mode = CY_MCWDT_MODE_INT,
60-
.c1Mode = CY_MCWDT_MODE_NONE,
61-
.c2ToggleBit = 0,
69+
.c1Mode = CY_MCWDT_MODE_INT,
6270
.c2Mode = CY_MCWDT_MODE_NONE,
71+
.c2ToggleBit = 0,
6372
.c0ClearOnMatch = false,
6473
.c1ClearOnMatch = false,
65-
.c0c1Cascade = false,
74+
.c0c1Cascade = true,
6675
.c1c2Cascade = false
6776
};
6877

@@ -77,7 +86,6 @@ static cy_stc_sysint_t lpt_sysint_config = {
7786
.intrPriority = LPT_INTERRUPT_PRIORITY
7887
};
7988

80-
8189
void lp_ticker_init(void)
8290
{
8391
lp_ticker_disable_interrupt();
@@ -100,14 +108,14 @@ void lp_ticker_init(void)
100108
Cy_MCWDT_Init(LPT_MCWDT_UNIT, &config);
101109
Cy_SysInt_Init(&lpt_sysint_config, lp_ticker_irq_handler);
102110
NVIC_EnableIRQ(lpt_sysint_config.intrSrc);
103-
Cy_MCWDT_Enable(LPT_MCWDT_UNIT, CY_MCWDT_CTR0, LPT_MCWDT_DELAY_WAIT);
111+
Cy_MCWDT_Enable(LPT_MCWDT_UNIT, LPT_MCWDT_CTRL, LPT_MCWDT_DELAY_WAIT);
104112
lpt_init_done = true;
105113
}
106114

107115
void lp_ticker_free(void)
108116
{
109117
NVIC_DisableIRQ(lpt_sysint_config.intrSrc);
110-
Cy_MCWDT_Disable(LPT_MCWDT_UNIT, CY_MCWDT_CTR0, LPT_MCWDT_DELAY_WAIT);
118+
Cy_MCWDT_Disable(LPT_MCWDT_UNIT, LPT_MCWDT_CTRL, LPT_MCWDT_DELAY_WAIT);
111119
#ifdef TARGET_MCU_PSOC6_M0
112120
cy_m0_nvic_release_channel(CY_LP_TICKER_IRQN_ID, lpt_sysint_config.intrSrc);
113121
lpt_sysint_config.intrSrc = (IRQn_Type)(-1);
@@ -117,32 +125,55 @@ void lp_ticker_free(void)
117125

118126
uint32_t lp_ticker_read(void)
119127
{
120-
return Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0);
128+
return Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER2);
121129
}
122130

123131
void lp_ticker_set_interrupt(timestamp_t timestamp)
124132
{
125-
uint16_t delay;
126-
uint16_t current = Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0);
127-
uint16_t new_ts = (uint16_t)timestamp;
128-
delay = new_ts - current;
129-
// Make sure the event is set for the future. Mbed internally will not schedule
130-
// delays longer than 0x7000, so too large delay means it should occur already.
131-
// MCWDT has internal delay of about 1.5 LF clock ticks, so this is the minimum
132-
// that we can schedule.
133-
if ((delay < 3) || (delay > (uint16_t)(-3))) {
134-
// Cheating a bit here.
135-
new_ts = current + 3;
136-
}
133+
uint32_t delay;
134+
uint16_t c0_count = Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0);
135+
uint16_t c1_count = Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER1);
136+
uint32_t c2_count = Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER2);
137137

138-
// Cypress PDL manual says that valid match range is 1..65535.
139-
if (new_ts == 0) {
140-
new_ts = 1;
141-
}
138+
uint32_t new_ts = (uint32_t)timestamp;
139+
140+
delay = new_ts - c2_count;
141+
lp_ticker_clear_interrupt();
142142

143-
// Set up and enable match interrupt.
144-
Cy_MCWDT_SetMatch(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0, new_ts, LPT_MCWDT_DELAY_WAIT);
145-
Cy_MCWDT_SetInterruptMask(LPT_MCWDT_UNIT, CY_MCWDT_CTR0);
143+
if (delay > MCWDT_COUNTER0_MAX_COUNT) {
144+
uint32_t c0_increment = delay % (MCWDT_COUNTER0_MAX_COUNT + 1);
145+
uint32_t counter0_count = (c0_count + delay) % (MCWDT_COUNTER0_MAX_COUNT + 1);
146+
uint32_t counter1_count = (delay - c0_increment) / (MCWDT_COUNTER1_MAX_COUNT + 1) ;
147+
counter1_count = (c1_count + counter1_count) % (MCWDT_COUNTER1_MAX_COUNT + 1);
148+
149+
if(counter1_count == 0) {
150+
counter1_count = 1;
151+
}
152+
if(counter0_count == 0) {
153+
counter0_count = 1;
154+
}
155+
Cy_MCWDT_SetMatch(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER1, counter1_count, LPT_MCWDT_DELAY_NO_WAIT);
156+
Cy_MCWDT_SetMatch(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0, counter0_count, LPT_MCWDT_DELAY_NO_WAIT);
157+
Cy_MCWDT_SetInterruptMask(LPT_MCWDT_UNIT, CY_MCWDT_CTR1);
158+
159+
}
160+
else {
161+
uint16_t counter0_count = c0_count + (uint16_t)delay;
162+
163+
// MCWDT has internal delay of about 1.5 LF clock ticks, so this is the minimum
164+
// that we can schedule.
165+
if (delay < 3) {
166+
// Cheating a bit here.
167+
counter0_count = c0_count + 3;
168+
}
169+
170+
if(counter0_count == 0) {
171+
counter0_count = 1;
172+
}
173+
Cy_MCWDT_SetMatch(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER1, MCWDT_COUNTER1_MAX_COUNT, LPT_MCWDT_DELAY_NO_WAIT);
174+
Cy_MCWDT_SetMatch(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0, counter0_count, LPT_MCWDT_DELAY_NO_WAIT);
175+
Cy_MCWDT_SetInterruptMask(LPT_MCWDT_UNIT, CY_MCWDT_CTR0);
176+
}
146177
}
147178

148179
void lp_ticker_disable_interrupt(void)
@@ -152,7 +183,7 @@ void lp_ticker_disable_interrupt(void)
152183

153184
void lp_ticker_clear_interrupt(void)
154185
{
155-
Cy_MCWDT_ClearInterrupt(LPT_MCWDT_UNIT, CY_MCWDT_CTR0);
186+
Cy_MCWDT_ClearInterrupt(LPT_MCWDT_UNIT, (CY_MCWDT_CTR0 | CY_MCWDT_CTR1));
156187
}
157188

158189
void lp_ticker_fire_interrupt(void)

0 commit comments

Comments
 (0)