Skip to content

Commit a68a19e

Browse files
bors[bot]refugeesusalevy
committed
Merge tock#1119
1119: Adds RTC, AON, PRCM driver to CC26x2 r=alevy a=refugeesus ### Pull Request Overview Add support for RTC, power domain and clock control to the cc26x2 chip. ### Testing Strategy This PR was tested by initializing dependent peripherals (RFCore from a separate PR) and passing is_enabled() checks. Panic on fail. ### TODO or Help Wanted n/a ### Documentation Updated - [ ] ~~Updated the relevant files in `/docs`, or no updates are required.~~ ### Formatting - [x] Ran `make formatall`. Co-authored-by: Robert Keith <robertfkeith@me.com> Co-authored-by: Amit Aryeh Levy <amit@amitlevy.com>
2 parents d291f76 + c91b27a commit a68a19e

File tree

5 files changed

+766
-7
lines changed

5 files changed

+766
-7
lines changed

chips/cc26x2/src/aon.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//! Always On Module (AON) management
2+
//!
3+
//! AON is a set of peripherals which is _always on_ (eg. the RTC, MCU, etc).
4+
//!
5+
//! The current configuration disables all wake-up selectors, since the
6+
//! MCU never go to sleep and is always active.
7+
use kernel::common::registers::{ReadOnly, ReadWrite};
8+
use kernel::common::StaticRef;
9+
use rtc;
10+
11+
#[repr(C)]
12+
pub struct AonIocRegisters {
13+
_reserved0: [u32; 3],
14+
ioc_clk32k_ctl: ReadWrite<u32, IocClk::Register>,
15+
}
16+
17+
#[repr(C)]
18+
pub struct AonEventRegisters {
19+
mcu_wu_sel: ReadWrite<u32>, // MCU Wake-up selector
20+
aux_wu_sel: ReadWrite<u32>, // AUX Wake-up selector
21+
event_to_mcu_sel: ReadWrite<u32>, // Event selector for MCU Events
22+
rtc_sel: ReadWrite<u32>, // RTC Capture event selector for AON_RTC
23+
}
24+
25+
#[repr(C)]
26+
struct AonPmCtlRegisters {
27+
aux_clk: ReadWrite<u32, AuxClk::Register>,
28+
ram_cfg: ReadWrite<u32, RamCfg::Register>,
29+
pwr_ctl: ReadWrite<u32, PwrCtl::Register>,
30+
pwr_stat: ReadOnly<u32, PwrStat::Register>,
31+
shutdown: ReadWrite<u32, Shutdown::Register>,
32+
_recharge: [u32; 4],
33+
}
34+
35+
register_bitfields![
36+
u32,
37+
AuxClk [
38+
SRC OFFSET(0) NUMBITS(1) [
39+
SCLK_HFDIV2 = 0x00,
40+
SCLK_MF = 0x01
41+
],
42+
PWR_DWN_SRC OFFSET(8) NUMBITS(1) [
43+
NO_CLOCK = 0b0,
44+
SCLK_LF = 0b1
45+
]
46+
],
47+
RamCfg [
48+
AUX_SRAM_PWR_OFF_OFF OFFSET(17) NUMBITS(1) [],
49+
AUX_SRAM_RET_EN OFFSET(16) NUMBITS(1) [],
50+
51+
// SRAM Retention enabled
52+
// 0x00 - Retention disabled
53+
// 0x01 - Retention enabled for BANK0
54+
// 0x03 - Retention enabled for BANK0, BANK1
55+
// 0x07 - Retention enabled for BANK0, BANK1, BANK2
56+
// 0x0F - Retention enabled for BANK0, BANK1, BANK2, BANK3
57+
BUS_SRAM_RET_EN OFFSET(0) NUMBITS(4) [
58+
OFF = 0x00,
59+
ON = 0x0F // Default to enable retention in all banks
60+
]
61+
],
62+
PwrCtl [
63+
// 0 = use GLDO in active mode, 1 = use DCDC in active mode
64+
DCDC_ACTIVE OFFSET(2) NUMBITS(1) [],
65+
// 0 = DCDC/GLDO are used, 1 = DCDC/GLDO are bypassed and using a external regulater
66+
EXT_REG_MODE OFFSET(1) NUMBITS(1) [],
67+
// 0 = use GDLO for recharge, 1 = use DCDC for recharge
68+
DCDC_EN OFFSET(0) NUMBITS(1) []
69+
],
70+
PwrStat [
71+
JTAG_PD_ON OFFSET(2) NUMBITS(1) [],
72+
AUX_BUS_RESET_DONE OFFSET(1) NUMBITS(1) [],
73+
AUX_RESET_DONE OFFSET(0) NUMBITS(1) []
74+
],
75+
Shutdown [
76+
// Controls whether MCU & AUX requesting to be powered off
77+
// will enable a transition to powerdown (0 = Enabled, 1 = Disabled)
78+
PWR_DWN_DIS OFFSET(0) NUMBITS(1) []
79+
],
80+
IocClk [
81+
EN OFFSET(0) NUMBITS(1) []
82+
]
83+
84+
];
85+
86+
const AON_EVENT_BASE: StaticRef<AonEventRegisters> =
87+
unsafe { StaticRef::new(0x4009_3000 as *const AonEventRegisters) };
88+
const AON_PMCTL_BASE: StaticRef<AonPmCtlRegisters> =
89+
unsafe { StaticRef::new(0x4009_0000 as *const AonPmCtlRegisters) };
90+
const AON_IOC_BASE: StaticRef<AonIocRegisters> =
91+
unsafe { StaticRef::new(0x4009_4000 as *const AonIocRegisters) };
92+
93+
pub struct Aon {
94+
event_regs: StaticRef<AonEventRegisters>,
95+
}
96+
97+
pub const AON: Aon = Aon::new();
98+
99+
impl Aon {
100+
const fn new() -> Aon {
101+
Aon {
102+
event_regs: AON_EVENT_BASE,
103+
}
104+
}
105+
106+
pub fn setup(&self) {
107+
let regs = &*self.event_regs;
108+
109+
// Default to no events at all
110+
regs.aux_wu_sel.set(0x3F3F3F3F);
111+
112+
// Set RTC CH1 as a wakeup source by default
113+
regs.mcu_wu_sel.set(0x3F3F3F24);
114+
115+
// Disable RTC combined event
116+
regs.rtc_sel.set(0x0000003F);
117+
118+
// The default reset value is 0x002B2B2B. However, 0x2b for each
119+
// programmable event corresponds to a JTAG event; which is fired
120+
// *all* the time during debugging through JTAG. It is better to
121+
// ignore it in this case.
122+
// NOTE: the aon programmable interrupt will still be fired
123+
// once a debugger is attached through JTAG.
124+
regs.event_to_mcu_sel.set(0x003F3F3F);
125+
}
126+
127+
pub fn set_dcdc_enabled(&self, enabled: bool) {
128+
let regs = AON_PMCTL_BASE;
129+
if enabled {
130+
regs.pwr_ctl
131+
.modify(PwrCtl::DCDC_ACTIVE::SET + PwrCtl::DCDC_EN::SET);
132+
} else {
133+
regs.pwr_ctl
134+
.modify(PwrCtl::DCDC_ACTIVE::CLEAR + PwrCtl::DCDC_EN::CLEAR);
135+
}
136+
}
137+
138+
pub fn lfclk_enable(&self, enable: bool) {
139+
let regs = AON_IOC_BASE;
140+
if enable {
141+
regs.ioc_clk32k_ctl.write(IocClk::EN::SET);
142+
} else {
143+
regs.ioc_clk32k_ctl.write(IocClk::EN::CLEAR);
144+
}
145+
}
146+
147+
pub fn aux_set_ram_retention(&self, enabled: bool) {
148+
let regs = AON_PMCTL_BASE;
149+
regs.ram_cfg.modify({
150+
if enabled {
151+
RamCfg::AUX_SRAM_RET_EN::SET
152+
} else {
153+
RamCfg::AUX_SRAM_RET_EN::CLEAR
154+
}
155+
});
156+
}
157+
158+
pub fn mcu_set_ram_retention(&self, on: bool) {
159+
let regs = AON_PMCTL_BASE;
160+
regs.ram_cfg.modify({
161+
if on {
162+
RamCfg::BUS_SRAM_RET_EN::ON
163+
} else {
164+
RamCfg::BUS_SRAM_RET_EN::OFF
165+
}
166+
});
167+
}
168+
169+
pub fn shutdown(&self) {
170+
let regs = AON_PMCTL_BASE;
171+
regs.shutdown.modify(Shutdown::PWR_DWN_DIS::SET);
172+
}
173+
/// Await a cycle of the AON domain in order
174+
/// to sync with it.
175+
pub fn sync(&self) {
176+
unsafe { rtc::RTC.sync() };
177+
}
178+
}

