diff --git a/epicardium/api/dispatcher.c b/epicardium/api/dispatcher.c index 20d873f2c2f6458f79991660594d9eae8001e461..c7a01d9f1adbfe39a36817a6b82c07d3855a64ac 100644 --- a/epicardium/api/dispatcher.c +++ b/epicardium/api/dispatcher.c @@ -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 */ diff --git a/epicardium/api/dispatcher.h b/epicardium/api/dispatcher.h index 727fe5acd339e1ce2e882b6bf4a73b433daf09c3..9ec0f0484d5f490bccf05299b296b91b5c4c61f1 100644 --- a/epicardium/api/dispatcher.h +++ b/epicardium/api/dispatcher.h @@ -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 diff --git a/epicardium/support.c b/epicardium/support.c index cbb90f8ba16f342237a36434067246e191fbcbdb..238a59ed40b7bb4c57facbad27705c22e24cab68 100644 --- a/epicardium/support.c +++ b/epicardium/support.c @@ -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");