1    /* 
     2     * Copyright (c) 2011, 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.timers.timer64;
    39    
    40    import xdc.rov.ViewInfo;
    41    
    42    import xdc.runtime.Assert;
    43    import xdc.runtime.Error;
    44    import xdc.runtime.Types;
    45    import ti.sysbios.interfaces.ITimer;
    46    import ti.sysbios.hal.Hwi;
    47    
    48    /*!
    49     *  ======== Timer ========
    50     *  Timer Peripheral Manager.
    51     *
    52     *  This Timer module manages the timer64 peripheral available on many devices.
    53     *  It is supported on the ARM and c64x+ DSP targets. This module supports the
    54     *  timer in '32-bit chained' and '32-bit unchained' mode.  In the
    55     *  '32-bit unchained' mode, specify the lower or upper half to be use.
    56     *  The physical timer being used will be taken out of reset, only when
    57     *  its specified to be the master.
    58     *
    59     *  For shared timers (timers that are shared by all cores on a homogeneous
    60     *  multicore device like C6742), each core can create the timer but only
    61     *  one core will initialize the timer and take it out of reset.  The core
    62     *  that does the initialization is specified in the .cfg file.  Core 0
    63     *  is the default for all shared timers.
    64     *
    65     *  Note:  Creating a timer with 'Timer.ANY' specified as the id will not
    66     *         return a shared timer on a homogeneous multicore device.  To use
    67     *         a shared timer, specify the timer id explicitly when creating it.
    68     *         On these devices Timer.ANY specifies the local timer id.  This
    69     *         allows a single image to run on multiple cores since each core
    70     *         will program a different local timer.
    71     *
    72     *  The following sample .cfg code sets core 1 to initialize a shared timer
    73     *  with id 4.
    74     *
    75     *  @p(code)
    76     *  var Timer = xdc.useModule('ti.sysbios.timers.timer64.Timer');
    77     *  
    78     *  // sets core 1 to init and release Timer 4.
    79     *  Timer.timerSettings[4].ownerCoreId = 1;
    80     *  @p
    81     *
    82     *  The following sample .cfg code sets core 0 to initialize a shared timer
    83     *  with id 4.  It also configures the Clock module to use this timer.
    84     *  This allows multiple cores to share timer 4 for the Clock module's
    85     *  interrupt source.
    86     *
    87     *  @p(code)
    88     *  // sets core 0 to init and release Timer 4.
    89     *  var Timer = xdc.useModule('ti.sysbios.timers.timer64.Timer');
    90     *  Timer.timerSettings[4].ownerCoreId = 0;
    91     *
    92     *  var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    93     *  Clock.timerId = 4;
    94     *  @p
    95     *
    96     *  @p(html)
    97     *  <h3> Calling Context </h3>
    98     *  <table border="1" cellpadding="3">
    99     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   100     *    </colgroup>
   101     *
   102     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   103     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   104     *    <!--                                                                -->
   105     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td>
   106     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td>
   108     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #Params_init}             </td><td>   Y    </td>
   110     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   111     *    <tr><td> {@link #construct}               </td><td>   Y    </td>
   112     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   113     *    <tr><td> {@link #create}                  </td><td>   N    </td>
   114     *    <td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   115     *    <tr><td> {@link #delete}                  </td><td>   N    </td>
   116     *    <td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   117     *    <tr><td> {@link #destruct}                </td><td>   Y    </td>
   118     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   119     *    <tr><td> {@link #getCount}                </td><td>   Y    </td>
   120     *    <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   121     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td>
   122     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   123     *    <tr><td> {@link #getFunc}                 </td><td>   Y    </td>
   124     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   125     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td>
   126     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   127     *    <tr><td> {@link #reconfig}                </td><td>   Y    </td>
   128     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   129     *    <tr><td> {@link #setFunc}                 </td><td>   Y    </td>
   130     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   131     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td>
   132     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   133     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td>
   134     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   135     *    <tr><td> {@link #start}                   </td><td>   Y    </td>
   136     *    <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   137     *    <tr><td> {@link #stop}                    </td><td>   Y    </td>
   138     *    <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   139     *    <tr><td colspan="6"> Definitions: <br />
   140     *       <ul>
   141     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   142     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   143     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   144     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   145     *           <ul>
   146     *             <li> In your module startup after this module is started 
   147     *    (e.g. Timer_Module_startupDone() returns TRUE). </li>
   148     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   149     *             <li> During main().</li>
   150     *             <li> During BIOS.startupFxns.</li>
   151     *           </ul>
   152     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   153     *           <ul>
   154     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   155     *             <li> In your module startup before this module is started 
   156     *   (e.g. Timer_Module_startupDone() returns FALSE).</li>
   157     *           </ul>
   158     *       </ul>
   159     *    </td></tr>
   160     *
   161     *  </table>
   162     *  @p
   163     *
   164     *  @p(html)
   165     *  <h3> Timer Mapping Tables </h3>
   166     *  <p>
   167     *  The Timer module allows the user to use and configure the various timers
   168     *  that exist on a particular device.  This is achieved by specifying a timer
   169     *  ID when calling {@link ti.sysbios.hal.Timer#Timer_create}. 
   170     *  However, the timer ID
   171     *  specified may not always map to that timer; for example, specifying an ID
   172     *  value of 1 does not necessarily mean that this will map to "GPTimer1".
   173     *  These tables are provided to show which timers map to which timer IDs.
   174     *  </p>
   175     *  {@link ./doc-files/TimerTables.html Timer Mapping Tables}
   176     *  @p
   177     *
   178     */
   179    @InstanceFinalize       /* To cleanup */
   180    @InstanceInitError      /* To report unavailability of timer */
   181    @ModuleStartup                /* to configure static timers */
   182    
   183    module Timer inherits ti.sysbios.interfaces.ITimer
   184    {
   185        /*! In 32-bit modes, used to specify which half of Timer to use */
   186        enum Half {
   187            Half_LOWER,
   188            Half_UPPER,
   189            Half_DEFAULT
   190        };
   191    
   192        /*!
   193         *  The different modes of the Timer. These values match the TIMMODE
   194         *  bit fields of the Timer Global Control Register.
   195         */
   196        enum Mode {
   197            Mode_64BITGPTIMER = 0,
   198            Mode_UNCHAINED = 1,
   199            Mode_WATCHDOG = 2,
   200            Mode_CHAINED = 3
   201        };
   202    
   203        /*! Max value of Timer period for PeriodType_COUNTS*/
   204        const UInt MAX_PERIOD = 0xffffffff;
   205    
   206        /*! Timer Control Register struct. */
   207        struct Control {
   208            Bits8 tien;      /*! 0=Clock not gated by TINP; 1=Clock gated */
   209            Bits8 invout;    /*! 0=Uninverted TSTAT drives TOUT; 1=Inverted TSTAT */
   210            Bits8 invin;     /*! 0=Uninverted TINP drives Timer; 1=Inverted TINP */
   211            UInt8 pwid;      /*! TSTATx goes inactive after pwid cycles (CP=0) */
   212            Bits8 cp;        /*! 0=pulse mode; 1=clock mode */
   213        };
   214    
   215        /*! Timer Emulation Management Register struct. */
   216        struct EmuMgt {
   217            Bool free;        /*! 0=suspend for emu halt; 1=don't suspend */
   218            Bool soft;        /*! 0=stop immediately; 1=stop when count==period */
   219        };
   220    
   221        /*! Timer GPIO interrupt control and enable Management Register struct. */
   222        struct GpioIntEn {
   223            Bits8 gpint12_eni;  /*! 0=source by timer; 1=input to source event */
   224            Bits8 gpint12_eno;  /*! 0=source by timer; 1=output to source event */
   225            Bits8 gpint12_invi; /*! 0=don't invert invput; 1=invert input */
   226            Bits8 gpint12_invo; /*! 0=don't invert output; 1=invert output */
   227            Bits8 gpint34_eni;  /*! 0=source by timer; 1=input to source event */
   228            Bits8 gpint34_eno;  /*! 0=source by timer; 1=output to source event */
   229            Bits8 gpint34_invi; /*! 0=don't invert invput; 1=invert input */
   230            Bits8 gpint34_invo; /*! 0=don't invert output; 1=invert output */
   231            Bits8 gpio_eni12;   /*! 0=TINP12 as timer input; 1=TINP12 as GPIO */
   232            Bits8 gpio_eno12;   /*! 0=TOUTP12 as timer output; 1=TOUTP12 as GPIO */
   233            Bits8 gpio_eni34;   /*! 0=TINP34 as timer input; 1=TINP34 as GPIO */
   234            Bits8 gpio_eno34;   /*! 0=TOUTP34 as timer output; 1=TOUTP12 as GPIO */
   235        };
   236    
   237        /*! Timer GPIO Data and Direction Management Register struct. */
   238        struct GpioDatDir {
   239            Bits8 gpio_dati12; /*! 0=TINP12 is input; 1=TINP12 is output */
   240            Bits8 gpio_dato12; /*! 0=TOUTP12 is input; 1=TOUTP12 is output */
   241            Bits8 gpio_dati34; /*! 0=TINP34 is input; 1=TINP34 is output */
   242            Bits8 gpio_dato34; /*! 0=TOUTP34 is input; 1=TOUTP34 is output */
   243            Bits8 gpio_diri12; /*! 0=input as GPIO input; 1=input as GPIO output */
   244            Bits8 gpio_diro12; /*! 0=output as GPIO input;1=output as GPIO output */
   245            Bits8 gpio_diri34; /*! 0=input as GPIO input; 1=input as GPIO output */
   246            Bits8 gpio_diro34; /*! 0=output as GPIO input;1=output as GPIO output */
   247        };
   248    
   249        /*! Timer Settings. */
   250        struct TimerSetting {
   251            Mode mode ;         /*! mode to put each Timer into */
   252            Bool master;        /*! for 'unchained' mode; 1=set mode and reset */
   253            UInt16 ownerCoreId; /*! the owner of a shared timer's core id */
   254        };
   255    
   256        /*! @_nodoc */
   257        @XmlDtd
   258        metaonly struct BasicView {
   259            Ptr         halTimerHandle;
   260            String      label;
   261            UInt        id;
   262            String      startMode;
   263            String      runMode;
   264            UInt        period;
   265            String      periodType;
   266            String      half;
   267            UInt        prescalar;
   268            UInt        intNum;
   269            String      tickFxn[];
   270            UArg        arg;
   271            String      extFreqLow;
   272            String      extFreqHigh;
   273            String      hwiHandle;
   274        };
   275    
   276    
   277        /*! @_nodoc */
   278        metaonly struct ModuleView {
   279            String      availMask;      /* avaliable 32-bit timer halves */
   280            String      intFrequency[];    /* internal frequency in Hz */
   281        }
   282    
   283        /*! @_nodoc */
   284        metaonly struct Device_View {
   285            UInt        id;
   286            Bool        inUse;
   287            UInt32      intFreq;
   288            UInt        intNum;
   289            UInt        eventId;
   290            String      baseAddress;
   291        };
   292    
   293        @Facet
   294        metaonly config ViewInfo.Instance rovViewInfo = 
   295            ViewInfo.create({
   296                viewMap: [
   297                [
   298                    'Basic',
   299                    {
   300                        type: ViewInfo.INSTANCE,
   301                        viewInitFxn: 'viewInitBasic',
   302                        structName: 'BasicView'
   303                    }
   304                ],
   305                [
   306                    'Module',
   307                    {
   308                        type: ViewInfo.MODULE,
   309                        viewInitFxn: 'viewInitModule',
   310                        structName: 'ModuleView'
   311                    }
   312                ],
   313                ]
   314            });
   315    
   316        /*!
   317         *  Assert raised when static created timer is not available
   318         */
   319        config xdc.runtime.Assert.Id A_notAvailable =
   320            {msg: "A_notAvailable: static created timer not available"};
   321        
   322        /*!
   323         *  Error raised when timer id specified is not supported.
   324         */
   325        config Error.Id E_invalidTimer = {
   326            msg: "E_invalidTimer: Invalid Timer Id %d"
   327        };
   328    
   329        /*!
   330         *  Error raised when timer requested is in use
   331         */
   332        config Error.Id E_notAvailable  = {
   333            msg: "E_notAvailable: Timer not available %d"
   334        };
   335    
   336        /*!
   337         *  Error raised when period requested is not supported
   338         */
   339        config Error.Id E_cannotSupport = {
   340            msg: "E_cannotSupport: Timer cannot support requested period %d"
   341        };
   342    
   343        /*!======== anyMask ========
   344         *  Available mask to be used when select = Timer_ANY. Set in xs file.
   345         */
   346        config Bits32 anyMask;
   347    
   348        /*! 
   349         *  ======== defaultHalf ========
   350         *        The default 32-bit half of the timer to be used.
   351         */
   352        config Half defaultHalf = Half_LOWER;
   353    
   354        /*! 
   355         *  ======== timerSettings ========
   356         *  Global Control configuration for each physical timer.
   357         *
   358         *  mode: Mode_UNCHAINED        32-bit unchained mode.
   359         *  master: TRUE                If TRUE, release Timer from reset.
   360         */
   361        config TimerSetting timerSettings[] = [];
   362    
   363        /*!
   364         *  ======== intFreq ========
   365         *  @_nodoc
   366         *  Internal frequency for Timer
   367         */
   368        metaonly config Types.FreqHz intFreq;
   369    
   370        /*!
   371         *  ======== intFreq ========
   372         *  Internal frequency for Timers
   373         */
   374        metaonly config Types.FreqHz intFreqs[];
   375    
   376    instance:
   377    
   378        /*! 
   379         *  ======== controlInit ========
   380         *  Control configuration. Default is all fields 0 or false except:
   381         *
   382         *      pwid: 1
   383         */
   384        config Control controlInit = {tien: 0, invout: 0, invin: 0,
   385                                      pwid: 1, cp: 0};
   386    
   387        /*! 
   388         *  ======== emuMgtInit ========
   389         *  Emulation Management configuration. Default is:
   390         *
   391         *      free: 0
   392         *      soft: 0
   393         */
   394        config EmuMgt emuMgtInit = {free: 0, soft: 0};
   395    
   396        /*! 
   397         *  ======== gpioIntEn ========
   398         *  General Purpose IO interrupt control and enable Management
   399         *  configuration. The default for all fields is 0.
   400         */
   401        config GpioIntEn gpioIntEn = {
   402            gpint12_eni: 0, gpint12_eno: 0, gpint12_invi: 0, gpint12_invo: 0,
   403            gpint34_eni: 0, gpint34_eno: 0, gpint34_invi: 0, gpint34_invo: 0,
   404            gpio_eni12:  0, gpio_eno12:  0, gpio_eni34:   0, gpio_eno34:   0};
   405        
   406        /*! 
   407         *  ======== gpioDatDir ========
   408         *  General Purpose IO data and direction Management configuration
   409         *  The default is all fields is 0.
   410         */
   411        config GpioDatDir gpioDatDir = {
   412            gpio_dati12: 0, gpio_dato12: 0, gpio_dati34: 0, gpio_dato34: 0,
   413            gpio_diri12: 0, gpio_diro12: 0, gpio_diri34: 0, gpio_diro34: 0};
   414    
   415        /*! 
   416         *  ======== half ========
   417         *  In 32-bit unchained mode, this field is used to specify which half
   418         *  of the timer to use.
   419         */
   420        config Half half = Half_DEFAULT;
   421    
   422        /*! Hwi Params for Hwi Object. Default is null. */
   423        config Hwi.Params *hwiParams = null;
   424    
   425        /*! Hwi interrupt number to be used by Timer. */
   426        config Int intNum = -1;
   427    
   428        /*! 
   429         *  ======== prescalar ========
   430         *  32-bit pre-scalar to TIM12 in '32-bit chained' mode. 
   431         *  The default is 0.
   432         */
   433        config UInt prescalar = 0;
   434    
   435        /*!
   436         *  ======== reconfig ========
   437         *  Used to modify static timer instances at runtime.
   438         *
   439         *  @param(timerParams)     timer Params
   440         *  @param(tickFxn)                functions that runs when timer expires
   441         */
   442        @DirectCall
   443        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   444    
   445    
   446    internal:   /* not for client use */
   447    
   448        /*! Device-specific Timer implementation. */
   449        proxy TimerSupportProxy inherits ti.sysbios.interfaces.ITimerSupport;
   450    
   451        /*!
   452         *  ======== staticAvailMask ========
   453         *  The number of statically available 32-bit timer halves
   454         *
   455         *  This is required for supporting timers that are local to a
   456         *  particular processor.  The module availMask keeps track of
   457         *  what timers are available at runtime.  The two mask are the
   458         *  same if there is no concept of local timers.
   459         */
   460        metaonly config Int staticAvailMask;
   461    
   462        /*!
   463         *  ======== startupNeeded ========
   464         *  This flag is use to prevent Timer_startup code (includes postInit(),
   465         *  deviceConfig(), initDevice() to be brought in un-necessarily.
   466         */
   467        config Bool startupNeeded = false;
   468        
   469        /*!
   470         *  ======== freqDivisor ========
   471         *  For some devices, the timer frequency is determined by the CPU
   472         *  frequency divided by a value.  This parameter captures that value
   473         *  and is used during runtime to re-calculate the timer frequency
   474         *  when the CPU frequency is changed and Timer_getFreq is called.
   475         *  For devices with a fix timer frequency, this value is 0.
   476         */
   477        config UInt freqDivisor = 0;
   478    
   479        /*! Information about timer */
   480        struct TimerDevice {
   481            UInt intNum;
   482            UInt eventId;
   483            Ptr  baseAddr;
   484        };
   485    
   486        /*!
   487         *  ======== numTimerDevices ========
   488         *  The number of logical timers on a device.
   489         */
   490        config Int numTimerDevices;
   491    
   492        /*!
   493         *  ======== numLocalTimers ========
   494         *  The number of physical local timers on a device.
   495         */
   496        config Int numLocalTimers = 0;
   497    
   498        /*!
   499         *  ======== spinLoop ========
   500         *  used by trigger function.
   501         */
   502        Void spinLoop(UInt count);
   503    
   504        /*! Instance state structure */
   505        struct Instance_State {
   506            Bool              staticInst;   /* statically created or not */
   507            Int               id;           /* logical timer id. */
   508            Half              half;         /* which half */
   509            UInt              tcrInit;      /* tcr  */
   510            UInt              emumgtInit;   /* emu mgt */
   511            UInt              gpioIntEn;    /* GPIO interrupt control */
   512            UInt              gpioDatDir;   /* GPIO data and direction */
   513            ITimer.RunMode    runMode;      /* timer mode */
   514            ITimer.StartMode  startMode;    /* timer mode */
   515            UInt              period;       /* period */
   516            ITimer.PeriodType periodType;   /* type (microsecs, inst) */
   517            UInt              prescalar;    /* pre-scalar for TIM12 */
   518            UInt              intNum;       /* intr num */
   519            UArg              arg;          /* isrFxn arg */
   520            Hwi.FuncPtr       tickFxn;      /* Timer fxn plugged into Hwi */
   521            Types.FreqHz      extFreq;      /* ext freq */
   522            Hwi.Handle        hwi;          /* hwi inst */
   523        }
   524    
   525        /*! Module state structure */
   526        struct Module_State {
   527            Bits32        availMask;    /* avaliable 32-bit timer halves */
   528            Types.FreqHz  intFreqs[];   /* internal frequency in Hz */
   529            TimerSetting  gctrl[];      /* global control information */
   530            TimerDevice   device[];     /* timer device information */
   531            Handle        handles[];    /* handles based on logical id */
   532        }
   533    }
   534    /*
   535     *  @(#) ti.sysbios.timers.timer64; 2, 0, 0, 0,306; 1-20-2011 12:29:09; /db/vtree/library/trees/avala/avala-o26x/src/ xlibrary
   536    
   537     */
   538