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            String      tickFxn[];
   217            UArg        arg;
   218            String      hwiHandle;
   219        };
   220    
   221        /*! @_nodoc */
   222        metaonly struct DeviceView {
   223            UInt        id;
   224            String      device;
   225            String      devAddr;
   226            UInt        intNum;
   227            UInt32      currCount;
   228            UInt32      nextCompareCount;
   229            UInt32      remainingCount;
   230            String      state;
   231        };
   232    
   233        /*! @_nodoc */
   234        metaonly struct ModuleView {
   235            String      availMask;
   236        }
   237    
   238        /*! @_nodoc */
   239        @Facet
   240        metaonly config ViewInfo.Instance rovViewInfo =
   241            ViewInfo.create({
   242                viewMap: [
   243                [
   244                    'Basic',
   245                    {
   246                        type: ViewInfo.INSTANCE,
   247                        viewInitFxn: 'viewInitBasic',
   248                        structName: 'BasicView'
   249                    }
   250                ],
   251                [
   252                    'Device',
   253                    {
   254                        type: ViewInfo.INSTANCE,
   255                        viewInitFxn: 'viewInitDevice',
   256                        structName: 'DeviceView'
   257                    }
   258                ],
   259                [
   260                    'Module',
   261                    {
   262                        type: ViewInfo.MODULE,
   263                        viewInitFxn: 'viewInitModule',
   264                        structName: 'ModuleView'
   265                    }
   266                ],
   267                ]
   268            });
   269    
   270        /*!
   271         *  ======== E_invalidTimer ========
   272         *  Error raised when specified timer id is not supported
   273         */
   274        config Error.Id E_invalidTimer = {
   275            msg: "E_invalidTimer: Invalid Timer Id %d"
   276        };
   277    
   278        /*!
   279         *  ======== E_notAvailable ========
   280         *  Error raised when requested timer is in use
   281         */
   282        config Error.Id E_notAvailable = {
   283            msg: "E_notAvailable: Timer not available %d"
   284        };
   285    
   286        /*!
   287         *  ======== E_cannotSupport ========
   288         *  Error raised when requested period is not supported
   289         */
   290        config Error.Id E_cannotSupport = {
   291            msg: "E_cannotSupport: Timer cannot support requested period %d"
   292        };
   293    
   294        /*!
   295         *  ======== anyMask ========
   296         *  Mask of available timers
   297         *
   298         *  This mask is used to identify the timers that can be used when
   299         *  Timer_create() is called with an id equal to
   300         *  {@link Timer#ANY Timer_ANY}.
   301         */
   302        config UInt anyMask = 0x1;
   303    
   304        /*!
   305         *  ======== funcHookCH1 ========
   306         *  Optional hook function for processing RTC channel 1 events
   307         *
   308         *  This function will be called when there is a timeout event on
   309         *  RTC Channel 1.  It will be called from hardware interrupt context,
   310         *  so any API calls from this function must be appropriate for
   311         *  execution from an ISR.
   312         *
   313         *  Function hooks are only supported with RunMode_DYNAMIC.
   314         */
   315        config FuncPtr funcHookCH1 = null;
   316    
   317        /*!
   318         *  ======== funcHookCH2 ========
   319         *  Optional hook function for processing RTC channel 2 events.
   320         *
   321         *  This function will be called when there is a timeout event on
   322         *  RTC Channel 2.  It will be called from hardware interrupt context,
   323         *  so any API calls from this function must be appropriate for
   324         *  execution from an ISR.
   325         *
   326         *  Function hooks are only supported with RunMode_DYNAMIC.
   327         */
   328        config FuncPtr funcHookCH2 = null;
   329    
   330        /*!
   331         *  ======== dynamicStub ========
   332         *  @_nodoc
   333         *
   334         *  @param(arg)     Unused.
   335         */
   336        Void dynamicStub(UArg arg);
   337    
   338        /*!
   339         *  ======== dynamicMultiStub ========
   340         *  @_nodoc
   341         *
   342         *  @param(arg)     Unused.
   343         */
   344        Void dynamicMultiStub(UArg arg);
   345    
   346        /*!
   347         *  ======== periodicStub ========
   348         *  @_nodoc
   349         *
   350         *  @param(arg)     Unused.
   351         */
   352        Void periodicStub(UArg arg);
   353    
   354       /*!
   355         *  ======== getCount64 ========
   356         *  Read the 64-bit timer counter register
   357         *
   358         *  @b(returns)     timer counter value
   359         */
   360        UInt64 getCount64(Object * timer);
   361    
   362       /*!
   363         *  ======== getExpiredCounts64 ========
   364         *  Returns expired counts (64-bits) since the last serviced interrupt.
   365         *
   366         *  @b(returns)     timer counter value
   367         */
   368        UInt64 getExpiredCounts64(Object * timer);
   369    
   370        /*!
   371         *  ======== getHandle ========
   372         *  @_nodoc
   373         *  Used by TimestampProvider module to get hold of timer handle used by
   374         *  Clock.
   375         *
   376         *  @param(id)      timer Id.
   377         */
   378        Handle getHandle(UInt id);
   379    
   380    instance:
   381    
   382        /*! Hwi Params for Hwi Object. Default is null. */
   383        config Hwi.Params *hwiParams = null;
   384        
   385    internal:   /* not for client use */
   386    
   387        /*!
   388         *  ======== noStartupNeeded ========
   389         *  Flag used to prevent misc code from being brought in
   390         *  un-necessarily
   391         */
   392        config UInt startupNeeded = false;
   393    
   394        /*
   395         *  ======== initDevice ========
   396         *  reset timer to its resting state
   397         */
   398        Void initDevice(Object *timer);
   399    
   400        /*
   401         *  ======== postInit ========
   402         *  finish initializing static Timers
   403         */
   404        Int postInit(Object *timer, Error.Block *eb);
   405    
   406        /*
   407         *  ======== setThreshold ========
   408         *  set the compare threshold in RTC register
   409         */
   410        Void setThreshold(Object *timer, UInt32 next, Bool wrap);
   411    
   412        struct Instance_State {
   413            Bool                    staticInst;
   414            Int                     id;
   415            ITimer.StartMode        startMode;
   416            UInt32                  period;
   417            UArg                    arg;
   418            Hwi.FuncPtr             tickFxn;
   419            Types.FreqHz            frequency;
   420            Hwi.Handle              hwi;
   421            UInt64                  period64;
   422            UInt64                  savedCurrCount;
   423            UInt64                  prevThreshold;
   424            UInt64                  nextThreshold;
   425        }
   426    
   427        struct Module_State {
   428            UInt            availMask;      /* available peripherals */
   429            Handle          handle;     /* array of handles based on id */
   430        }
   431    }