Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
181fe501
Commit
181fe501
authored
Mar 17, 2015
by
danicampora
Browse files
cc3200: Add RTC callback with wake-up from sleep capability.
parent
6de1b393
Changes
3
Hide whitespace changes
Inline
Side-by-side
cc3200/mods/pybrtc.c
View file @
181fe501
...
...
@@ -54,12 +54,16 @@
/// print(rtc.datetime())
/******************************************************************************
DECLARE TYPES
DECLARE CONSTANTS
******************************************************************************/
#define PYBRTC_CLOCK_FREQUENCY_HZ 32768
#define PYBRTC_MIN_INTERVAL_VALUE 25
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef
struct
{
uint32_t
alarm_sec
;
uint16_t
alarm_msec
;
uint8_t
pwrmode
;
byte
prwmode
;
}
pybrtc_data_t
;
/******************************************************************************
...
...
@@ -92,11 +96,26 @@ void pybrtc_init(void) {
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC
void
pyb_rtc_callback_enable
(
mp_obj_t
self_in
)
{
// check the wake from param
if
(
pybrtc_data
.
prwmode
&
PYB_PWR_MODE_ACTIVE
)
{
// enable the slow clock interrupt
MAP_PRCMIntEnable
(
PRCM_INT_SLOW_CLK_CTR
);
}
else
{
// just in case it was already enabled before
MAP_PRCMIntDisable
(
PRCM_INT_SLOW_CLK_CTR
);
}
pybsleep_configure_timer_wakeup
(
pybrtc_data
.
prwmode
);
}
STATIC
void
pyb_rtc_callback_disable
(
mp_obj_t
self_in
)
{
// check the wake from param
if
(
pybrtc_data
.
prwmode
&
PYB_PWR_MODE_ACTIVE
)
{
// enable the slow clock interrupt
MAP_PRCMIntDisable
(
PRCM_INT_SLOW_CLK_CTR
);
}
// disable wake from ldps and hibernate
pybsleep_configure_timer_wakeup
(
PYB_PWR_MODE_ACTIVE
);
}
/******************************************************************************/
...
...
@@ -171,6 +190,7 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp
// check if any parameters were passed
mp_obj_t
_callback
=
mpcallback_find
((
mp_obj_t
)
&
pyb_rtc_obj
);
if
(
kw_args
->
used
>
0
||
_callback
==
mp_const_none
)
{
uint32_t
f_mseconds
=
args
[
3
].
u_int
;
uint32_t
seconds
;
uint16_t
mseconds
;
// get the seconds and the milliseconds from the RTC
...
...
@@ -178,25 +198,26 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp
mseconds
=
RTC_CYCLES_U16MS
(
mseconds
);
// configure the rtc alarm accordingly
seconds
+=
args
[
3
].
u_int
/
1000
;
mseconds
+=
args
[
3
].
u_int
-
((
args
[
3
].
u_int
/
1000
)
*
1000
);
if
(
mseconds
>
1000
)
{
seconds
++
;
mseconds
-=
1000
;
}
// check the wake from param
if
(
args
[
4
].
u_int
&
PYB_PWR_MODE_ACTIVE
)
{
MAP_PRCMRTCMatchSet
(
seconds
,
mseconds
);
}
// save the alarm config for later
pybrtc_data
.
alarm_sec
=
seconds
;
pybrtc_data
.
alarm_msec
=
mseconds
;
pybrtc_data
.
pwrmode
=
args
[
4
].
u_int
;
// create the new callback
seconds
+=
f_mseconds
/
1000
;
mseconds
+=
f_mseconds
-
((
f_mseconds
/
1000
)
*
1000
);
// set the match value
MAP_PRCMRTCMatchSet
(
seconds
,
mseconds
);
// save the match data for later
pybrtc_data
.
prwmode
=
args
[
4
].
u_int
;
// create the callback
_callback
=
mpcallback_new
((
mp_obj_t
)
&
pyb_rtc_obj
,
args
[
1
].
u_obj
,
&
pybrtc_cb_methods
);
// set the lpds callback
pybsleep_set_timer_lpds_callback
(
_callback
);
// the interrupt priority is ignored since is already set to to highest level by the sleep module
// to make sure that the wakeup callbacks are always called first when resuming from sleep
// enable the interrupt (the object is not relevant here, the function already knows it)
pyb_rtc_callback_enable
(
NULL
);
}
return
_callback
;
}
...
...
cc3200/mods/pybsleep.c
View file @
181fe501
...
...
@@ -67,6 +67,9 @@
#define WAKEUP_TIME_LPDS (LPDS_UP_TIME + LPDS_DOWN_TIME + USER_OFFSET) // 20 msec
#define WAKEUP_TIME_HIB (32768) // 1 s
#define FORCED_TIMER_INTERRUPT_MS (1)
#define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 3)
/******************************************************************************
DECLARE PRIVATE TYPES
******************************************************************************/
...
...
@@ -110,6 +113,7 @@ typedef struct {
mp_obj_t
wlan_lpds_wake_cb
;
mp_obj_t
timer_lpds_wake_cb
;
mp_obj_t
gpio_lpds_wake_cb
;
uint
timer_wake_pwrmode
;
}
pybsleep_wake_cb_t
;
/******************************************************************************
...
...
@@ -131,6 +135,8 @@ void pybsleep_suspend_exit (void);
STATIC
void
pybsleep_obj_wakeup
(
void
);
STATIC
void
PRCMInterruptHandler
(
void
);
STATIC
void
pybsleep_iopark
(
void
);
STATIC
bool
setup_timer_lpds_wake
(
void
);
STATIC
bool
setup_timer_hibernate_wake
(
void
);
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
...
...
@@ -151,8 +157,8 @@ void pybsleep_init0 (void) {
// disable all LPDS and hibernate wake up sources (WLAN is disabed/enabled before entering LDPS mode)
MAP_PRCMLPDSWakeupSourceDisable
(
PRCM_LPDS_GPIO
);
MAP_PRCMLPDSWakeupSourceDisable
(
PRCM_LPDS_TIMER
);
MAP_PRCMHibernateWakeupSourceDisable
(
PRCM_HIB_SLOW_CLK_CTR
|
PRCM_HIB_GPIO2
|
PRCM_HIB_GPIO4
|
PRCM_HIB_GPIO13
|
PRCM_HIB_GPIO17
|
PRCM_HIB_GPIO11
|
PRCM_HIB_GPIO24
|
PRCM_HIB_GPIO26
);
MAP_PRCMHibernateWakeupSourceDisable
(
PRCM_HIB_SLOW_CLK_CTR
|
PRCM_HIB_GPIO2
|
PRCM_HIB_GPIO4
|
PRCM_HIB_GPIO13
|
PRCM_HIB_GPIO17
|
PRCM_HIB_GPIO11
|
PRCM_HIB_GPIO24
|
PRCM_HIB_GPIO26
);
// store the reset casue (if it's soft reset, leave it as it is)
if
(
pybsleep_reset_cause
!=
PYB_SLP_SOFT_RESET
)
{
...
...
@@ -216,6 +222,10 @@ void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj) {
pybsleep_wake_cb
.
timer_lpds_wake_cb
=
cb_obj
;
}
void
pybsleep_configure_timer_wakeup
(
uint
pwrmode
)
{
pybsleep_wake_cb
.
timer_wake_pwrmode
=
pwrmode
;
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
...
...
@@ -405,6 +415,9 @@ STATIC void PRCMInterruptHandler (void) {
}
break
;
case
PRCM_LPDS_TIMER
:
// disable timer was wake-up source
pybsleep_wake_cb
.
timer_wake_pwrmode
&=
~
PYB_PWR_MODE_LPDS
;
MAP_PRCMLPDSWakeupSourceDisable
(
PRCM_LPDS_TIMER
);
if
(
pybsleep_wake_cb
.
timer_lpds_wake_cb
)
{
mpcallback_handler
(
pybsleep_wake_cb
.
timer_lpds_wake_cb
);
}
...
...
@@ -466,6 +479,77 @@ STATIC void pybsleep_iopark (void) {
HWREG
(
0x4402E10C
)
=
0x00000E61
;
}
STATIC
bool
setup_timer_lpds_wake
(
void
)
{
uint64_t
t_match
,
t_curr
,
t_remaining
;
// get the time remaining for the RTC timer to expire
t_match
=
MAP_PRCMSlowClkCtrMatchGet
();
t_curr
=
MAP_PRCMSlowClkCtrGet
();
if
(
t_match
>
t_curr
)
{
// get the time remaining in terms of slow clocks
t_remaining
=
(
t_match
-
t_curr
);
if
(
t_remaining
>
WAKEUP_TIME_LPDS
)
{
// subtract the time it takes for wakeup from lpds
t_remaining
-=
WAKEUP_TIME_LPDS
;
t_remaining
=
(
t_remaining
>
0xFFFFFFFF
)
?
0xFFFFFFFF
:
t_remaining
;
// setup the LPDS wake time
MAP_PRCMLPDSIntervalSet
((
uint32_t
)
t_remaining
);
// enable the wake source
MAP_PRCMLPDSWakeupSourceEnable
(
PRCM_LPDS_TIMER
);
return
true
;
}
}
else
{
// setup a timer interrupt immediately
MAP_PRCMRTCMatchSet
(
0
,
FORCED_TIMER_INTERRUPT_MS
);
}
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable
(
PRCM_LPDS_TIMER
);
// LPDS wake by timer was not possible, force
// an interrupt in active mode instead
MAP_PRCMIntEnable
(
PRCM_INT_SLOW_CLK_CTR
);
return
false
;
}
STATIC
bool
setup_timer_hibernate_wake
(
void
)
{
uint64_t
t_match
,
t_curr
,
t_remaining
;
// get the time remaining for the RTC timer to expire
t_match
=
MAP_PRCMSlowClkCtrMatchGet
();
t_curr
=
MAP_PRCMSlowClkCtrGet
();
if
(
t_match
>
t_curr
)
{
// get the time remaining in terms of slow clocks
t_remaining
=
(
t_match
-
t_curr
);
if
(
t_remaining
>
WAKEUP_TIME_HIB
)
{
// subtract the time it takes for wakeup from hibernate
t_remaining
-=
WAKEUP_TIME_HIB
;
// setup the LPDS wake time
MAP_PRCMHibernateIntervalSet
((
uint32_t
)
t_remaining
);
// enable the wake source
MAP_PRCMHibernateWakeupSourceEnable
(
PRCM_HIB_SLOW_CLK_CTR
);
return
true
;
}
}
else
{
// setup a timer interrupt immediately
MAP_PRCMRTCMatchSet
(
0
,
FORCED_TIMER_INTERRUPT_MS
);
}
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable
(
PRCM_HIB_SLOW_CLK_CTR
);
// hibernate wake by timer was not possible, force
// an interrupt in active mode instead
MAP_PRCMIntEnable
(
PRCM_INT_SLOW_CLK_CTR
);
return
false
;
}
/******************************************************************************/
// Micro Python bindings; Sleep class
...
...
@@ -483,6 +567,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_idle_obj, pyb_sleep_idle);
STATIC
mp_obj_t
pyb_sleep_suspend
(
mp_obj_t
self_in
)
{
nlr_buf_t
nlr
;
// check if we should enable timer wake-up
if
(
pybsleep_wake_cb
.
timer_wake_pwrmode
&
PYB_PWR_MODE_LPDS
)
{
if
(
!
setup_timer_lpds_wake
())
{
// lpds entering is not possible, wait for the forced interrupt and return
pybsleep_wake_cb
.
timer_wake_pwrmode
&=
~
PYB_PWR_MODE_LPDS
;
HAL_Delay
(
FAILED_SLEEP_DELAY_MS
);
return
mp_const_none
;
}
}
// check if we need to enable network wake-up
if
(
pybsleep_wake_cb
.
wlan_lpds_wake_cb
)
{
MAP_PRCMLPDSWakeupSourceEnable
(
PRCM_LPDS_HOST_IRQ
);
...
...
@@ -498,6 +592,7 @@ STATIC mp_obj_t pyb_sleep_suspend (mp_obj_t self_in) {
pybsleep_suspend_enter
();
nlr_pop
();
}
// an exception is always raised when exiting suspend mode
enable_irq
(
primsk
);
...
...
@@ -509,6 +604,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_suspend_obj, pyb_sleep_suspend);
/// Enters hibernate mode. Wake up sources should have been enable prior to
/// calling this method.
STATIC
mp_obj_t
pyb_sleep_hibernate
(
mp_obj_t
self_in
)
{
// check if we should enable timer wake-up
if
(
pybsleep_wake_cb
.
timer_wake_pwrmode
&
PYB_PWR_MODE_HIBERNATE
)
{
if
(
!
setup_timer_hibernate_wake
())
{
// hibernating is not possible, wait for the forced interrupt and return
pybsleep_wake_cb
.
timer_wake_pwrmode
&=
~
PYB_PWR_MODE_HIBERNATE
;
HAL_Delay
(
FAILED_SLEEP_DELAY_MS
);
return
mp_const_none
;
}
}
wlan_stop
();
pybsleep_flash_powerdown
();
MAP_PRCMHibernateEnter
();
...
...
cc3200/mods/pybsleep.h
View file @
181fe501
...
...
@@ -71,5 +71,6 @@ void pybsleep_remove (const mp_obj_t obj);
void
pybsleep_set_wlan_lpds_callback
(
mp_obj_t
cb_obj
);
void
pybsleep_set_gpio_lpds_callback
(
mp_obj_t
cb_obj
);
void
pybsleep_set_timer_lpds_callback
(
mp_obj_t
cb_obj
);
void
pybsleep_configure_timer_wakeup
(
uint
pwrmode
);
#endif
/* PYBSLEEP_H_ */
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment