Commit 365d2475 authored by schneider's avatar schneider
Browse files

feat(epicardium): Lower clock speed when idle

parent 0e0efade
Pipeline #5272 passed with stages
in 32 seconds
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
/* This function is defined by the generated dispatcher code */ /* This function is defined by the generated dispatcher code */
void __api_dispatch_call(api_id_t id, void *buffer); void __api_dispatch_call(api_id_t id, void *buffer);
static volatile bool event_ready = false; static volatile bool call_pending = false;
int api_dispatcher_init() int api_dispatcher_init()
{ {
...@@ -34,7 +34,7 @@ int api_dispatcher_init() ...@@ -34,7 +34,7 @@ int api_dispatcher_init()
bool api_dispatcher_poll_once() bool api_dispatcher_poll_once()
{ {
if (event_ready) { if (call_pending) {
return false; return false;
} }
...@@ -46,22 +46,27 @@ bool api_dispatcher_poll_once() ...@@ -46,22 +46,27 @@ bool api_dispatcher_poll_once()
return false; return false;
} }
event_ready = true; call_pending = true;
return true; return true;
} }
bool api_dispatcher_poll() bool api_dispatcher_poll()
{ {
if (event_ready) { if (call_pending) {
return true; return true;
} }
return api_dispatcher_poll_once(); return api_dispatcher_poll_once();
} }
bool api_dispatcher_call_pending()
{
return call_pending;
}
api_id_t api_dispatcher_exec() api_id_t api_dispatcher_exec()
{ {
if (!event_ready) { if (!call_pending) {
return 0; return 0;
} }
...@@ -69,7 +74,7 @@ api_id_t api_dispatcher_exec() ...@@ -69,7 +74,7 @@ api_id_t api_dispatcher_exec()
__api_dispatch_call(id, API_CALL_MEM->buffer); __api_dispatch_call(id, API_CALL_MEM->buffer);
API_CALL_MEM->call_flag = _API_FLAG_RETURNED; API_CALL_MEM->call_flag = _API_FLAG_RETURNED;
event_ready = false; call_pending = false;
SEMA_FreeSema(_API_SEMAPHORE); SEMA_FreeSema(_API_SEMAPHORE);
/* Notify the caller that we returned */ /* Notify the caller that we returned */
......
...@@ -15,6 +15,12 @@ int api_dispatcher_init(); ...@@ -15,6 +15,12 @@ int api_dispatcher_init();
bool api_dispatcher_poll_once(); bool api_dispatcher_poll_once();
bool api_dispatcher_poll(); bool api_dispatcher_poll();
/*
* Check if the other core requested a call or if we are already excuting it.
* Only returns a cached version, without acquiring any locks.
*/
bool api_dispatcher_call_pending();
/* /*
* Attempt to dispatch a call, if one had been polled using * Attempt to dispatch a call, if one had been polled using
* api_dispatcher_poll(). Will return 0 if no call was dispatched or the ID of * api_dispatcher_poll(). Will return 0 if no call was dispatched or the ID of
......
...@@ -8,6 +8,11 @@ ...@@ -8,6 +8,11 @@
#include "api/dispatcher.h" #include "api/dispatcher.h"
#include "user_core/user_core.h" #include "user_core/user_core.h"
#include "os/core.h" #include "os/core.h"
#include "drivers/drivers.h"
#include "usb.h"
#include "mxc_sys.h"
#include "wut.h"
#include "card10.h" #include "card10.h"
...@@ -16,7 +21,8 @@ ...@@ -16,7 +21,8 @@
*/ */
void pre_idle_sleep(TickType_t xExpectedIdleTime) void pre_idle_sleep(TickType_t xExpectedIdleTime)
{ {
if (xExpectedIdleTime > 0) { if (xExpectedIdleTime > 0 &&
(CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0) {
/* /*
* WFE because the other core should be able to notify * WFE because the other core should be able to notify
* epicardium if it wants to issue an API call. * epicardium if it wants to issue an API call.
...@@ -26,7 +32,57 @@ void pre_idle_sleep(TickType_t xExpectedIdleTime) ...@@ -26,7 +32,57 @@ void pre_idle_sleep(TickType_t xExpectedIdleTime)
* TODO: Ensure this is actually correct and does not have any * TODO: Ensure this is actually correct and does not have any
* race conditions. * race conditions.
*/ */
if ((CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0) {
/* If the other core is waiting for a call to return and we are able
* to sleep, reduce the system clock to save energy. */
if (xExpectedIdleTime >= pdMS_TO_TICKS(10) &&
api_dispatcher_call_pending()) {
uint32_t ms = xExpectedIdleTime - 1;
/* Initialize Wakeup timer */
WUT_Init(WUT_PRES_1);
wut_cfg_t wut_cfg;
wut_cfg.mode = WUT_MODE_COMPARE;
wut_cfg.cmp_cnt = 0xFFFFFFFF;
WUT_Config(&wut_cfg);
WUT_Enable();
/* Enable WUT as a wakup source */
NVIC_EnableIRQ(WUT_IRQn);
uint32_t targetTick;
targetTick = WUT_GetCount();
targetTick += ((uint64_t)(ms)*SYS_WUT_GetFreq() / 1000);
WUT_SetCompare(targetTick);
/* Stop SysTick */
uint32_t val = SysTick->VAL;
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
if (usb_get_status() & MAXUSB_STATUS_VBUS_ON) {
SYS_Clock_Select(SYS_CLOCK_HIRC, NULL);
} else {
MXC_GCR->clkcn |= MXC_S_GCR_CLKCN_PSC_DIV4;
SYS_Clock_Select(SYS_CLOCK_HIRC, NULL);
SYS_ClockSourceDisable(SYS_CLOCK_HIRC96);
}
disp_update_backlight_clock();
__asm volatile("dsb" ::: "memory");
__asm volatile("wfe");
__asm volatile("isb");
MXC_GCR->clkcn &= ~(MXC_S_GCR_CLKCN_PSC_DIV4);
SYS_Clock_Select(SYS_CLOCK_HIRC96, NULL);
disp_update_backlight_clock();
SYS_ClockSourceDisable(SYS_CLOCK_HIRC);
SysTick->LOAD = val;
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
ms = (WUT_GetCount() * 1000) / SYS_WUT_GetFreq();
for (uint32_t t = 0; t < ms; t++) {
xTaskIncrementTick();
}
} else {
__asm volatile("dsb" ::: "memory"); __asm volatile("dsb" ::: "memory");
__asm volatile("wfe"); __asm volatile("wfe");
__asm volatile("isb"); __asm volatile("isb");
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment