Skip to content
Snippets Groups Projects
Commit 1695d090 authored by rahix's avatar rahix
Browse files

Merge 'Dynamically scale system clock based on load'

See merge request !481
parents 0e0efade 365d2475
No related branches found
No related tags found
1 merge request!481Dynamically scale system clock based on load
Pipeline #5273 passed
...@@ -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");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment