You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2017/11/20 20:00:28 UTC
[GitHub] ccollins476ad commented on a change in pull request #667: Apollo2 - Tickless idle and HAL timer implementation
ccollins476ad commented on a change in pull request #667: Apollo2 - Tickless idle and HAL timer implementation
URL: https://github.com/apache/mynewt-core/pull/667#discussion_r152096024
##########
File path: hw/mcu/ambiq/apollo2/src/hal_os_tick.c
##########
@@ -17,31 +17,118 @@
* under the License.
*/
+/**
+ * NOTE: Unlike other MCUs, this one does not use SysTick to implement the
+ * tickless idle state. The SysTick timer uses HCLK as its source, and HCLK is
+ * gated while this MCU is in deep sleep (e.g., during a `wfi` instruction).
+ *
+ * To enable a wake up from deep sleep, the idle state is instead implemented
+ * using this MCU's system timer (STIMER) with LFRC as the source.
+ */
+
#include <assert.h>
#include <os/os.h>
-#include <mcu/system_apollo2.h>
-#include <hal/hal_os_tick.h>
+#include "mcu/system_apollo2.h"
+#include "hal/hal_os_tick.h"
+#include "bsp/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+#define APOLLO2_OS_TICK_FREQ 1024 /* Hz */
+#define APOLLO2_OS_TICK_IRQ STIMER_CMPR0_IRQn
+
+/*** Value of timer when the ISR last executed. */
+static uint32_t apollo2_os_tick_prev;
+
+/*** Number of system ticks per single OS tick. */
+static uint32_t apollo2_os_tick_dur;
+
+static void
+apollo2_os_tick_set_timer(int os_ticks)
+{
+ uint32_t sys_ticks;
+ uint32_t cfg;
+
+ OS_ASSERT_CRITICAL();
+
+ sys_ticks = os_ticks * apollo2_os_tick_dur;
+
+ /* Freeze time, set timer expiry, then unfreeze time. */
+ cfg = am_hal_stimer_config(AM_HAL_STIMER_CFG_FREEZE);
+ am_hal_stimer_compare_delta_set(0, sys_ticks);
+ am_hal_stimer_config(cfg);
+}
+
+static void
+apollo2_os_tick_handler(void)
+{
+ uint32_t cur;
+ int os_ticks;
+ int delta;
+ os_sr_t sr;
+
+ OS_ENTER_CRITICAL(sr);
+
+ /* Calculate elapsed ticks and advance OS time. */
+ cur = am_hal_stimer_counter_get();
+ delta = cur - apollo2_os_tick_prev;
+ os_ticks = delta / apollo2_os_tick_dur;
+ os_time_advance(os_ticks);
+
+ /* Clear timer interrupt. */
+ am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREA);
+
+ /* Update the time associated with the most recent tick. */
+ apollo2_os_tick_prev += os_ticks * apollo2_os_tick_dur;
+
+ /* Schedule timer to interrupt at the next tick. */
+ apollo2_os_tick_set_timer(apollo2_os_tick_dur);
+
+ OS_EXIT_CRITICAL(sr);
+}
-/*
- * XXX implement tickless mode.
- */
void
os_tick_idle(os_time_t ticks)
{
OS_ASSERT_CRITICAL();
+
+ /* Since the STIMER only uses relative scheduling, all ticks values are
+ * valid. There is no need to check for wrap around.
+ */
+
+ /* Only set the timer for nonzero tick values. For values of 0, just let
+ * the timer expire on the next tick, as scheduled earlier.
+ */
+ if (ticks > 0) {
+ apollo2_os_tick_set_timer(ticks);
Review comment:
I could be wrong, but I don't think so. `apollo2_os_tick_set_timer()` multiplies its parameter by `apollo2_os_tick_dur` before setting the output compare.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
With regards,
Apache Git Services