1    /*
     2     * Copyright (c) 2014-2017, 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.cc26xx;
    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    
    47    /*!
    48     *  ======== Timer ========
    49     *  CC26xx Timer Peripheral Manager
    50     *
    51     *  This Timer module manages the RTC timer peripheral on
    52     *  CC26XX/CC13XX devices.  This Timer operates in a dynamic tick mode
    53     *  (RunMode_DYNAMIC). Rather than interrupting on every fixed tick period,
    54     *  the Timer is dynamically reprogrammed to interrupt on the next required
    55     *  tick (as determined by work that has been scheduled with a future timeout).
    56     *
    57     *  By default, this Timer module is used by the SYS/BIOS
    58     *  {@link ti.sysbios.knl.Clock Clock} module for implementing timing services
    59     *  on CC26XX/CC13XX devices.  Operating in dynamic mode allows the Clock module
    60     *  to implement dynamic tick suppression, to reduce the number of interrupts
    61     *  from the timer, to the minimum required for any scheduled work.
    62     *
    63     *  The RTC peripheral is implemented as a 64-bit counter, with the upper
    64     *  32-bits of count representing seconds, and the lower 32-bits representing
    65     *  sub-seconds.  Three timer "channels" are provided for generating time match
    66     *  interrupt events.  The match compare value for each channel is a 32-bit
    67     *  value, spanning the lower 16-bits of the RTC seconds count, and the upper
    68     *  16-bits of the subsecond count.  There is a single interrupt line from the
    69     *  RTC to generate a CPU interrupt, for a match event occurring on any
    70     *  of these three channels.
    71     *
    72     *  Channel 0 of the RTC is dedicated to use by the Clock module.  This Timer
    73     *  module implementation is therefore responsible for overall management of
    74     *  the RTC, including resetting and starting the RTC during application boot,
    75     *  and providing the single interrupt service routine (ISR) for the RTC.
    76     *
    77     *  Channels 1 and 2 of the RTC are not used by the Clock module.  These
    78     *  channels may be available for use by some applications, depending upon the
    79     *  mix of software components being used.  For this purpose, this Timer
    80     *  module supports sharing of the RTC interrupt, to support usage
    81     *  of these other channels (in parallel with the usage of Channel 0 by the
    82     *  Clock module).
    83     *
    84     *  To use one of these other channels the application will need to explicitly
    85     *  configure an interrupt "hook" function for the channel. In this case, when
    86     *  an RTC interrupt triggers the ISR will check the status of each channel to
    87     *  see if the corresponding channel hook function should be called.
    88     *
    89     *  The time match values for Channel 0 will be automatically programmed by
    90     *  the Clock module.  To use Channels 1 (and/or Channel 2), the application
    91     *  will need to explicitly program the match value for the corresponding
    92     *  channel, for the desired time for the interrupt.  Also, the application
    93     *  will need to explicitly enable the additional channel, and include it in the
    94     *  combined event configuration.
    95     *
    96     *  The below snippets show an example of using Channel 1, with Driverlib API
    97     *  calls to configure an RTC event at 4 seconds after boot.
    98     *
    99     *  First, in the application .cfg file a hook function is defined for
   100     *  Channel 1:
   101     *
   102     *  @p(code)
   103     *    var Timer = xdc.module('ti.sysbios.family.arm.cc26xx.Timer');
   104     *    Timer.funcHookCH1 = "&myHookCH1";
   105     *  @p
   106     *
   107     *  In main(), Channel 1 is first cleared, a compare (match) value of 4 seconds
   108     *  is set, the channel is enabled, and is included (along with Channel
   109     *  0) in the combined event configuration:
   110     *
   111     *  @p(code)
   112     *    AONRTCEventClear(AON_RTC_CH1);
   113     *    AONRTCCompareValueSet(AON_RTC_CH1, 0x40000);
   114     *    AONRTCChannelEnable(AON_RTC_CH1);
   115     *    AONRTCCombinedEventConfig(AON_RTC_CH0 | AON_RTC_CH1);
   116     *  @p
   117     *
   118     *  With the above, myHookCH1() will be called when the RTC reaches a count of
   119     *  4 seconds.  At that time, a new compare value can be written for the next
   120     *  interrupt that should occur for Channel 1.
   121     *
   122     *  @p(html)
   123     *  <h3> Calling Context </h3>
   124     *  <table border="1" cellpadding="3">
   125     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   126     *  </colgroup>
   127     *
   128     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   129     *  <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   130     *    <!--                                                          -->
   131     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td>
   132     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   133     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td>
   134     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   135     *    <tr><td> {@link #Params_init}             </td><td>   N    </td>
   136     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   137     *    <tr><td> {@link #construct}               </td><td>   N    </td>
   138     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   139     *    <tr><td> {@link #create}                  </td><td>   N    </td>
   140     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   141     *    <tr><td> {@link #delete}                  </td><td>   N    </td>
   142     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   143     *    <tr><td> {@link #destruct}                </td><td>   N    </td>
   144     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   145     *    <tr><td> {@link #getCount}                </td><td>   Y    </td>
   146     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   147     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td>
   148     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   149     *    <tr><td> {@link #getFunc}                 </td><td>   Y    </td>
   150     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   151     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td>
   152     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   153     *    <tr><td> {@link #setFunc}                 </td><td>   Y    </td>
   154     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   155     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td>
   156     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   157     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td>
   158     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   159     *    <tr><td> {@link #start}                   </td><td>   Y    </td>
   160     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   161     *    <tr><td> {@link #stop}                    </td><td>   Y    </td>
   162     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   163     *    <tr><td colspan="6"> Definitions: <br />
   164     *       <ul>
   165     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   166     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   167     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   168     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   169     *           <ul>
   170     *             <li> In your module startup after this module is started
   171     *  (e.g. Timer_Module_startupDone() returns TRUE). </li>
   172     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   173     *             <li> During main().</li>
   174     *             <li> During BIOS.startupFxns.</li>
   175     *           </ul>
   176     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   177     *           <ul>
   178     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   179     *             <li> In your module startup before this module is started
   180     *  (e.g. Timer_Module_startupDone() returns FALSE).</li>
   181     *           </ul>
   182     *       </ul>
   183     *    </td></tr>
   184     *
   185     *  </table>
   186     *  @p
   187     */
   188    @ModuleStartup          /* To configure static timers */
   189    @InstanceInitStatic
   190    
   191    module Timer inherits ti.sysbios.interfaces.ITimer
   192    {
   193        /*! override supportsDynamic - this Timer does support RunMode_DYNAMIC */
   194        override metaonly config Bool supportsDynamic = true;
   195    
   196        /*! override defaultMode - use RunMode_PERIODIC by default */
   197        override metaonly config Bool defaultDynamic = true;
   198    
   199        // -------- Module Types --------
   200    
   201        /*! Max value of Timer period for PeriodType_COUNTS */
   202        const UInt MAX_PERIOD = 0xFFFFFFFF;
   203    
   204        /*! @_nodoc
   205         *  Min instructions to use in trigger().
   206         */
   207        const Int MIN_SWEEP_PERIOD = 1;
   208    
   209        /*! @_nodoc */
   210        @XmlDtd
   211        metaonly struct BasicView {
   212            Ptr         halTimerHandle;
   213            String      label;
   214            UInt        id;
   215            String      startMode;
   216            UInt        period;
   217            String      tickFxn[];
   218            UArg        arg;
   219            String      hwiHandle;
   220        };
   221    
   222        /*! @_nodoc */
   223        metaonly struct DeviceView {
   224            UInt        id;
   225            String      device;
   226            String      devAddr;
   227            UInt        intNum;
   228            UInt        period;
   229            UInt64      period64;
   230            UInt        currCount;
   231            UInt        remainingCount;
   232            UInt64      prevThreshold;
   233            UInt64      nextThreshold;
   234            String      state;
   235        };
   236    
   237        /*! @_nodoc */
   238        metaonly struct ModuleView {
   239            String      availMask;
   240        }
   241    
   242        /*! @_nodoc */
   243        @Facet
   244        metaonly config ViewInfo.Instance rovViewInfo =
   245            ViewInfo.create({
   246                viewMap: [
   247                [
   248                    'Basic',
   249                    {
   250                        type: ViewInfo.INSTANCE,
   251                        viewInitFxn: 'viewInitBasic',
   252                        structName: 'BasicView'
   253                    }
   254                ],
   255                [
   256                    'Device',
   257                    {
   258                        type: ViewInfo.INSTANCE,
   259                        viewInitFxn: 'viewInitDevice',
   260                        structName: 'DeviceView'
   261                    }
   262                ],
   263                [
   264                    'Module',
   265                    {
   266                        type: ViewInfo.MODULE,
   267                        viewInitFxn: 'viewInitModule',
   268                        structName: 'ModuleView'
   269                    }
   270                ],
   271                ]
   272            });
   273    
   274        /*!
   275         *  ======== E_invalidTimer ========
   276         *  Error raised when specified timer id is not supported
   277         */
   278        config Error.Id E_invalidTimer = {
   279            msg: "E_invalidTimer: Invalid Timer Id %d"
   280        };
   281    
   282        /*!
   283         *  ======== E_notAvailable ========
   284         *  Error raised when requested timer is in use
   285         */
   286        config Error.Id E_notAvailable = {
   287            msg: "E_notAvailable: Timer not available %d"
   288        };
   289    
   290        /*!
   291         *  ======== E_cannotSupport ========
   292         *  Error raised when requested period is not supported
   293         */
   294        config Error.Id E_cannotSupport = {
   295            msg: "E_cannotSupport: Timer cannot support requested period %d"
   296        };
   297    
   298        /*!
   299         *  ======== anyMask ========
   300         *  Mask of available timers
   301         *
   302         *  This mask is used to identify the timers that can be used when
   303         *  Timer_create() is called with an id equal to
   304         *  {@link Timer#ANY Timer_ANY}.
   305         */
   306        config UInt anyMask = 0x1;
   307    
   308        /*!
   309         *  ======== funcHookCH1 ========
   310         *  Optional hook function for processing RTC channel 1 events
   311         *
   312         *  This function will be called when there is a timeout event on
   313         *  RTC Channel 1.  It will be called from hardware interrupt context,
   314         *  so any API calls from this function must be appropriate for
   315         *  execution from an ISR.
   316         *
   317         *  Function hooks are only supported with RunMode_DYNAMIC.
   318         */
   319        config FuncPtr funcHookCH1 = null;
   320    
   321        /*!
   322         *  ======== funcHookCH2 ========
   323         *  Optional hook function for processing RTC channel 2 events.
   324         *
   325         *  This function will be called when there is a timeout event on
   326         *  RTC Channel 2.  It will be called from hardware interrupt context,
   327         *  so any API calls from this function must be appropriate for
   328         *  execution from an ISR.
   329         *
   330         *  Function hooks are only supported with RunMode_DYNAMIC.
   331         */
   332        config FuncPtr funcHookCH2 = null;
   333    
   334        /*!
   335         *  ======== dynamicStub ========
   336         *  @_nodoc
   337         *
   338         *  @param(arg)     Unused.
   339         */
   340        Void dynamicStub(UArg arg);
   341    
   342        /*!
   343         *  ======== dynamicMultiStub ========
   344         *  @_nodoc
   345         *
   346         *  @param(arg)     Unused.
   347         */
   348        Void dynamicMultiStub(UArg arg);
   349    
   350        /*!
   351         *  ======== periodicStub ========
   352         *  @_nodoc
   353         *
   354         *  @param(arg)     Unused.
   355         */
   356        Void periodicStub(UArg arg);
   357    
   358       /*!
   359         *  ======== getCount64 ========
   360         *  Read the 64-bit timer counter register
   361         *
   362         *  @b(returns)     timer counter value
   363         */
   364        UInt64 getCount64(Object * timer);
   365    
   366       /*!
   367         *  ======== getExpiredCounts64 ========
   368         *  Returns expired counts (64-bits) since the last serviced interrupt.
   369         *
   370         *  @b(returns)     timer counter value
   371         */
   372        UInt64 getExpiredCounts64(Object * timer);
   373    
   374        /*!
   375         *  ======== getHandle ========
   376         *  @_nodoc
   377         *  Used by TimestampProvider module to get hold of timer handle used by
   378         *  Clock.
   379         *
   380         *  @param(id)      timer Id.
   381         */
   382        Handle getHandle(UInt id);
   383    
   384    instance:
   385    
   386        /*! Hwi Params for Hwi Object. Default is null. */
   387        config Hwi.Params *hwiParams = null;
   388        
   389    internal:   /* not for client use */
   390    
   391        /*!
   392         *  ======== noStartupNeeded ========
   393         *  Flag used to prevent misc code from being brought in
   394         *  un-necessarily
   395         */
   396        config UInt startupNeeded = false;
   397    
   398        /*
   399         *  ======== initDevice ========
   400         *  reset timer to its resting state
   401         */
   402        Void initDevice(Object *timer);
   403    
   404        /*
   405         *  ======== postInit ========
   406         *  finish initializing static Timers
   407         */
   408        Int postInit(Object *timer, Error.Block *eb);
   409    
   410        /*
   411         *  ======== setThreshold ========
   412         *  set the compare threshold in RTC register
   413         */
   414        Void setThreshold(Object *timer, UInt32 next, Bool wrap);
   415    
   416        struct Instance_State {
   417            Bool                    staticInst;
   418            Int                     id;
   419            ITimer.StartMode        startMode;
   420            UInt32                  period;
   421            UArg                    arg;
   422            Hwi.FuncPtr             tickFxn;
   423            Types.FreqHz            frequency;
   424            Hwi.Handle              hwi;
   425            UInt64                  period64;
   426            UInt64                  savedCurrCount;
   427            UInt64                  prevThreshold;
   428            UInt64                  nextThreshold;
   429        }
   430    
   431        struct Module_State {
   432            UInt            availMask;      /* available peripherals */
   433            Handle          handle;     /* array of handles based on id */
   434        }
   435    }