Skip to content

Commit 840246a

Browse files
Keyur HariyaKeyur Hariya
authored andcommitted
Rework us_ticker and rtc_api/lp_ticker | Fix compiler warnings for spi_api
Simplify tickers to stop emulating 1us ticks by using native timer resolutions. Implement ticker get info functions. Separate rtc and lp ticker init status by implementing separate functions. Add mbed_critical include file to disable compiler warning messages.
1 parent 3bc2d2e commit 840246a

File tree

3 files changed

+110
-329
lines changed

3 files changed

+110
-329
lines changed
Lines changed: 79 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
2+
* Copyright (C) 2016,2018 Maxim Integrated Products, Inc., All Rights Reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -36,55 +36,37 @@
3636
#include "rtc.h"
3737
#include "lp.h"
3838

39-
#define PRESCALE_VAL RTC_PRESCALE_DIV_2_0 // Set the divider for the 4kHz clock
40-
#define SHIFT_AMT (RTC_PRESCALE_DIV_2_12 - PRESCALE_VAL)
39+
// LOG2 for 32-bit powers of 2
40+
#define LOG2_1(n) (((n) >= (1 << 1)) ? 1 : 0)
41+
#define LOG2_2(n) (((n) >= (1 << 2)) ? ( 2 + (LOG2_1((n) >> 2))) : LOG2_1(n))
42+
#define LOG2_4(n) (((n) >= (1 << 4)) ? ( 4 + (LOG2_2((n) >> 4))) : LOG2_2(n))
43+
#define LOG2_8(n) (((n) >= (1 << 8)) ? ( 8 + (LOG2_4((n) >> 8))) : LOG2_4(n))
44+
#define LOG2(n) (((n) >= (1 << 16)) ? (16 + (LOG2_8((n) >> 16))) : LOG2_8(n))
4145

42-
#define WINDOW 1000
46+
#define LP_TIMER_FREQ_HZ 4096
47+
#define LP_TIMER_PRESCALE RTC_PRESCALE_DIV_2_0
48+
#define LP_TIMER_RATE_HZ (LP_TIMER_FREQ_HZ >> LP_TIMER_PRESCALE)
49+
#define LP_TIMER_WIDTH 32
4350

44-
static int rtc_inited = 0;
45-
static volatile uint32_t overflow_cnt = 0;
46-
47-
static uint64_t rtc_read64(void);
48-
49-
//******************************************************************************
50-
static void overflow_handler(void)
51-
{
52-
overflow_cnt++;
53-
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
54-
}
51+
static volatile int rtc_inited = 0;
52+
static volatile int lp_ticker_inited = 0;
5553

