1    /*
     2     * Copyright (c) 2014-2015, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    /*
    33     *  ======== Timer.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.family.arm.cc32xx;
    38    
    39    import xdc.rov.ViewInfo;
    40    
    41    import xdc.runtime.Types;
    42    import xdc.runtime.Error;
    43    
    44    import ti.sysbios.interfaces.ITimer;
    45    import ti.sysbios.family.arm.m3.Hwi;
    46    import ti.sysbios.knl.Clock;
    47    
    48    /*!
    49     *  ======== Timer ========
    50     *  CC3200 Timer Peripheral Manager
    51     *
    52     *  This module manages the 32Khz RTC timer available on CC3200 devices.
    53     *  The RTC timer uses 2 32-bit words, with the upper 16 bits of the MSW
    54     *  reserved, resulting in a 48-bit counter.
    55     *
    56     *  The Timer module supports the timer in 'one shot', 'continuous', and
    57     *  'dynamic' modes.
    58     *
    59     *  In 'one shot' mode, a timer function will "fire" (run) when the timer
    60     *  period expires. In 'one shot' mode this will only happen once.
    61     *
    62     *  In 'continuous' mode, the specified timer function will "fire" every
    63     *  time the period expires, throughout the lifetime of the program.
    64     *
    65     *  In 'dynamic' mode, the specified timer function will "fire" every
    66     *  time the period expires.  But the period of the timer can be changed
    67     *  dynamically, to correspond to the next tick interrupt needed from the
    68     *  timer.  This mode is used by the SYS/BIOS
    69     *  {@link ti.sysbios.knl.Clock Clock} module for implementing
    70     *  dynamic tick suppression, to reduce the number of interrupts from the
    71     *  timer to the minimum required for currently scheduled timeouts.
    72     *
    73     *  @a(Warning)
    74     *  Some of the RTC timer registers are accessed from the 32KHz clock
    75     *  domain, making reads/writes to these registers on the order of 100
    76     *  microseconds.
    77     *  If using the RTC timer for the {@link ti.sysbios.knl.Clock Clock}
    78     *  module's tick source, the interrupt latency will be as high as 200
    79     *  microseconds, as the {@link ti.sysbios.knl.Clock Clock} ISR makes two
    80     *  RTC register accesses on the 32KHz clock domain.
    81     *
    82     *  @p(html)
    83     *  <h3> Calling Context </h3>
    84     *  <table border="1" cellpadding="3">
    85     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    86     *  </colgroup>
    87     *
    88     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
    89     *  <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    90     *    <!--                                                          -->
    91     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td>
    92     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    93     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td>
    94     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    95     *    <tr><td> {@link #Params_init}             </td><td>   N    </td>
    96     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    97     *    <tr><td> {@link #construct}               </td><td>   N    </td>
    98     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    99     *    <tr><td> {@link #create}                  </td><td>   N    </td>
   100     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   101     *    <tr><td> {@link #delete}                  </td><td>   N    </td>
   102     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   103     *    <tr><td> {@link #destruct}                </td><td>   N    </td>
   104     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   105     *    <tr><td> {@link #getCount}                </td><td>   Y    </td>
   106     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td>
   108     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #getFunc}                 </td><td>   Y    </td>
   110     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   111     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td>
   112     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   113     *    <tr><td> {@link #setFunc}                 </td><td>   Y    </td>
   114     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   115     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td>
   116     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   117     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td>
   118     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   119     *    <tr><td> {@link #start}                   </td><td>   Y    </td>
   120     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   121     *    <tr><td> {@link #stop}                    </td><td>   Y    </td>
   122     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   123     *    <tr><td colspan="6"> Definitions: <br />
   124     *       <ul>
   125     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   126     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   127     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   128     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   129     *           <ul>
   130     *             <li> In your module startup after this module is started
   131     *  (e.g. Timer_Module_startupDone() returns TRUE). </li>
   132     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   133     *             <li> During main().</li>
   134     *             <li> During BIOS.startupFxns.</li>
   135     *           </ul>
   136     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   137     *           <ul>
   138     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   139     *             <li> In your module startup before this module is started
   140     *  (e.g. Timer_Module_startupDone() returns FALSE).</li>
   141     *           </ul>
   142     *       </ul>
   143     *    </td></tr>
   144     *
   145     *  </table>
   146     *  @p
   147     */
   148    @ModuleStartup          /* To configure static timers */
   149    @InstanceInitStatic
   150    
   151    module Timer inherits ti.sysbios.interfaces.ITimer
   152    {
   153        /*! override supportsDynamic - this Timer does support RunMode_DYNAMIC */
   154        override metaonly config Bool supportsDynamic = true;
   155    
   156        /*! override defaultMode - use RunMode_PERIODIC by default */
   157        override metaonly config Bool defaultDynamic = true;
   158    
   159        /*! Max value of Timer period for PeriodType_COUNTS */
   160        const UInt64 MAX_PERIOD = 0xFFFFFFFFFFFF;
   161    
   162    
   163        /*! @_nodoc */
   164        @XmlDtd
   165        metaonly struct BasicView {
   166            Ptr         halTimerHandle;
   167            String      label;
   168            UInt        id;
   169            String      startMode;
   170            UInt64      period;
   171            String      tickFxn[];
   172            UArg        arg;
   173            String      hwiHandle;
   174        };
   175    
   176        /*! @_nodoc */
   177        metaonly struct DeviceView {
   178            UInt        id;
   179            String      device;
   180            String      devAddr;
   181            UInt        intNum;
   182            UInt64      period64;
   183            UInt        currCount;
   184            UInt        remainingCount;
   185            UInt64      nextThreshold;
   186            String      state;
   187        };
   188    
   189        /*! @_nodoc */
   190        metaonly struct ModuleView {
   191            String      availMask;
   192        }
   193    
   194        /*! @_nodoc */
   195        @Facet
   196        metaonly config ViewInfo.Instance rovViewInfo =
   197            ViewInfo.create({
   198                viewMap: [
   199                [
   200                    'Basic',
   201                    {
   202                        type: ViewInfo.INSTANCE,
   203                        viewInitFxn: 'viewInitBasic',
   204                        structName: 'BasicView'
   205                    }
   206                ],
   207                [
   208                    'Device',
   209                    {
   210                        type: ViewInfo.INSTANCE,
   211                        viewInitFxn: 'viewInitDevice',
   212                        structName: 'DeviceView'
   213                    }
   214                ],
   215                [
   216                    'Module',
   217                    {
   218                        type: ViewInfo.MODULE,
   219                        viewInitFxn: 'viewInitModule',
   220                        structName: 'ModuleView'
   221                    }
   222                ],
   223                ]
   224            });
   225    
   226        /*!
   227         *  ======== E_invalidTimer ========
   228         *  Error raised when specified timer id is not supported
   229         */
   230        config Error.Id E_invalidTimer = {
   231            msg: "E_invalidTimer: Invalid Timer Id %d"
   232        };
   233    
   234        /*!
   235         *  ======== E_notAvailable ========
   236         *  Error raised when requested timer is in use
   237         */
   238        config Error.Id E_notAvailable = {
   239            msg: "E_notAvailable: Timer not available %d"
   240        };
   241    
   242        /*!
   243         *  ======== E_cannotSupport ========
   244         *  Error raised when requested period is not supported
   245         */
   246        config Error.Id E_cannotSupport = {
   247            msg: "E_cannotSupport: Timer cannot support requested period %d"
   248        };
   249    
   250        /*!
   251         *  ======== anyMask ========
   252         *  Mask of available timers
   253         *
   254         *  This mask is used to identify the timers that can be used when
   255         *  Timer_create() is called with an id equal to
   256         *  {@link Timer#ANY Timer_ANY}.
   257         */
   258        config UInt anyMask = 0x1;
   259    
   260    
   261        /*!
   262         *  Period of a tick
   263         *
   264         *  The RTC timer can take up to a 48-bit period.
   265         *  (The implementation of ITimer supports a period of UInt32
   266         *  timer counts).
   267         */
   268        config UInt64 period64 = 0;
   269    
   270        /*!
   271         *  ======== dynamicStub ========
   272         *  @_nodoc
   273         *
   274         *  @param(arg)     Unused.
   275         */
   276        Void dynamicStub(UArg arg);
   277    
   278        /*!
   279         *  ======== periodicStub ========
   280         *  @_nodoc
   281         *
   282         *  @param(arg)     Unused.
   283         */
   284        Void periodicStub(UArg arg);
   285    
   286       /*!
   287         *  ======== getCount64 ========
   288         *  Read the 64-bit timer counter register
   289         *
   290         *  @b(returns)     timer counter value
   291         */
   292        UInt64 getCount64(Object * timer);
   293    
   294       /*!
   295         *  ======== getMatchShadowReg ========
   296         *  Get the 64-bit value last written to the match register
   297         *
   298         *  @b(returns)     match register value
   299         */
   300        UInt64 getMatchShadowReg();
   301    
   302        /*!
   303         *  ======== getAvailMask ========
   304         *  Returns the availMask.
   305         *
   306         *  @b(returns)     Mask of available timers
   307         */
   308        UInt getAvailMask();
   309    
   310        /*!
   311         *  ======== setAvailMask ========
   312         *  Set the availMask to given mask.
   313         *
   314         *  This function validates the given mask to ensure it does not mark
   315         *  any currently used timer as available. If validation is successful,
   316         *  the mask overwrites the current availMask and the function returns
   317         *  TRUE. Otherwise, the mask is discarded and the function returns
   318         *  FALSE.
   319         *
   320         *  @param(mask)    Mask used to write to availMask
   321         */
   322        Bool setAvailMask(UInt mask);
   323    
   324        /*!
   325         *  ======== getHandle ========
   326         *  @_nodoc
   327         *  Used by TimestampProvider module to get hold of timer handle used by
   328         *  Clock.
   329         *
   330         *  @param(id)      timer Id.
   331         */
   332        Handle getHandle(UInt id);
   333    
   334        /*!
   335         *  ======== setNextMaxTick ========
   336         *  @_nodoc
   337         *  Instead of using maxSkippable, this timer sets the next
   338         *  scheduled tick to the last tick just before the next rollover
   339         *  of the lower 32-bits of the counter.
   340         */
   341        Void setNextMaxTick(UArg arg);
   342    
   343    instance:
   344    
   345        /*! Hwi Params for Hwi Object. Default is null. */
   346        config Hwi.Params *hwiParams = null;
   347    
   348    internal:   /* not for client use */
   349    
   350        /*!
   351         *  ======== noStartupNeeded ========
   352         *  Flag used to prevent misc code from being brought in
   353         *  un-necessarily
   354         */
   355        config UInt startupNeeded = false;
   356    
   357        /*
   358         *  ======== initDevice ========
   359         *  reset timer to its resting state
   360         */
   361        Void initDevice(Object *timer);
   362    
   363        /*
   364         *  ======== setThreshold ========
   365         *  set the compare threshold in RTC register
   366         */
   367        Void setThreshold(Object *timer, UInt64 next);
   368    
   369        struct Instance_State {
   370            Bool                    staticInst;
   371            Int                     id;
   372            ITimer.StartMode        startMode;
   373            UArg                    arg;
   374            Hwi.FuncPtr             tickFxn;
   375            Types.FreqHz            frequency;
   376            Hwi.Handle              hwi;
   377            UInt64                  period64;
   378            UInt64                  savedCurrCount;
   379        }
   380    
   381        struct Module_State {
   382            UInt            availMask;  /* available peripherals */
   383            Handle          handle;     /* array of handles based on id */
   384    
   385            /*
   386             *  Clock object for setting the next interrupt to, when nothing else
   387             *  is on the clock queue.
   388             */
   389            Clock.Handle    clock;
   390    
   391            /*
   392             *  The value of the upper 32 bits of timer counter register
   393             *  at, or a few Clock ticks after the time the Clock object was
   394             *  last started.
   395             */
   396            UInt32          timeUpper;
   397    
   398            /*
   399             *  We need the period for the Clock function.  There is only one
   400             *  timer, and this period will be the same as the Timer object's
   401             *  period.
   402             */
   403            UInt64          period64;
   404    
   405            /*
   406             *  Shadow the match register.  This is part of the module
   407             *  state, so it can be accessed from an API without having to
   408             *  specify a Timer object.
   409             */
   410            UInt64          nextThreshold;
   411        }
   412    }