antmerlino commented on a change in pull request #3488:
URL: https://github.com/apache/incubator-nuttx/pull/3488#discussion_r835778986



##########
File path: arch/arm/src/stm32h7/stm32_tickless.c
##########
@@ -0,0 +1,1057 @@
+/****************************************************************************
+ * arch/arm/src/stm32h7/stm32_tickless.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Tickless OS Support.
+ *
+ * When CONFIG_SCHED_TICKLESS is enabled, all support for timer interrupts
+ * is suppressed and the platform specific code is expected to provide the
+ * following custom functions.
+ *
+ *   void up_timer_initialize(void): Initializes the timer facilities.
+ *     Called early in the initialization sequence (by up_initialize()).
+ *   int up_timer_gettime(FAR struct timespec *ts):  Returns the current
+ *     time from the platform specific time source.
+ *   int up_timer_cancel(void):  Cancels the interval timer.
+ *   int up_timer_start(FAR const struct timespec *ts): Start (or re-starts)
+ *     the interval timer.
+ *
+ * The RTOS will provide the following interfaces for use by the platform-
+ * specific interval timer implementation:
+ *
+ *   void nxsched_timer_expiration(void):  Called by the platform-specific
+ *     logic when the interval timer expires.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * STM32 Timer Usage
+ *
+ * This implementation uses one timer:  A free running timer to provide
+ * the current time and a capture/compare channel for timed-events.
+ *
+ * BASIC timers that are found on some STM32 chips (timers 6 and 7) are
+ * incompatible with this implementation because they don't have capture/
+ * compare channels.  There are two interrupts generated from our timer,
+ * the overflow interrupt which drives the timing handler and the capture/
+ * compare interrupt which drives the interval handler.  There are some low
+ * level timer control functions implemented here because the API of
+ * stm32_tim.c does not provide adequate control over capture/compare
+ * interrupts.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/timers/arch_timer.h>
+#include <debug.h>
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+
+#include "stm32_tim.h"
+#include "stm32_dbgmcu.h"
+
+#include "systick.h"
+
+#ifdef CONFIG_SCHED_TICKLESS
+
+/* Only TIM2 and TIM5 timers may be 32-bits in width */
+
+#undef HAVE_32BIT_TICKLESS
+
+#if (CONFIG_STM32H7_TICKLESS_TIMER == 2) || \
+    (CONFIG_STM32H7_TICKLESS_TIMER == 5)
+ #define HAVE_32BIT_TICKLESS 1
+#endif
+
+#if (CONFIG_STM32H7_TICKLESS_TIMER == 6) || \
+    (CONFIG_STM32H7_TICKLESS_TIMER == 7)
+# error Basic timers not supported by the tickless driver
+#endif
+
+#if CONFIG_STM32H7_TICKLESS_CHANNEL == 1
+#define DIER_CAPT_IE          GTIM_DIER_CC1IE
+#elif CONFIG_STM32H7_TICKLESS_CHANNEL == 2
+#define DIER_CAPT_IE          GTIM_DIER_CC2IE
+#elif CONFIG_STM32H7_TICKLESS_CHANNEL == 3
+#define DIER_CAPT_IE          GTIM_DIER_CC3IE
+#elif CONFIG_STM32H7_TICKLESS_CHANNEL == 4
+#define DIER_CAPT_IE          GTIM_DIER_CC4IE
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32_tickless_s
+{
+  uint8_t timer;                   /* The timer/counter in use */
+  uint8_t channel;                 /* The timer channel to use for intervals */
+  FAR struct stm32_tim_dev_s *tch; /* Handle returned by stm32_tim_init() */
+  uint32_t frequency;
+  uint32_t overflow;               /* Timer counter overflow */
+  volatile bool pending;           /* True: pending task */
+  uint32_t period;                 /* Interval period */
+  uint32_t base;
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
+  uint64_t last_alrm;
+#endif
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct stm32_tickless_s g_tickless;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_getreg16
+ *
+ * Description:
+ *   Get a 16-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline uint16_t stm32_getreg16(uint8_t offset)
+{
+  return getreg16(g_tickless.base + offset);
+}
+
+/****************************************************************************
+ * Name: stm32_putreg16
+ *
+ * Description:
+ *   Put a 16-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void stm32_putreg16(uint8_t offset, uint16_t value)
+{
+  putreg16(value, g_tickless.base + offset);
+}
+
+/****************************************************************************
+ * Name: stm32_modifyreg16
+ *
+ * Description:
+ *   Modify a 16-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void stm32_modifyreg16(uint8_t offset, uint16_t clearbits,
+                                     uint16_t setbits)
+{
+  modifyreg16(g_tickless.base + offset, clearbits, setbits);
+}
+
+/****************************************************************************
+ * Name: stm32_tickless_enableint
+ ****************************************************************************/
+
+static inline void stm32_tickless_enableint(int channel)
+{
+  stm32_modifyreg16(STM32_BTIM_DIER_OFFSET, 0, 1 << channel);
+}
+
+/****************************************************************************
+ * Name: stm32_tickless_disableint
+ ****************************************************************************/
+
+static inline void stm32_tickless_disableint(int channel)
+{
+  stm32_modifyreg16(STM32_BTIM_DIER_OFFSET, 1 << channel, 0);
+}
+
+/****************************************************************************
+ * Name: stm32_tickless_ackint
+ ****************************************************************************/
+
+static inline void stm32_tickless_ackint(int channel)
+{
+  stm32_putreg16(STM32_BTIM_SR_OFFSET, ~(1 << channel));
+}
+
+/****************************************************************************
+ * Name: stm32_tickless_getint
+ ****************************************************************************/
+
+static inline uint16_t stm32_tickless_getint(void)
+{
+  return stm32_getreg16(STM32_BTIM_SR_OFFSET);
+}
+
+/****************************************************************************
+ * Name: stm32_tickless_setchannel
+ ****************************************************************************/
+
+static int stm32_tickless_setchannel(uint8_t channel)
+{
+  uint16_t ccmr_orig   = 0;
+  uint16_t ccmr_val    = 0;
+  uint16_t ccmr_mask   = 0xff;
+  uint16_t ccer_val    = stm32_getreg16(STM32_GTIM_CCER_OFFSET);
+  uint8_t  ccmr_offset = STM32_GTIM_CCMR1_OFFSET;
+
+  /* Further we use range as 0..3; if channel=0 it will also overflow here */
+
+  if (--channel > 4)
+    {
+      return -EINVAL;
+    }
+
+  /* Assume that channel is disabled and polarity is active high */
+
+  ccer_val &= ~((GTIM_CCER_CC1P | GTIM_CCER_CC1E) <<
+                GTIM_CCER_CCXBASE(channel));
+
+  /* This function is not supported on basic timers. To enable or
+   * disable it, simply set its clock to valid frequency or zero.
+   */
+
+  if (g_tickless.base == STM32_TIM6_BASE ||
+      g_tickless.base == STM32_TIM7_BASE)
+    {
+      return -EINVAL;
+    }
+
+  /* Frozen mode because we don't want to change the GPIO, preload register
+   * disabled.
+   */
+
+  ccmr_val = (GTIM_CCMR_MODE_FRZN << GTIM_CCMR1_OC1M_SHIFT);
+
+  /* Set polarity */
+
+  ccer_val |= GTIM_CCER_CC1P << GTIM_CCER_CCXBASE(channel);
+
+  /* Define its position (shift) and get register offset */
+
+  if ((channel & 1) != 0)
+    {
+      ccmr_val  <<= 8;
+      ccmr_mask <<= 8;
+    }
+
+  if (channel > 1)
+    {
+      ccmr_offset = STM32_GTIM_CCMR2_OFFSET;
+    }
+
+  ccmr_orig  = stm32_getreg16(ccmr_offset);
+  ccmr_orig &= ~ccmr_mask;
+  ccmr_orig |= ccmr_val;
+  stm32_putreg16(ccmr_offset, ccmr_orig);
+  stm32_putreg16(STM32_GTIM_CCER_OFFSET, ccer_val);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_interval_handler
+ *
+ * Description:
+ *   Called when the timer counter matches the compare register
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called early in the initialization sequence before any special
+ *   concurrency protections are required.
+ *
+ ****************************************************************************/
+
+static void stm32_interval_handler(void)
+{
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
+  struct timespec tv;
+#endif
+  tmrinfo("Expired...\n");
+
+  /* Disable the compare interrupt now. */
+
+  stm32_tickless_disableint(g_tickless.channel);
+  stm32_tickless_ackint(g_tickless.channel);
+
+  g_tickless.pending = false;
+
+#ifndef CONFIG_SCHED_TICKLESS_ALARM
+  nxsched_timer_expiration();
+#else
+  up_timer_gettime(&tv);
+  nxsched_alarm_expiration(&tv);
+#endif
+}
+
+/****************************************************************************
+ * Name: stm32_timing_handler
+ *
+ * Description:
+ *   Timer interrupt callback.  When the freerun timer counter overflows,
+ *   this interrupt will occur.  We will just increment an overflow count.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32_timing_handler(void)
+{
+  g_tickless.overflow++;
+
+  STM32_TIM_ACKINT(g_tickless.tch, GTIM_SR_UIF);
+}
+
+/****************************************************************************
+ * Name: stm32_tickless_handler
+ *
+ * Description:
+ *   Generic interrupt handler for this timer.  It checks the source of the
+ *   interrupt and fires the appropriate handler.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int stm32_tickless_handler(int irq, void *context, void *arg)
+{
+  int interrupt_flags = stm32_tickless_getint();
+
+  if (interrupt_flags & GTIM_SR_UIF)

Review comment:
       I'm not going to do these.  I've reached my point of it being too 
nitpicky. Are we really going through every instance of this logic in the 
codebase and changing it to `!= 0`.  Is it really any more readable? 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to