5654
//******************************************************************************
57-
void rtc_init(void)
55+
static void init_rtc(void)
5856
{
59-
if (rtc_inited) {
60-
return;
61-
}
62-
rtc_inited = 1;
63-
64-
overflow_cnt = 0;
65-
6657
/* Enable power for RTC for all LPx states */
6758
MXC_PWRSEQ->reg0 |= (MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN |
6859
MXC_F_PWRSEQ_REG0_PWR_RTCEN_SLP);
6960

7061
/* Enable clock to synchronizers */
7162
CLKMAN_SetClkScale(CLKMAN_CLK_SYNC, CLKMAN_SCALE_DIV_1);
7263

73-
// Prepare interrupt handlers
74-
NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
75-
NVIC_EnableIRQ(RTC0_IRQn);
76-
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
77-
NVIC_EnableIRQ(RTC3_IRQn);
78-
79-
// Enable wakeup on RTC rollover
80-
LP_ConfigRTCWakeUp(0, 0, 0, 1);
81-
8264
/* RTC registers are only reset on a power cycle. Do not reconfigure the RTC
8365
* if it is already running.
8466
*/
8567
if (!RTC_IsActive()) {
86-
rtc_cfg_t cfg = {0};
87-
cfg.prescaler = PRESCALE_VAL;
68+
rtc_cfg_t cfg = { 0 };
69+
cfg.prescaler = LP_TIMER_PRESCALE;
8870
cfg.snoozeMode = RTC_SNOOZE_DISABLE;
8971

9072
int retval = RTC_Init(&cfg);
@@ -96,163 +78,128 @@ void rtc_init(void)
9678
}
9779

9880
//******************************************************************************
99-
void lp_ticker_init(void)
81+
static void overflow_handler(void)
82+
{
83+
MXC_RTCTMR->comp[1] += ((UINT32_MAX >> LOG2(LP_TIMER_RATE_HZ)) + 1);
84+
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
85+
}
86+
87+
//******************************************************************************
88+
void rtc_init(void)
10089
{
101-
rtc_init();
90+
if (rtc_inited) {
91+
return;
92+
}
93+
94+
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
95+
NVIC_EnableIRQ(RTC3_IRQn);
96+
// Enable wakeup on RTC overflow
97+
LP_ConfigRTCWakeUp(lp_ticker_inited, 0, 0, 1);
98+
init_rtc();
99+
rtc_inited = 1;
102100
}
103101

104102
//******************************************************************************
105103
void rtc_free(void)
106104
{
107-
if (RTC_IsActive()) {
108-
// Clear and disable RTC
109-
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR;
110-
RTC_Stop();
105+
if (rtc_inited) {
106+
rtc_inited = 0;
107+
if (lp_ticker_inited) {
108+
RTC_DisableINT(MXC_F_RTC_FLAGS_OVERFLOW);
109+
} else {
110+
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR;
111+
RTC_Stop();
112+
}
111113
}
112114
}
113115

114116
//******************************************************************************
115117
int rtc_isenabled(void)
116118
{
117-
return RTC_IsActive();
119+
return rtc_inited;
118120
}
119121

120122
//******************************************************************************
121-
time_t rtc_read(void)
123+
void rtc_write(time_t t)
122124
{
123-
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
124-
uint32_t ovf1, ovf2;
125-
126-
// Make sure RTC is setup before trying to read
127125
if (!rtc_inited) {
128126
rtc_init();
129127
}
130128

131-
// Ensure coherency between overflow_cnt and timer
132-
do {
133-
ovf_cnt_1 = overflow_cnt;
134-
ovf1 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
135-
timer_cnt = RTC_GetCount();
136-
ovf2 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
137-
ovf_cnt_2 = overflow_cnt;
138-
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
129+
MXC_RTCTMR->comp[1] = t - (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ));
139130

140-
// Account for an unserviced interrupt
141-
if (ovf1) {
142-
ovf_cnt_1++;
143-
}
144-
145-
return (timer_cnt >> SHIFT_AMT) + (ovf_cnt_1 << (32 - SHIFT_AMT));
131+
// Wait for pending transactions
132+
while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING);
146133
}
147134

148135
//******************************************************************************
149-
static uint64_t rtc_read64(void)
136+
time_t rtc_read(void)
150137
{
151-
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
152-
uint32_t ovf1, ovf2;
153-
uint64_t current_us;
154-
155-
// Make sure RTC is setup before trying to read
156138
if (!rtc_inited) {
157139
rtc_init();
158140
}
159141

160-
// Ensure coherency between overflow_cnt and timer
161-
do {
162-
ovf_cnt_1 = overflow_cnt;
163-
ovf1 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
164-
timer_cnt = RTC_GetCount();
165-
ovf2 = RTC_GetFlags() & MXC_F_RTC_FLAGS_OVERFLOW;
166-
ovf_cnt_2 = overflow_cnt;
167-
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
142+
return (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)) + MXC_RTCTMR->comp[1];
143+
}
168144

169-
// Account for an unserviced interrupt
170-
if (ovf1) {
171-
ovf_cnt_1++;
145+
//******************************************************************************
146+
void lp_ticker_init(void)
147+
{
148+
if (lp_ticker_inited) {
149+
return;
172150
}
173151

174-
current_us = (((uint64_t)timer_cnt * 1000000) >> SHIFT_AMT) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - SHIFT_AMT));
175-
176-
return current_us;
152+
NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
153+
NVIC_EnableIRQ(RTC0_IRQn);
154+
init_rtc();
155+
lp_ticker_inited = 1;
177156
}
178157

