1    /*
     2     * Copyright (c) 2015-2016, 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    package ti.sysbios.timers.rti;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import xdc.runtime.Assert;
    41    import xdc.runtime.Error;
    42    import xdc.runtime.Types;
    43    import ti.sysbios.interfaces.ITimer;
    44    import ti.sysbios.hal.Hwi;
    45    
    46    /*!
    47     *  ======== Timer ========
    48     *  RTI Timer Peripheral Manager.
    49     *
    50     *  This Timer module manages the RTI timer peripheral(s) available on the ARM
    51     *  and C6000 devices (see {@link ./doc-files/TimerTables.html Timer Mapping Tables}
    52     *  for supported device information).
    53     *
    54     *  @p(html)
    55     *  <h3> Calling Context </h3>
    56     *  <table border="1" cellpadding="3">
    57     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
    58     *
    59     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    60     *    <!--                                                                                                                 -->
    61     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    62     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    63     *    <tr><td> {@link #Params_init}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    64     *    <tr><td> {@link #construct}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    65     *    <tr><td> {@link #create}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    66     *    <tr><td> {@link #delete}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    67     *    <tr><td> {@link #destruct}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    68     *    <tr><td> {@link #getCount}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    69     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    70     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    71     *    <tr><td> {@link #reconfig}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    72     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    73     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    74     *    <tr><td> {@link #start}                   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    75     *    <tr><td> {@link #stop}                    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    76     *    <tr><td colspan="6"> Definitions: <br />
    77     *       <ul>
    78     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
    79     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
    80     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
    81     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
    82     *           <ul>
    83     *             <li> In your module startup after this module is started (e.g. Timer_Module_startupDone() returns TRUE). </li>
    84     *             <li> During xdc.runtime.Startup.lastFxns. </li>
    85     *             <li> During main().</li>
    86     *             <li> During BIOS.startupFxns.</li>
    87     *           </ul>
    88     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
    89     *           <ul>
    90     *             <li> During xdc.runtime.Startup.firstFxns.</li>
    91     *             <li> In your module startup before this module is started (e.g. Timer_Module_startupDone() returns FALSE).</li>
    92     *           </ul>
    93     *       </ul>
    94     *    </td></tr>
    95     *
    96     *  </table>
    97     *  @p
    98     *
    99     */
   100    @ModuleStartup          /* to configure static timers */
   101    
   102    module Timer inherits ti.sysbios.interfaces.ITimer
   103    {
   104        /*! Max value of Timer period for PeriodType_COUNTS*/
   105        const UInt MAX_PERIOD = 0xffffffff;
   106    
   107        /*! @_nodoc
   108         *  Min instructions to use in trigger().
   109         */
   110        const Int MIN_SWEEP_PERIOD = 8;
   111    
   112        /*! Timer Settings. */
   113        metaonly struct TimerSetting {
   114            Ptr baseAddr;   /*! specify the base address  */
   115            Int intNum;     /*! specify which interrupt vector */
   116            Int eventId;    /*! specify which event number to use */
   117            String name;    /*! specify the timer name */
   118        };
   119    
   120        /*! @_nodoc */
   121        @XmlDtd
   122        metaonly struct BasicView {
   123            Ptr         halTimerHandle;
   124            String      label;
   125            UInt        id;
   126            String      name;
   127            String      startMode;
   128            String      runMode;
   129            UInt        periodInCounts;
   130            UInt        periodInMicroSecs;
   131            UInt        intNum;
   132            Int         eventId;
   133            String      tickFxn[];
   134            UArg        arg;
   135            String      extFreq;
   136            String      hwiHandle;
   137        };
   138    
   139        /*! @_nodoc */
   140        metaonly struct DeviceView {
   141            UInt        id;
   142            String      device;
   143            String      devAddr;
   144            UInt        intNum;
   145            String      runMode;
   146            UInt        period;
   147            String      state;
   148        };
   149    
   150        /*! @_nodoc */
   151        metaonly struct ModuleView {
   152            String      availMask;      /* available 32-bit timer halves */
   153            String      intFrequency[]; /* internal frequency in Hz */
   154        }
   155    
   156        /*! @_nodoc */
   157        @Facet
   158        metaonly config ViewInfo.Instance rovViewInfo =
   159            ViewInfo.create({
   160                viewMap: [
   161                [
   162                    'Basic',
   163                    {
   164                        type: ViewInfo.MODULE_DATA,
   165                        viewInitFxn: 'viewInitBasic',
   166                        structName: 'BasicView'
   167                    }
   168                ],
   169                [
   170                    'Device',
   171                    {
   172                        type: ViewInfo.INSTANCE,
   173                        viewInitFxn: 'viewInitDevice',
   174                        structName: 'DeviceView'
   175                    }
   176                ],
   177                [
   178                    'Module',
   179                    {
   180                        type: ViewInfo.MODULE,
   181                        viewInitFxn: 'viewInitModule',
   182                        structName: 'ModuleView'
   183                    }
   184                ],
   185                ]
   186            });
   187    
   188        /*!
   189         *  ======== A_invalidTimer ========
   190         *  Assert raised when timer id specified is not supported.
   191         */
   192        config xdc.runtime.Assert.Id A_invalidTimer  = {
   193            msg: "A_invalidTimer: Invalid Timer Id."
   194        };
   195    
   196        /*!
   197         *  Error raised when timer id specified is not supported.
   198         */
   199        config Error.Id E_invalidTimer =
   200            {msg: "E_invalidTimer: Invalid Timer Id %d"};
   201    
   202        /*!
   203         *  Error raised when timer requested is in use
   204         */
   205        config Error.Id E_notAvailable =
   206            {msg: "E_notAvailable: Timer not available %d"};
   207    
   208        /*!
   209         *  Error raised when Hwi Params has mask where self is turned on.
   210         *
   211         *  This is not allowed because the timers on this platform do not
   212         *  support one-shot mode and a stub is used to stop it.
   213         *  Another timer interrupt cannot go off when the ISR is running.
   214         */
   215        config Error.Id E_invalidHwiMask  =
   216            {msg: "E_InvalidMask: Mask in hwiParams cannot enable self"};
   217    
   218        /*!
   219         *  Error raised when period requested is not supported
   220         */
   221        config Error.Id E_cannotSupport  =
   222            {msg: "E_cannotSupport: Timer cannot support requested period %d"};
   223    
   224        /*!
   225         *  ======== anyMask ========
   226         *  Available mask to be used when select = Timer_ANY
   227         */
   228        config UInt anyMask;
   229    
   230        /*!
   231         *  ======== continueOnSuspend ========
   232         *  Continue counting during emulation halt. Default is false.
   233         *
   234         *  When false, timer stops counting during emulation halt. When true,
   235         *  timer continues to count during emulation halt.
   236         */
   237        config Bool continueOnSuspend = false;
   238    
   239        /*!
   240         *  ======== intFreqs ========
   241         *  Default internal timer input clock frequency array.
   242         *
   243         *  This array can be used to change the input clock frequency
   244         *  for a particular timer.
   245         *
   246         *  For example, if it is required to change the input clock frequency
   247         *  for timer id 1 to 200MHz on a device that has 2 timers, the
   248         *  intFreqs[1] config param can be set to {hi:0, lo:200000000} in the
   249         *  config script.
   250         *
   251         *  @p(code)
   252         *  var Timer = xdc.useModule('ti.sysbios.timers.rti.Timer');
   253         *  Timer.intFreqs[1].lo = 200000000; // = CPU freq
   254         *  Timer.intFreqs[1].hi = 0;
   255         *  @p
   256         */
   257        metaonly config Types.FreqHz intFreqs[];
   258    
   259        /*!
   260         *  ======== timerSettings ========
   261         *  Global Control configuration for each physical timer.
   262         */
   263        metaonly config TimerSetting timerSettings[] = [];
   264    
   265        /*!
   266         *  @_nodoc
   267         *  RTI timer registers.
   268         */
   269        struct DeviceRegs {
   270            UInt32 RTIGCTRL;        /*! 0x00h */
   271            UInt32 RTITBCTRL;       /*! 0x04h */
   272            UInt32 RTICAPCTRL;      /*! 0x08h */
   273            UInt32 RTICOMPCTRL;     /*! 0x0Ch */
   274            UInt32 RTIFRC0;         /*! 0x10h */
   275            UInt32 RTIUC0;          /*! 0x14h */
   276            UInt32 RTICPUC0;        /*! 0x18h */
   277            UInt32 RESERVED0;       /*! 0x1Ch */
   278            UInt32 RTICAFRC0;       /*! 0x20h */
   279            UInt32 RTICAUC0;        /*! 0x24h */
   280            UInt32 RESERVED1;       /*! 0x28h */
   281            UInt32 RESERVED2;       /*! 0x2Ch */
   282            UInt32 RTIFRC1;         /*! 0x30h */
   283            UInt32 RTIUC1;          /*! 0x34h */
   284            UInt32 RTICPUC1;        /*! 0x38h */
   285            UInt32 RESERVED3;       /*! 0x3Ch */
   286            UInt32 RTICAFRC1;       /*! 0x40h */
   287            UInt32 RTICAUC1;        /*! 0x44h */
   288            UInt32 RESERVED4;       /*! 0x48h */
   289            UInt32 RESERVED5;       /*! 0x4Ch */
   290            UInt32 RTICOMP0;        /*! 0x50h */
   291            UInt32 RTIUDCP0;        /*! 0x54h */
   292            UInt32 RTICOMP1;        /*! 0x58h */
   293            UInt32 RTIUDCP1;        /*! 0x5Ch */
   294            UInt32 RTICOMP2;        /*! 0x60h */
   295            UInt32 RTIUDCP2;        /*! 0x64h */
   296            UInt32 RTICOMP3;        /*! 0x68h */
   297            UInt32 RTIUDCP3;        /*! 0x6Ch */
   298            UInt32 RTITBLCOMP;      /*! 0x70h */
   299            UInt32 RTITBLHCOMP;     /*! 0x74h */
   300            UInt32 RESERVED6;       /*! 0x78h */
   301            UInt32 RESERVED7;       /*! 0x7Ch */
   302            UInt32 RTISETINTENA;    /*! 0x80h */
   303            UInt32 RTICLEARINTENA;  /*! 0x84h */
   304            UInt32 RTIINTFLAG;      /*! 0x88h */
   305            UInt32 RESERVED8;       /*! 0x8Ch */
   306            UInt32 RTIDWDCTRL;      /*! 0x90h */
   307            UInt32 RTIDWDPRLD;      /*! 0x94h */
   308            UInt32 RTIWDSTATUS;     /*! 0x98h */
   309            UInt32 RTIWDKEY;        /*! 0x9Ch */
   310            UInt32 RTIDWDCNTR;      /*! 0xA0h */
   311            UInt32 RTIWWDRXNCTRL;   /*! 0xA4h */
   312            UInt32 RTIWWDSIZECTRL;  /*! 0xA8h */
   313            UInt32 RTIINTCLRENABLE; /*! 0xACh */
   314            UInt32 RTICOMP0CLR;     /*! 0xB0h */
   315            UInt32 RTICOMP1CLR;     /*! 0xB4h */
   316            UInt32 RTICOMP2CLR;     /*! 0xB8h */
   317            UInt32 RTICOMP3CLR;     /*! 0xBCh */
   318        };
   319    
   320        /*!
   321         *  ======== oneShotStub ========
   322         *  @_nodoc
   323         *  RTI timer does not support one shot mode. This stub stops timer
   324         *  and disables its interrupt.
   325         *
   326         *  @param(arg)     Timer Handle.
   327         */
   328        Void oneShotStub(UArg arg);
   329    
   330        /*!
   331         *  ======== periodicStub ========
   332         *  @_nodoc
   333         *
   334         *  @param(arg)     Timer Handle.
   335         */
   336        Void periodicStub(UArg arg);
   337    
   338        /*!
   339         *  ======== getHandle ========
   340         *  @_nodoc
   341         *  Used by TimestampProvider module to get hold of timer handle used by
   342         *  Clock.
   343         *
   344         *  @param(id)      timer Id.
   345         */
   346        Handle getHandle(UInt id);
   347    
   348    instance:
   349    
   350        /*!
   351         *  ======== createHwi ========
   352         *  Controls whether the timer module creates a Hwi. Default is true.
   353         *
   354         *  If an application needs to create a Hwi for the timer, it is possible
   355         *  to indicate to the timer module to not create a Hwi by setting this
   356         *  param to false. This feature may be useful if the application needs to
   357         *  create a Hwi using the family specific Hwi module or on certain ARM
   358         *  targets create a Hwi of FIQ type to minimize latency.
   359         *
   360         *  If the application creates its own Hwi, it needs to select an interrupt
   361         *  number corresponding to the timer Id (see
   362         *  {@link ./doc-files/TimerTables.html Timer Mapping Tables}).
   363         *
   364         *  Here's an example for the Cortex-R4 target that creates a custom
   365         *  Hwi of FIQ type and sets "Timer.createHwi" param to false when
   366         *  creating a Timer object, in order to prevent the Timer module from
   367         *  creating a Hwi.
   368         *
   369         *  @p(code)
   370         *  *.cfg:
   371         *  xdc.useModule('ti.sysbios.timers.rti.Timer');
   372         *  xdc.useModule('ti.sysbios.family.arm.v7r.vim.Hwi');
   373         *
   374         *  *.c:
   375         *  #include <xdc/std.h>
   376         *  #include <xdc/runtime/Error.h>
   377         *
   378         *  #include <ti/sysbios/timers/rti/Timer.h>
   379         *  #include <ti/sysbios/family/arm/v7r/vim/Hwi.h>
   380         *  ...
   381         *
   382         *  Timer_Struct timer0;
   383         *  Timer_Handle handle0;
   384         *
   385         *  interrupt Void myIsr()
   386         *  {
   387         *      // Timer needs to be stopped only if run mode is One shot.
   388         *      // For periodic run mode, this function needs to only ack
   389         *      // the timer interrupt.
   390         *      Timer_stop(handle0);
   391         *      Timer_ackInterrupt(handle0);
   392         *      ...
   393         *  }
   394         *
   395         *  Int main(Int argc, char* argv[])
   396         *  {
   397         *      Timer_Params timerParams;
   398         *      Hwi_Params hwiParams;
   399         *      Error_Block eb;
   400         *
   401         *      Error_init(&eb);
   402         *
   403         *      // The interrupt number corresponding to a given Timer Id
   404         *      // can be determined from the Timer Mapping table. A link
   405         *      // to the table can be found in this document.
   406         *      Hwi_Params_init(&hwiParams);
   407         *      hwiParams.type = Hwi_Type_FIQ;
   408         *      Hwi_create(2, (Hwi_FuncPtr)(&myIsr), &hwiParams, &eb);
   409         *
   410         *      Timer_Params_init(&timerParams);
   411         *      timerParams.period = 60000;
   412         *      timerParams.runMode = Timer_RunMode_ONESHOT;
   413         *      timerParams.periodType = Timer_PeriodType_MICROSECS;
   414         *      timerParams.createHwi = FALSE;
   415         *      Timer_construct(&timer0, 0, NULL, &timerParams, &eb);
   416         *
   417         *      handle0 = Timer_handle(&timer0);
   418         *      ...
   419         *
   420         *      BIOS_start();
   421         *      return(0);
   422         *  }
   423         *  @p
   424         */
   425        config Bool createHwi = true;
   426    
   427        /*!
   428         *  ======== hwiParams ========
   429         *  Hwi Params for Hwi Object. Default is null.
   430         */
   431        config Hwi.Params *hwiParams = null;
   432    
   433        /*!
   434         *  ======== prescale ========
   435         *  Prescale factor. Default is 1 (0 is not recommended).
   436         *
   437         *  The Prescale factor can be used to achieve longer timer periods.
   438         *  With a prescale factor specified, the actual timer period is
   439         *  period * (prescale + 1).
   440         */
   441        config UInt8 prescale = 1;
   442    
   443        /*!
   444         *  ======== reconfig ========
   445         *  Used to modify static timer instances at runtime.
   446         *
   447         *  @param(timerParams)     timer Params
   448         *  @param(tickFxn)         functions that runs when timer expires.
   449         */
   450        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   451    
   452        /*!
   453         *  ======== ackInterrupt ========
   454         *  clear the current timer interrupt flag
   455         */
   456        Void ackInterrupt();
   457    
   458    internal:   /* not for client use */
   459    
   460        /*! Information about timer */
   461        struct TimerDevice {
   462            Int  intNum;
   463            Int  eventId;
   464            Ptr  baseAddr;
   465        };
   466    
   467        /*!
   468         *  ======== startupNeeded ========
   469         *  Flag used to prevent misc code from being brought in
   470         *  un-necessarily
   471         */
   472        config UInt startupNeeded = false;
   473    
   474        /*!
   475         *  ======== numTimerDevices ========
   476         *  The number of logical timers on a device.
   477         */
   478        config Int numTimerDevices;
   479    
   480        /*
   481         *  ======== initDevice ========
   482         *  reset timer to its resting state
   483         */
   484        Void initDevice(Object *timer);
   485    
   486        /*
   487         *  ======== postInit ========
   488         *  finish initializing static and dynamic Timers
   489         */
   490        Int postInit(Object *timer, Error.Block *eb);
   491    
   492        /*
   493         *  ======== checkOverflow ========
   494         */
   495        Bool checkOverflow(UInt32 a, UInt32 b);
   496    
   497        struct Instance_State {
   498            Bool                    staticInst;
   499            Int                     id;
   500            ITimer.RunMode          runMode;
   501            ITimer.StartMode        startMode;
   502            UInt                    prescale;
   503            UInt                    period;
   504            ITimer.PeriodType       periodType;
   505            UInt                    intNum;
   506            UArg                    arg;
   507            Hwi.FuncPtr             tickFxn;
   508            Types.FreqHz            extFreq;
   509            Hwi.Handle              hwi;
   510            Bool                    createHwi;
   511        }
   512    
   513        struct Module_State {
   514            UInt            availMask;      /* available peripherals */
   515            TimerDevice     device[];       /* timer device information */
   516            Types.FreqHz    intFreqs[];     /* internal frequency in Hz */
   517            Handle          handles[];      /* array of handles based on id */
   518        }
   519    }