This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new d269c0f350 arch/arm/src/samv7/sam_tc_lowerhalf.c: do not set the 
CPCSTOP bit
d269c0f350 is described below

commit d269c0f3508ebbacbddcdd06aaad1d25b9455f37
Author: Stepan Pressl <pressl.ste...@gmail.com>
AuthorDate: Fri Feb 7 00:14:41 2025 +0100

    arch/arm/src/samv7/sam_tc_lowerhalf.c: do not set the CPCSTOP bit
    
    The CPCSTOP has a negative effect on the periodic timer operation.
    This causes the timer to stop when an overrun occurs.
    Timer must be then restarted in the interrupt. However, as interrupts
    are not infinitely fast, this prolongs the next timeout.
    
    Signed-off-by: Stepan Pressl <pressl.ste...@gmail.com>
---
 arch/arm/src/samv7/sam_tc_lowerhalf.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/arch/arm/src/samv7/sam_tc_lowerhalf.c 
b/arch/arm/src/samv7/sam_tc_lowerhalf.c
index 732aa4e901..5031319c7a 100644
--- a/arch/arm/src/samv7/sam_tc_lowerhalf.c
+++ b/arch/arm/src/samv7/sam_tc_lowerhalf.c
@@ -193,6 +193,18 @@ static void sam_timer_handler(TC_HANDLE tch, void *arg, 
uint32_t sr)
   struct sam_lowerhalf_s *lower = (struct sam_lowerhalf_s *)arg;
   uint32_t next_interval_us = 0;
 
+  /*  CPCSTOP should not be set! This has a negative impact on periodic
+   *  timer operation. If CPCSTOP is set, the timer is stopped when
+   *  an overrun happens and must be restarted manually here.
+   *  However, as interrupt handlers are not infinitely fast, they can
+   *  introduce a delay for each start, effectively prolonging
+   *  the next timeout.
+   *
+   *  If notify.periodic = false, it can happen the timer is so fast
+   *  it overruns again before lower->callback returns false.
+   *  However, usage of such small delays is unlikely in an application.
+   */
+
   if (lower->callback(&next_interval_us, lower->arg))
     {
       if (next_interval_us > 0)
@@ -200,10 +212,6 @@ static void sam_timer_handler(TC_HANDLE tch, void *arg, 
uint32_t sr)
           sam_settimeout((struct timer_lowerhalf_s *)lower,
                          next_interval_us);
         }
-
-      /* Start the counter */
-
-      sam_tc_start(tch);
     }
   else
     {
@@ -624,7 +632,6 @@ int sam_timer_initialize(const char *devpath, int chan)
    *   TC_CMR_TCCLKS       - Returned by sam_tc_clockselect
    *   TC_CMR_CLKI=0       - Not inverted
    *   TC_CMR_BURST_NONE   - Not gated by an external signal
-   *   TC_CMR_CPCSTOP=1    - Stop the clock on an RC compare event
    *   TC_CMR_CPCDIS=0     - Don't disable the clock on an RC compare event
    *   TC_CMR_EEVTEDG_NONE - No external events (and, hence, no edges
    *   TC_CMR_EEVT_TIOB    - ???? REVISIT
@@ -640,13 +647,15 @@ int sam_timer_initialize(const char *devpath, int chan)
    *   TC_CMR_BCPC_NONE    - RC compare has no effect on TIOB
    *   TC_CMR_BEEVT_NONE   - No external event effect on TIOB
    *   TC_CMR_BSWTRG_NONE  - No software trigger effect on TIOB
+   *
+   *   Do not set CPCSTOP. More explanation in the irq handler.
    */
 
-  cmr |= (TC_CMR_BURST_NONE  | TC_CMR_CPCSTOP     | TC_CMR_EEVTEDG_NONE |
-          TC_CMR_EEVT_TIOB   | TC_CMR_WAVSEL_UPRC | TC_CMR_WAVE         |
-          TC_CMR_ACPA_NONE   | TC_CMR_ACPC_NONE   | TC_CMR_AEEVT_NONE   |
-          TC_CMR_ASWTRG_NONE | TC_CMR_BCPB_NONE   | TC_CMR_BCPC_NONE    |
-          TC_CMR_BEEVT_NONE  | TC_CMR_BSWTRG_NONE);
+  cmr |= (TC_CMR_BURST_NONE  | TC_CMR_EEVTEDG_NONE | TC_CMR_EEVT_TIOB   |
+          TC_CMR_WAVSEL_UPRC | TC_CMR_WAVE         | TC_CMR_ACPA_NONE   |
+          TC_CMR_ACPC_NONE   | TC_CMR_AEEVT_NONE   | TC_CMR_ASWTRG_NONE |
+          TC_CMR_BCPB_NONE   | TC_CMR_BCPC_NONE    | TC_CMR_BEEVT_NONE  |
+          TC_CMR_BSWTRG_NONE);
 
   lower->tch = sam_tc_allocate(chan, cmr);
 

Reply via email to