179158
//******************************************************************************
180-
void rtc_write(time_t t)
159+
uint32_t lp_ticker_read(void)
181160
{
182-
// Make sure RTC is setup before accessing
183-
if (!rtc_inited) {
184-
rtc_init();
185-
}
186-
187-
RTC_Stop();
188-
RTC_SetCount(t << SHIFT_AMT);
189-
overflow_cnt = t >> (32 - SHIFT_AMT);
190-
RTC_Start();
161+
return MXC_RTCTMR->timer;
191162
}
192163

193164
//******************************************************************************
194165
void lp_ticker_set_interrupt(timestamp_t timestamp)
195166
{
196-
uint32_t comp_value;
197-
uint64_t curr_ts64;
198-
uint64_t ts64;
199-
200-
// Note: interrupts are disabled before this function is called.
201-
202-
// Disable the alarm while it is prepared
203-
RTC_DisableINT(MXC_F_RTC_INTEN_COMP0);
204-
205-
curr_ts64 = rtc_read64();
206-
ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL);
207-
208-
// If this event is older than a recent window, it must be in the future
209-
if ((ts64 < (curr_ts64 - WINDOW)) && ((curr_ts64 - WINDOW) < curr_ts64)) {
210-
ts64 += 0x100000000ULL;
211-
}
212-
213-
uint32_t timer = RTC_GetCount();
214-
if (ts64 <= curr_ts64) {
215-
// This event has already occurred. Set the alarm to expire immediately.
216-
comp_value = timer + 1;
217-
} else {
218-
comp_value = (ts64 << SHIFT_AMT) / 1000000;
219-
}
220-
221-
// Ensure that the compare value is far enough in the future to guarantee the interrupt occurs.
222-
if ((comp_value < (timer + 2)) && (comp_value > (timer - 10))) {
223-
comp_value = timer + 2;
224-
}
225-
226-
MXC_RTCTMR->comp[0] = comp_value;
167+
MXC_RTCTMR->comp[0] = timestamp;
227168
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
228-
RTC_EnableINT(MXC_F_RTC_INTEN_COMP0);
169+
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
229170

230-
// Enable wakeup from RTC
231-
LP_ConfigRTCWakeUp(1, 0, 0, 1);
171+
// Enable wakeup from RTC compare 0
172+
LP_ConfigRTCWakeUp(1, 0, 0, rtc_inited);
232173

233174
// Wait for pending transactions
234175
while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING);
235176
}
236177

237-
void lp_ticker_fire_interrupt(void)
178+
//******************************************************************************
179+
void lp_ticker_disable_interrupt(void)
238180
{
239-
NVIC_SetPendingIRQ(RTC0_IRQn);
181+
RTC_DisableINT(MXC_F_RTC_INTEN_COMP0);
240182
}
241183

242184
//******************************************************************************
243-
inline void lp_ticker_disable_interrupt(void)
185+
void lp_ticker_clear_interrupt(void)
244186
{
245-
RTC_DisableINT(MXC_F_RTC_INTEN_COMP0);
187+
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
246188
}
247189

248190
//******************************************************************************
249-
inline void lp_ticker_clear_interrupt(void)
191+
void lp_ticker_fire_interrupt(void)
250192
{
251-
RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS);
193+
NVIC_SetPendingIRQ(RTC0_IRQn);
252194
}
253195

254196
//******************************************************************************
255-
inline uint32_t lp_ticker_read(void)
197+
const ticker_info_t *lp_ticker_get_info(void)
256198
{
257-
return rtc_read64();
199+
static const ticker_info_t info = {
200+
LP_TIMER_RATE_HZ,
201+
LP_TIMER_WIDTH
202+
};
203+
204+
return &info;
258205
}

targets/TARGET_Maxim/TARGET_MAX32625/spi_api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
*/
3333

3434
#include "mbed_assert.h"
35+
#include "mbed_critical.h"
3536
#include "spi_api.h" // mbed HAL
3637
#include "spim_regs.h" // bare metal
3738
#include "spim.h" // Maxim CMSIS driver

0 commit comments

Comments
 (0)