Skip to content

Commit ee7cefc

Browse files
committed
Add RTC and Sleep to CM3DS
This commit represents the second stage of the low power implementations that are required from Mbed 5.10 onwards. Besides the default hal implementations (rtc_api.c and sleep.c), the PL031 RTC's native driver needed to be added. Due to HW limitations in SSE-050 and the CM3DS, Deep Sleep couldn't be implemented, therefore it is functionally identical to Sleep (WFI). Change-Id: Ibed2bdb452f48c98024dc7ef07fb51a4425e0a80 Signed-off-by: Bence Kaposzta <[email protected]>
1 parent 1b79231 commit ee7cefc

File tree

8 files changed

+494
-10
lines changed

8 files changed

+494
-10
lines changed

targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@
4949
*/
5050
#define USEC_TIMER_BIT_WIDTH 32U
5151
#define USEC_REPORTED_SHIFT 5U
52-
#define USEC_REPORTED_FREQ_HZ (TIMERS_INPUT_CLOCK_FREQ_HZ >> USEC_REPORTED_SHIFT)
52+
#define USEC_REPORTED_FREQ_HZ (TIMERS_INPUT_CLOCK_FREQ_HZ >> \
53+
USEC_REPORTED_SHIFT)
5354
#define USEC_REPORTED_BITS (USEC_TIMER_BIT_WIDTH - USEC_REPORTED_SHIFT)
5455

5556
/* mbed low power ticker configuration */
@@ -72,6 +73,9 @@
7273
(LP_TIMER_HW_PRESCALER+LP_REPORTED_SHIFT))
7374
#define LP_REPORTED_BITS (LP_TIMER_BIT_WIDTH - LP_REPORTED_SHIFT)
7475

76+
/* RTC PL031 */
77+
#define RTC_PL031
78+
7579
/* ARM GPIO */
7680
#define ARM_GPIO0
7781
#define ARM_GPIO1
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
* Copyright (c) 2018 Arm Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* \file rtc_pl031_drv.c
19+
* \brief Implementation of the PL031 Real Time Clock (RTC) native driver.
20+
*
21+
* \note PL031 device specific definitions based on
22+
* real_time_clock_pl031_r1p3_technical_reference_manual.pdf
23+
* which is available from http://infocenter.arm.com.
24+
*/
25+
26+
#include <stddef.h>
27+
#include "rtc_pl031_drv.h"
28+
29+
/**
30+
* \brief Structure to access the memory mapped registers of the PL031.
31+
*/
32+
struct rtc_pl031_dev_reg_map_t {
33+
volatile uint32_t rtcdr; /*!< Data Register */
34+
volatile uint32_t rtcmr; /*!< Match Register */
35+
volatile uint32_t rtclr; /*!< Load Register */
36+
volatile uint32_t rtccr; /*!< Control Register */
37+
volatile uint32_t rtcimsc;
38+
/*!< Interrupt Mask Set or Clear Register */
39+
volatile uint32_t rtcris; /*!< Raw Interrupt Status Register */
40+
volatile uint32_t rtcmis; /*!< Masked Interrupt Status Register */
41+
volatile uint32_t rtcicr; /*!< Interrupt Clear Register */
42+
volatile uint32_t reserved[1008]; /*!< Reserved from Offset 0x20-0xFDC */
43+
volatile uint32_t rtcperiphid0; /*!< Peripheral ID0 Register */
44+
volatile uint32_t rtcperiphid1; /*!< Peripheral ID1 Register */
45+
volatile uint32_t rtcperiphid2; /*!< Peripheral ID2 Register */
46+
volatile uint32_t rtcperiphid3; /*!< Peripheral ID3 Register */
47+
volatile uint32_t rtcpcellid0; /*!< Primary Cell ID0 Register */
48+
volatile uint32_t rtcpcellid1; /*!< Primary Cell ID1 Register */
49+
volatile uint32_t rtcpcellid2; /*!< Primary Cell ID2 Register */
50+
volatile uint32_t rtcpcellid3; /*!< Primary Cell ID3 Register */
51+
};
52+
53+
/* RTC Control Register */
54+
#define RTC_PL031_RTCCR_ENABLE_POS 0x0U
55+
#define RTC_PL031_RTCCR_ENABLE_MSK (0x1U << RTC_PL031_RTCCR_ENABLE_POS)
56+
57+
/* RTC Interrupt Mask Set or Clear Register */
58+
#define RTC_PL031_RTCIMSC_SET_CLEAR_POS 0x0U
59+
#define RTC_PL031_RTCIMSC_SET_CLEAR_MSK (0x1U << \
60+
RTC_PL031_RTCIMSC_SET_CLEAR_POS)
61+
62+
/* RTC RAW Interrupt Status Register */
63+
#define RTC_PL031_RTCRIS_STATUS_POS 0x0U
64+
#define RTC_PL031_RTCRIS_STATUS_MSK (0x1U << RTC_PL031_RTCRIS_STATUS_POS)
65+
66+
/* RTC Masked Interrupt Status Register */
67+
#define RTC_PL031_RTCMIS_STATUS_POS 0x0U
68+
#define RTC_PL031_RTCMIS_STATUS_MSK (0x1U << RTC_PL031_RTCMIS_STATUS_POS)
69+
70+
/* RTC Interrupt Clear Register */
71+
#define RTC_PL031_RTCICR_CLEAR_POS 0x0U
72+
#define RTC_PL031_RTCICR_CLEAR_MSK (0x1U << RTC_PL031_RTCICR_CLEAR_POS)
73+
74+
bool rtc_pl031_init(struct rtc_pl031_dev_t* dev)
75+
{
76+
struct rtc_pl031_dev_reg_map_t* p_rtc;
77+
78+
if (dev == NULL) {
79+
return false;
80+
}
81+
82+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
83+
p_rtc->rtcmr = 0U;
84+
p_rtc->rtcicr = RTC_PL031_RTCICR_CLEAR_MSK;
85+
return true;
86+
}
87+
88+
bool rtc_pl031_dev_enable(struct rtc_pl031_dev_t* dev)
89+
{
90+
struct rtc_pl031_dev_reg_map_t* p_rtc;
91+
92+
if (dev == NULL) {
93+
return false;
94+
}
95+
96+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
97+
p_rtc->rtccr = RTC_PL031_RTCCR_ENABLE_MSK;
98+
return true;
99+
}
100+
101+
bool rtc_pl031_dev_disable(struct rtc_pl031_dev_t* dev)
102+
{
103+
struct rtc_pl031_dev_reg_map_t* p_rtc;
104+
105+
if (dev == NULL) {
106+
return false;
107+
}
108+
109+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
110+
p_rtc->rtccr = 0U;
111+
return true;
112+
}
113+
114+
bool rtc_pl031_read_current_time(struct rtc_pl031_dev_t* dev, uint32_t *seconds)
115+
{
116+
struct rtc_pl031_dev_reg_map_t* p_rtc;
117+
118+
if (dev == NULL || seconds == NULL) {
119+
return false;
120+
}
121+
122+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
123+
*seconds = (uint32_t)p_rtc->rtcdr;
124+
return true;
125+
}
126+
127+
bool rtc_pl031_write_current_time(struct rtc_pl031_dev_t* dev, uint32_t seconds)
128+
{
129+
struct rtc_pl031_dev_reg_map_t* p_rtc;
130+
131+
if (dev == NULL) {
132+
return false;
133+
}
134+
135+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
136+
p_rtc->rtclr = (uint32_t)seconds;
137+
return true;
138+
}
139+
140+
bool rtc_pl031_enable_interrupt(struct rtc_pl031_dev_t* dev)
141+
{
142+
struct rtc_pl031_dev_reg_map_t* p_rtc;
143+
144+
if (dev == NULL) {
145+
return false;
146+
}
147+
148+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
149+
p_rtc->rtcimsc = 0U;
150+
return true;
151+
}
152+
153+
bool rtc_pl031_disable_interrupt(struct rtc_pl031_dev_t* dev)
154+
{
155+
struct rtc_pl031_dev_reg_map_t* p_rtc;
156+
157+
if (dev == NULL) {
158+
return false;
159+
}
160+
161+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
162+
p_rtc->rtcimsc = RTC_PL031_RTCIMSC_SET_CLEAR_MSK;
163+
return true;
164+
}
165+
166+
bool rtc_pl031_is_interrupt_masked(struct rtc_pl031_dev_t* dev)
167+
{
168+
struct rtc_pl031_dev_reg_map_t* p_rtc =
169+
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
170+
171+
if (p_rtc->rtcimsc & RTC_PL031_RTCIMSC_SET_CLEAR_MSK){
172+
return true;
173+
} else {
174+
return false;
175+
}
176+
}
177+
178+
bool rtc_pl031_is_raw_interrupt_pending(struct rtc_pl031_dev_t* dev)
179+
{
180+
struct rtc_pl031_dev_reg_map_t* p_rtc =
181+
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
182+
183+
if (p_rtc->rtcris & RTC_PL031_RTCRIS_STATUS_MSK) {
184+
return true;
185+
} else {
186+
return false;
187+
}
188+
}
189+
190+
bool rtc_pl031_is_masked_interrupt_pending(struct rtc_pl031_dev_t* dev)
191+
{
192+
struct rtc_pl031_dev_reg_map_t* p_rtc =
193+
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
194+
195+
if (p_rtc->rtcmis & RTC_PL031_RTCMIS_STATUS_MSK) {
196+
return true;
197+
} else {
198+
return false;
199+
}
200+
}
201+
202+
bool rtc_pl031_write_match_value(struct rtc_pl031_dev_t* dev, uint32_t seconds)
203+
{
204+
struct rtc_pl031_dev_reg_map_t* p_rtc;
205+
206+
if (dev == NULL) {
207+
return false;
208+
}
209+
210+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
211+
p_rtc->rtcmr = (uint32_t)seconds;
212+
return true;
213+
}
214+
215+
bool rtc_pl031_clear_interrupt(struct rtc_pl031_dev_t* dev)
216+
{
217+
struct rtc_pl031_dev_reg_map_t* p_rtc;
218+
219+
if (dev == NULL) {
220+
return false;
221+
}
222+
223+
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
224+
p_rtc->rtcicr = RTC_PL031_RTCICR_CLEAR_MSK;
225+
return true;
226+
}

0 commit comments

Comments
 (0)