chips/cc26x2/src/chip.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
//! Configuration and interrupt handling.
2-
31
use cc26xx::gpio;
42
use cc26xx::peripheral_interrupts;
5-
use cc26xx::rtc;
63
use cc26xx::uart;
74
use cortexm4::{self, nvic};
85
use kernel;
6+
use rtc;
97

108
pub struct Cc26X2 {
119
mpu: cortexm4::mpu::MPU,
@@ -33,7 +31,6 @@ impl kernel::Chip for Cc26X2 {
3331
fn systick(&self) -> &Self::SysTick {
3432
&self.systick
3533
}
36-
3734
fn service_pending_interrupts(&mut self) {
3835
unsafe {
3936
while let Some(interrupt) = nvic::next_pending() {
@@ -44,7 +41,7 @@ impl kernel::Chip for Cc26X2 {
4441
// AON Programmable interrupt
4542
// We need to ignore JTAG events since some debuggers emit these
4643
peripheral_interrupts::AON_PROG => (),
47-
_ => panic!("unhandled interrupt {:?}", interrupt),
44+
_ => panic!("unhandled interrupt {}", interrupt),
4845
}
4946
let n = nvic::Nvic::new(interrupt);
5047
n.clear_pending();

chips/cc26x2/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
#![feature(used)]
1+
#![feature(const_fn, used)]
22
#![no_std]
33
#![crate_name = "cc26x2"]
44
#![crate_type = "rlib"]
55
extern crate cc26xx;
66
extern crate cortexm4;
77
#[allow(unused_imports)]
8-
#[macro_use(debug)]
8+
#[macro_use]
99
extern crate kernel;
1010

11+
pub mod aon;
1112
pub mod chip;
1213
pub mod crt1;
14+
pub mod prcm;
15+
pub mod rtc;
1316

1417
pub use crt1::init;

0 commit comments

Comments
 (0)