1    /*
     2     * Copyright (c) 2012, 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    
    38    package ti.sysbios.family.c28;
    39    
    40    import xdc.rov.ViewInfo;
    41    
    42    import xdc.runtime.Error;
    43    import xdc.runtime.Assert;
    44    import xdc.runtime.Types;
    45    import ti.sysbios.interfaces.ITimer;
    46    
    47    /*!
    48     *  ======== Timer ========
    49     *  Timer peripherals manager for the c28 family.
    50     *
    51     *  @p(html)
    52     *  <h3> 28x Timers </h3>
    53     *  @p(blist)
    54     *  - The 28x has three 32-bit timers.
    55     *  - The 28x timer counts downward from 'period' to 0; however, Timer_getCount
    56     *    will count upward.
    57     *  - The 28x timer supports an optional 16-bit prescalar. The prescalar
    58     *    effectively sets the period of the timer tick; the prescalar counts down
    59     *    from the prescale factor to 0, then a timer tick occurs. So, with a
    60     *    prescale set, the actual timer period is (prescale * period).
    61     *  @p
    62     *
    63     *  @p(html)
    64     *  <h3> Calling Context </h3>
    65     *  <table border="1" cellpadding="3">
    66     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
    67     *
    68     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    69     *    <!--                                                                                                                 -->
    70     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    71     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    72     *    <tr><td> {@link #Params_init}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    73     *    <tr><td> {@link #construct}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    74     *    <tr><td> {@link #create}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    75     *    <tr><td> {@link #delete}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    76     *    <tr><td> {@link #destruct}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    77     *    <tr><td> {@link #getCount}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    78     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    79     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    80     *    <tr><td> {@link #getPrescale}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    81     *    <tr><td> {@link #getPrescaleCount}        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    82     *    <tr><td> {@link #reconfig}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    83     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    84     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    85     *    <tr><td> {@link #setPrescale}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    86     *    <tr><td> {@link #start}                   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    87     *    <tr><td> {@link #stop}                    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    88     *    <tr><td colspan="6"> Definitions: <br />
    89     *       <ul>
    90     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
    91     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
    92     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
    93     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
    94     *           <ul>
    95     *             <li> In your module startup after this module is started (e.g. Timer_Module_startupDone() returns TRUE). </li>
    96     *             <li> During xdc.runtime.Startup.lastFxns. </li>
    97     *             <li> During main().</li>
    98     *             <li> During BIOS.startupFxns.</li>
    99     *           </ul>
   100     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   101     *           <ul>
   102     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   103     *             <li> In your module startup before this module is started (e.g. Timer_Module_startupDone() returns FALSE).</li>
   104     *           </ul>
   105     *       </ul>
   106     *    </td></tr>
   107     *  </table>
   108     *  @p
   109     */
   110    
   111    @InstanceFinalize       /* Clear the timer and delete its Hwi */
   112    @InstanceInitError      /* To report unavailability of a timer */
   113    @ModuleStartup          /* To configure static timers */
   114    
   115    module Timer inherits ti.sysbios.interfaces.ITimer
   116    {
   117        /*! Max value of Timer period for PeriodType_COUNTS*/
   118        const UInt MAX_PERIOD = 0xffffffff;
   119    
   120        /*! Number of timer peripherals on chip */
   121        const Int NUM_TIMER_DEVICES = 3;
   122    
   123        /*! Timer Emulation Mode. */
   124        struct EmulationMode {
   125            UInt free;      /*! At sw breakpoint, stop or free-run the timer. */
   126            UInt soft;      /*! At sw breakpoint, hard stop or run down timer. */
   127        };
   128    
   129        /*! @_nodoc */
   130        metaonly struct BasicView {
   131            Ptr         halTimerHandle;
   132            String      label;
   133            UInt        id;
   134            String      startMode;
   135            String      runMode;
   136            UInt        period;
   137            String      periodType;
   138            UInt        prescalar;
   139            UInt        intNum;
   140            UArg        arg;
   141            String      tickFxn[];
   142            String      hwiHandle;
   143        };
   144    
   145        /*! @_nodoc */
   146        metaonly struct DeviceView {
   147            UInt        id;
   148            String      deviceAddr;
   149            UInt        intNum;
   150            UInt        period;
   151            UInt        currCount;
   152            UInt        remainingCount;
   153        };
   154    
   155        /*! @_nodoc */
   156        @Facet
   157        metaonly config ViewInfo.Instance rovViewInfo =
   158            ViewInfo.create({
   159                viewMap: [
   160                    ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
   161                    ['Device', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDevice', structName: 'DeviceView'}],
   162                ]
   163            });
   164    
   165        /*!
   166         *  Assert raised in Timer_create when timer id specified is not supported.
   167         */
   168        config Assert.Id A_invalidTimer = {
   169            msg: "A_invalidTimer: Timer id must be 0-2"
   170        };
   171    
   172        /*!
   173         *  Error raised in Timer_create when timer requested is in use.
   174         */
   175        config Error.Id E_notAvailable = {
   176            msg: "E_notAvailable: Timer not available %d"
   177        };
   178    
   179        /*!
   180         *  Assert raised in Timer_create if an invalid RunMode is requested.
   181         */
   182        config Assert.Id A_invalidRunMode = {
   183            msg: "A_invalidRunMode: Invalid RunMode"
   184        };
   185    
   186        /*!
   187         *  Assert raised in Timer_create when Hwi Params does not mask 'self'.
   188         *
   189         *  This is not allowed because the timers on this platform do not
   190         *  inherently support one-shot mode. Instead, a stub is used to stop the
   191         *  timer, so it is important that the timer interrupt not occur again
   192         *  before the stub has stopped the timer.
   193         */
   194        config Assert.Id A_invalidHwiMask = {
   195            msg: "A_InvalidMask: Mask in hwiParams cannot enable self"
   196        };
   197    
   198        /*!
   199         *  Assert raised when period requested is not supported.
   200         */
   201        config Assert.Id E_cannotSupport = {
   202            msg: "E_cannotSupport: Timer cannot support requested period"
   203        };
   204    
   205        /*!
   206         *  ======== anyMask ========
   207         *  Available mask to be used when select = Timer_ANY
   208         */
   209        config UInt anyMask = 0x7;
   210    
   211    instance:
   212    
   213        /*!
   214         *  ======== emulationModeInit ========
   215         *  Initial timer emulation mode. Default hard stop.
   216         *
   217         *  Determines timer state at a software breakpoint. If 'free' is 1, the
   218         *  timer will continue to run, and the value of 'soft' doesn't matter.
   219         *  When 'free' is 0 and 'soft' is 1, the timer runs down to 0 then stops.
   220         *  When 'free' is 0 and 'soft' is 0, the timer halts.
   221         *
   222         *  @p(html)
   223         *  <pre>
   224         *  FREE   SOFT
   225         *  0      0      Stop after next timer decrement. (Hard stop)
   226         *  0      1      Stop after timer runs down to 0. (Soft stop)
   227         *  1      x      Continue running the timer.
   228         *  </pre>
   229         */
   230        config EmulationMode emulationModeInit = {free: 0, soft: 0};
   231    
   232        /*!
   233         *  ======== prescale ========
   234         *  Prescale factor.
   235         *
   236         *  The prescale factor determines the length of a timer tick.
   237         *  If a prescale of 10 is specified, a timer tick will occur
   238         *  every 11 cycles.
   239         *
   240         *  If the timer is used as a counter, the prescale factor determines
   241         *  the period between counts. Otherwise, the prescale factor can be used
   242         *  to achieve longer timer periods: with a prescale specified, the actual
   243         *  period is (period * prescale+1).
   244         */
   245        config UInt16 prescale = 0;
   246    
   247        /*!
   248         *  ======== hwiParams ========
   249         *  Parameters for the Hwi object created for the Timer ISR.
   250         *
   251         *  The mask setting for the Hwi object should include SELF to prevent
   252         *  nested timer interrupts.
   253         */
   254        config Hwi.Params *hwiParams = null;
   255    
   256        /*!
   257         *  ======== getCount ========
   258         *  Returns the number of counts that have passed.
   259         *
   260         *  The 28x timer counts downward from the period to 0, but getCount
   261         *  subtracts the timer counter value from the period so that getCount
   262         *  counts upward instead of downward.
   263         *
   264         *  @b(returns) timer counts, counting upward from 0
   265         */
   266        @DirectCall
   267        override UInt32 getCount();
   268    
   269        /*!
   270         *  ======== setPreScale ========
   271         *  Set timer prescale value.
   272         *
   273         *  This function sets the value of the prescalar, and will also reload
   274         *  the timer counter and prescale registers.
   275         *
   276         *  The prescalar decrements with each timer clock source cycle until it
   277         *  reaches zero, then the timer's count is decremented by one. The
   278         *  prescalar has the effect of setting the rate of the timer tick.
   279         *
   280         *  @param(preScalar) The value to set the prescale period to.
   281         */
   282        Void setPrescale(UInt16 preScalar);
   283    
   284        /*!
   285         *  ======== getPrescale ========
   286         *  Get timer prescale value.
   287         *
   288         *  This is not the prescale count, but the period of the prescalar.
   289         *
   290         *  @b(returns) prescale value
   291         */
   292        UInt16 getPrescale();
   293    
   294        /*!
   295         *  ======== getPrescaleCount ========
   296         *  Reads timer prescale counter.
   297         *
   298         *  The prescale counter counts down from prescale to 0, but
   299         *  getPrescaleCount subtracts the counter value from the period so that
   300         *  this function counts upward instead of downward.
   301         *
   302         *  @b(returns) prescale counter, counting upward from 0
   303         */
   304        UInt16 getPrescaleCount();
   305    
   306        /*!
   307         *  ======== getExpiredCounts64 ========
   308         *  @_nodoc
   309         *  Called by TimestampProvider to read the timer counter, accounting
   310         *  for counter rollover.
   311         *
   312         *  This version of the API returns a 64-bit count and is only used when
   313         *  the TimestampProvider is using a dedicated timer.
   314         *
   315         *  This function must be called with interrupts disabled.
   316         *
   317         *  @b(returns) Timer counts, accounting for counter rollover.
   318         */
   319        @DirectCall
   320        Void getExpiredCounts64(Types.Timestamp64 *result);
   321    
   322        /*!
   323         *  ======== reconfig ========
   324         *  Used to modify timer instances at runtime.
   325         *
   326         *  @param(timerParams)     timer Params
   327         *  @param(tickFxn)         functions that runs when timer expires
   328         */
   329        @DirectCall
   330        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   331    
   332    internal:   /* not for client use */
   333    
   334        /*
   335         *  ======== postInit ========
   336         *  finish initializing static and dynamic Timers
   337         */
   338        Int postInit(Object *timer, Error.Block *eb);
   339    
   340        /*
   341         *  ======== stopAndClear ========
   342         */
   343        Void stopAndClear(Object *timer);
   344    
   345        /*
   346         *  ======== checkOverflow ========
   347         */
   348        Bool checkOverflow(UInt32 a, UInt32 b);
   349    
   350        /*!
   351         *  ======== oneShotStub ========
   352         *  This stub implements oneShot mode by stopping the timer and clearing
   353         *  the CPU IFR bit. It does not clear the PIEIFR bit, so timer 0 does
   354         *  not support one shot mode.
   355         *
   356         *  @param(arg) The timer object
   357         */
   358        Void oneShotStub(UArg arg);
   359    
   360        /*!
   361         *  ======== startupNeeded ========
   362         *  Flag used to prevent Module_startup and Timer_startup code from being
   363         *  brought in unnecessarily. Flag is set if there are any static Timer
   364         *  instances.
   365         */
   366        config UInt startupNeeded = false;
   367    
   368        config UInt8 intNumDef[3];
   369    
   370        struct Instance_State {
   371            Int                id;             /* timer id. */
   372            EmulationMode      emulationModeInit; /* initial emu mode */
   373            ITimer.RunMode     runMode;        /* timer mode */
   374            ITimer.StartMode   startMode;      /* timer mode */
   375            UInt32             period;         /* period */
   376            ITimer.PeriodType  periodType;
   377            UInt16             prescale;       /* prescale */
   378            UInt               intNum;         /* intr num */
   379            UArg               arg;            /* tickFxn arg*/
   380            Hwi.FuncPtr        tickFxn;        /* tickFxn */
   381            Types.FreqHz       extFreq;
   382            Hwi.Handle         hwi;
   383        }
   384    
   385        struct Module_State {
   386            Char   availMask;                       /* Available peripherals */
   387            Handle staticTimers[NUM_TIMER_DEVICES]; /* Array of statically created
   388                                                     * timer handles based on id */
   389        }
   390    }