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
Pipeline #5273 passed with stages
in 45 seconds
......@@ -9,7 +9,7 @@
/* This function is defined by the generated dispatcher code */
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()
{
......@@ -34,7 +34,7 @@ int api_dispatcher_init()
bool api_dispatcher_poll_once()
{
if (event_ready) {
if (call_pending) {
return false;
}
......@@ -46,22 +46,27 @@ bool api_dispatcher_poll_once()
return false;
}
event_ready = true;
call_pending = true;
return true;
}
bool api_dispatcher_poll()
{
if (event_ready) {
if (call_pending) {
return true;
}
return api_dispatcher_poll_once();
}
bool api_dispatcher_call_pending()
{
return call_pending;
}
api_id_t api_dispatcher_exec()
{
if (!event_ready) {
if (!call_pending) {
return 0;
}
......@@ -69,7 +74,7 @@ api_id_t api_dispatcher_exec()
__api_dispatch_call(id, API_CALL_MEM->buffer);
API_CALL_MEM->call_flag = _API_FLAG_RETURNED;
event_ready = false;
call_pending = false;
SEMA_FreeSema(_API_SEMAPHORE);
/* Notify the caller that we returned */
......
......@@ -15,6 +15,12 @@ int api_dispatcher_init();
bool api_dispatcher_poll_once();
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
* api_dispatcher_poll(). Will return 0 if no call was dispatched or the ID of
......
......@@ -8,6 +8,11 @@
#include "api/dispatcher.h"
#include "user_core/user_core.h"
#include "os/core.h"
#include "drivers/drivers.h"
#include "usb.h"
#include "mxc_sys.h"
#include "wut.h"
#include "card10.h"
......@@ -16,7 +21,8 @@
*/
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
* epicardium if it wants to issue an API call.
......@@ -26,7 +32,57 @@ void pre_idle_sleep(TickType_t xExpectedIdleTime)
* TODO: Ensure this is actually correct and does not have any
* 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("wfe");
__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