Skip to content

Commit 63412bb

Browse files
author
Cruz Monrreal
authored
Merge pull request #6605 from maximmbed/max32625-rework-ticker
Rework us_ticker and rtc_api/lp_ticker | Fix compiler warning for spi_api
2 parents b630691 + b594ec2 commit 63412bb

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)