This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Memory placement requirements for running SYS/BIOS out of external ram on xintf?

Other Parts Discussed in Thread: TMS320F28335, SYSBIOS

I am working on a project with the TMS320F28335 that has hit the limit of the on chip memory. As such I want to push, as much as possible, the memory we are using to the RAM chip we have connected via the XINTF bus. I am setting up the linker command file as such:

MEMORY
{
PAGE 0:    /* Program and Data Memory */
    /*TFI         : origin = 0x338000, length = 0x007F80*/ /* first sector on-chip FLASH */
    APP         : origin = 0x300000, length = 0x038000     /* other sectors on-chip FLASH */
    CSM_RSVD    : origin = 0x33FF80, length = 0x000076     /* Program with all 0x0000 when CSM is in use. */
    BEGIN       : origin = 0x33FFF6, length = 0x000002     /* Used for "boot to Flash" bootloader mode. */
    CSM_PWL     : origin = 0x33FFF8, length = 0x000008     /* CSM password locations in FLASH */
    OTP         : origin = 0x380400, length = 0x000400     /* on-chip OTP */
    ADC_CAL     : origin = 0x380080, length = 0x000009     /* ADC_cal function in Reserved memory */
   
    IQTABLES    : origin = 0x3FE000, length = 0x000b50     /* IQ Math Tables in Boot ROM */
    IQTABLES2   : origin = 0x3FEB50, length = 0x00008c     /* IQ Math Tables in Boot ROM */  
    FPUTABLES   : origin = 0x3FEBDC, length = 0x0006A0     /* FPU Tables in Boot ROM */
    ROM         : origin = 0x3FF27C, length = 0x000D44     /* Boot ROM */        
    RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */
    VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */

PAGE 1 :   /* Data Memory */
    /*-------------------------------------------------------------------------*/
    /* RAM Ranges                                                              */
    /*-------------------------------------------------------------------------*/

    /*
     * Zero wait state both program and data.
     * Ideal for placement of data structures and code that is time critical.
     */
    M01SARAM    : origin = 0x000000, length = 0x000800

    /*
     * Zero wait state for both program and data. This is also secure memory
     * for which the Flash API must run if the CSM is not unlocked.
     * Ideal for placement of data structures and code that is time critical.
     */
    L03SARAM    : origin = 0x008000, length = 0x004000

    /*
     * Zero wait state for data reads and writes.
     * One wait state for program reads and writes.
     * Ideal for placement of data structures.
     */
    L47SARAM    : origin = 0x00C000, length = 0x004000

    /*
     * External RAM chip.
     */
    XRAM        : origin = 0x100000, length = 0x080000

    ...............

}

SECTIONS
{
    /* Allocate program areas: */
    .cinit              : > APP         PAGE = 0 /* constants use to initialize global vars and const in ram */
    .pinit              : > APP         PAGE = 0 /* table of constructors to be call at startup              */
    .text               : > APP         PAGE = 0 /* executable code and constants                            */
    codestart           : > BEGIN       PAGE = 0
    csmpasswds          : > CSM_PWL     PAGE = 0
    csm_rsvd            : > CSM_RSVD    PAGE = 0
   
    /* Allocate uninitalized data sections: */
    .stack              : >  L03SARAM | L47SARAM   PAGE = 1
    .ebss               : >  XRAM       PAGE = 1
    .esysmem            : >  XRAM       PAGE = 1
    .sysmem             : >  XRAM       PAGE = 1
    .cio                : >  XRAM       PAGE = 1

    /* Initalized sections go in Flash */
    .econst             : >  APP        PAGE = 0 /* far constant variabls             */
    .switch             : >  APP        PAGE = 0 /* jump tables for switch structures */
    .args               : >  APP        PAGE = 0

    /* Allocate IQ math areas: */
    IQmath              : >  APP        PAGE = 0        /* Math Code */
    IQmathTables        : >  IQTABLES   PAGE = 0, TYPE = NOLOAD
    FPUmathTables       : >  FPUTABLES  PAGE = 0, TYPE = NOLOAD
   
    /* Allocate ADC_cal function (pre-programmed by factory into TI reserved memory) */
    .adc_cal            : load = ADC_CAL,   PAGE = 0, TYPE = NOLOAD

    ..............................

    XRamFile          : > XRAM         PAGE = 1

I am manually placing all task stacks in the .stack section as well as calling a routine that configures external memory in the via

Reset = xdc.useModule('xdc.runtime.Reset');
Reset.fxns[Reset.fxns.length++] = "&initExternMem";

When I run I get the following error:

"gged interrupt flagged: intr# 19
xdc.runtime.Error.raise: terminating execution
"

Is the problem that I am not running the initExternMem call early enough so that Bios can access its data structures or is the problem that certain parts of bios have to run from internal ram?

Please advise



  • Steve,

    Honestly, I'm not 100% sure, but I would guess the issue is related to BIOS not being able to access some of its variables.  I'm going to go ahead and move this over to the BIOS forum to see if they have any suggestions.  I'm still learning BIOS myself and I have limited experience with external memory on the Delfino devices.

    Regards,

    Trey

  • Thanks Trey. There wasn't a cut and dry category for this question. Hopefully someone over in the BIOS forum can help.

  • Anyone? Anyone? Bueller?

  • Hi Steve,

    Looking a your exception it seems that your interrupt function hasn't been "plugged" in yet. What exactly is your "initExernMem" doing? Does it use interrupts?

    This Wiki article explains the C28 startup sequence with SYS/BIOS.

    http://processors.wiki.ti.com/index.php/SYS/BIOS_for_the_28x

  • It initializes the XINTF interface for the external memory we are using. Since the the C initialization has not been run yet I access all the registers by pointer as opposed to the linker command file placed data structures and it most certainly does not use interrupts.

        ///////////////////////////////////////////////////////////////////////////
        // setup xternal ram interface
        ///////////////////////////////////////////////////////////////////////////

        volatile struct SYS_CTRL_REGS*  SysCtrlRegs;
        volatile struct GPIO_CTRL_REGS* GpioCtrlRegs;
        volatile struct XINTF_REGS*     XintfRegs;

        SysCtrlRegs  = (volatile struct SYS_CTRL_REGS*) 0x007010;
        GpioCtrlRegs = (volatile struct GPIO_CTRL_REGS*)0x006F80;
        XintfRegs    = (volatile struct XINTF_REGS*)    0x007070;

        EALLOW;
        // Make sure the XINTF clock is enabled
        SysCtrlRegs->PCLKCR3.bit.XINTFENCLK = 1;
        SysCtrlRegs->PCLKCR3.bit.GPIOINENCLK = 1;    // GPIO input clock

        // Configure the GPIO for XINTF with a 16-bit data bus
         GpioCtrlRegs->GPCMUX1.bit.GPIO64 = 3;  // XD15
         GpioCtrlRegs->GPCMUX1.bit.GPIO65 = 3;  // XD14
         GpioCtrlRegs->GPCMUX1.bit.GPIO66 = 3;  // XD13
         GpioCtrlRegs->GPCMUX1.bit.GPIO67 = 3;  // XD12
         GpioCtrlRegs->GPCMUX1.bit.GPIO68 = 3;  // XD11
         GpioCtrlRegs->GPCMUX1.bit.GPIO69 = 3;  // XD10
         GpioCtrlRegs->GPCMUX1.bit.GPIO70 = 3;  // XD19
         GpioCtrlRegs->GPCMUX1.bit.GPIO71 = 3;  // XD8
         GpioCtrlRegs->GPCMUX1.bit.GPIO72 = 3;  // XD7
         GpioCtrlRegs->GPCMUX1.bit.GPIO73 = 3;  // XD6
         GpioCtrlRegs->GPCMUX1.bit.GPIO74 = 3;  // XD5
         GpioCtrlRegs->GPCMUX1.bit.GPIO75 = 3;  // XD4
         GpioCtrlRegs->GPCMUX1.bit.GPIO76 = 3;  // XD3
         GpioCtrlRegs->GPCMUX1.bit.GPIO77 = 3;  // XD2
         GpioCtrlRegs->GPCMUX1.bit.GPIO78 = 3;  // XD1
         GpioCtrlRegs->GPCMUX1.bit.GPIO79 = 3;  // XD0

         GpioCtrlRegs->GPBMUX1.bit.GPIO40 = 3;  // XA0/XWE1n
         GpioCtrlRegs->GPBMUX1.bit.GPIO41 = 3;  // XA1
         GpioCtrlRegs->GPBMUX1.bit.GPIO42 = 3;  // XA2
         GpioCtrlRegs->GPBMUX1.bit.GPIO43 = 3;  // XA3
         GpioCtrlRegs->GPBMUX1.bit.GPIO44 = 3;  // XA4
         GpioCtrlRegs->GPBMUX1.bit.GPIO45 = 3;  // XA5
         GpioCtrlRegs->GPBMUX1.bit.GPIO46 = 3;  // XA6
         GpioCtrlRegs->GPBMUX1.bit.GPIO47 = 3;  // XA7
         GpioCtrlRegs->GPCMUX2.bit.GPIO80 = 3;  // XA8
         GpioCtrlRegs->GPCMUX2.bit.GPIO81 = 3;  // XA9
         GpioCtrlRegs->GPCMUX2.bit.GPIO82 = 3;  // XA10
         GpioCtrlRegs->GPCMUX2.bit.GPIO83 = 3;  // XA11
         GpioCtrlRegs->GPCMUX2.bit.GPIO84 = 3;  // XA12
         GpioCtrlRegs->GPCMUX2.bit.GPIO85 = 3;  // XA13
         GpioCtrlRegs->GPCMUX2.bit.GPIO86 = 3;  // XA14
         GpioCtrlRegs->GPCMUX2.bit.GPIO87 = 3;  // XA15
         GpioCtrlRegs->GPBMUX1.bit.GPIO39 = 3;  // XA16
         GpioCtrlRegs->GPAMUX2.bit.GPIO31 = 3;  // XA17
         GpioCtrlRegs->GPAMUX2.bit.GPIO30 = 3;  // XA18
         GpioCtrlRegs->GPAMUX2.bit.GPIO29 = 3;  // XA19
    //KCM     GpioCtrlRegs->GPBMUX1.bit.GPIO35 = 3;  // XRNW
         GpioCtrlRegs->GPBMUX1.bit.GPIO38 = 3;  // XWE0

    //KCM uncommented the next two lines
        //GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 3;  // XZCS0
         GpioCtrlRegs->GPBMUX1.bit.GPIO37 = 3;  // XZCS7
         GpioCtrlRegs->GPAMUX2.bit.GPIO28 = 3;  // XZCS6
        // All Zones---------------------------------
        // Timing for all zones based on XTIMCLK = SYSCLKOUT
        XintfRegs->XINTCNF2.bit.XTIMCLK = 0;
        //Buffer up to 3 writes
        XintfRegs->XINTCNF2.bit.WRBUFF = 3;
        //XCLKOUT is enabled
        XintfRegs->XINTCNF2.bit.CLKOFF = 0;
        //XCLKOUT = XTIMCLK
        XintfRegs->XINTCNF2.bit.CLKMODE = 0;

        // Zone 0------------------------------------
        // When using ready, ACTIVE must be 1 or greater
        // Lead must always be 1 or greater
        // Zone write timing
        XintfRegs->XTIMING6.bit.XWRLEAD = 1;
        XintfRegs->XTIMING6.bit.XWRACTIVE = 1; // Drives = 1
        XintfRegs->XTIMING6.bit.XWRTRAIL = 1;
        // Zone read timing
        XintfRegs->XTIMING6.bit.XRDLEAD = 1;
        XintfRegs->XTIMING6.bit.XRDACTIVE = 1; // Drives = 2
        XintfRegs->XTIMING6.bit.XRDTRAIL = 1;

        // don't double all Zone read/write lead/active/trail timing
        XintfRegs->XTIMING6.bit.X2TIMING = 0;

        // Zone will not sample XREADY signal
        XintfRegs->XTIMING6.bit.USEREADY = 0;
        XintfRegs->XTIMING6.bit.READYMODE = 0;

        // 1,1 = x16 data bus
        // 0,1 = x32 data bus
        // other values are reserved
        XintfRegs->XTIMING6.bit.XSIZE = 3;

        EDIS;

       //Force a pipeline flush to ensure that the write to
       //the last register configured occurs before returning.
       asm(" RPT #7 || NOP");

  • So XintfRegs    = (volatile struct XINTF_REGS*)    0x007070; should be

    XintfRegs    = (volatile struct XINTF_REGS*)    0x0B20;

    The incorrect address points to the external interrupt control registers and possibly be the cause of the unplugged interrupt problem. I will experiment and post results.

  • Problem not fixed. Still getting the error.

    gged interrupt flagged: intr# 19
    xdc.runtime.Error.raise: terminating execution.

  • Hi Steve,

    After the exception, can you use ROV to what's going on in the Hwi module? I don't think that there is a interrupt vector 19 on the C28.

    Are you using just this linker cmd file, or are you also including another one? Which version of SYS/BIOS and XDCtools are you using?

    This needs to be added to your linker file.

        PIEVECT     : origin = 0xD00,    length = 0x100

    Can you see in your .map file if there is some reserved allocation for the PIE vector table to prevent your application from writing over it...

    Something like this:  

             name            origin    length      used     unused   attr    fill

    ----------------------  --------  ---------  --------  --------  ----  --------

      PIEVECT               00000d00   00000100  00000000  00000100  RWIX

  • Tom. I have since got the project to work.

    The problem was:

    stack              : >  L03SARAM | L47SARAM   PAGE = 1

    this was where I was placing task stacks.

    I replace that with this:

        .taskStack          : >  L03SARAM | L47SARAM | M01SARAM PAGE = 1
        .stack              : >  L47SARAM | M01SARAM            PAGE = 1 /* the stack                   */

    and put task stacks in .taskStack and that seemed to fix the issue. I ma now running my entire project, except for some time critical code, from external ram. It would be nice if sys/bios provided better insight into what these kind of problems are when they arise. There are some things it does well reporting but not a lot.

  • Steve you are a savior I need the same thing same processor. I am guessing you got the easy part of modifying you gel file to load to external RAM

    any chance of you posting your linker command files? (-: we have 2meg external ram on XINTF

  • Let me be more clear I WANT to load and debug the whole SYSBIOS app in the external RAM

  • /* --COPYRIGHT--,BSD
     * Copyright (c) $(CPYYEAR), Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /*
     *  ======== TMS320F28335.cmd ========
     *  Define the memory block start/length for the F28335
     *
     *! Revision History
     *! ================
     *! 26-May-2011 jv  created to support c28 generic platform.
     */

    /*
     *  PAGE 0 will be used to organize program sections
     *  PAGE 1 will be used to organize data sections
     *
     *  Notes:
     *        Memory blocks on F28335 are uniform (ie same
     *        physical memory) in both PAGE 0 and PAGE 1.  
     *        That is the same memory region should not be
     *        defined for both PAGE 0 and PAGE 1.
     *        Doing so will result in corruption of program
     *        and/or data.
     *        
     *        L0/L1/L2 and L3 memory blocks are mirrored - that is
     *        they can be accessed in high memory or low memory.
     *        For simplicity only one instance is used in this
     *        linker file.
     */

    MEMORY
    {
    PAGE 0:    /* Program and Data Memory */
        /*TFI         : origin = 0x338000, length = 0x007F80*/ /* first sector on-chip FLASH */
        APP         : origin = 0x300000, length = 0x038000     /* other sectors on-chip FLASH */
        CSM_RSVD    : origin = 0x33FF80, length = 0x000076     /* Program with all 0x0000 when CSM is in use. */
        BEGIN       : origin = 0x33FFF6, length = 0x000002     /* Used for "boot to Flash" bootloader mode. */
        CSM_PWL     : origin = 0x33FFF8, length = 0x000008     /* CSM password locations in FLASH */
        OTP         : origin = 0x380400, length = 0x000400     /* on-chip OTP */
        ADC_CAL     : origin = 0x380080, length = 0x000009     /* ADC_cal function in Reserved memory */
       
        IQTABLES    : origin = 0x3FE000, length = 0x000b50     /* IQ Math Tables in Boot ROM */
        IQTABLES2   : origin = 0x3FEB50, length = 0x00008c     /* IQ Math Tables in Boot ROM */  
        FPUTABLES   : origin = 0x3FEBDC, length = 0x0006A0     /* FPU Tables in Boot ROM */
        ROM         : origin = 0x3FF27C, length = 0x000D44     /* Boot ROM */        
        RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */
        VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */

    PAGE 1 :   /* Data Memory */
        /*-------------------------------------------------------------------------*/
        /* RAM Ranges                                                              */
        /*-------------------------------------------------------------------------*/
        /*
         * Memory location for bootloader to pass info to the application and
         * vice versa.
         */
        REBOOT_FLAGS  : origin = 0x000000, length = 1

        /*
         * Zero wait state both program and data.
         * Ideal for placement of data structures and code that is time critical.
         */
        M01SARAM    : origin = 0x000001, length = 0x0007FF

        /*
         * Zero wait state for both program and data. This is also secure memory
         * for which the Flash API must run if the CSM is not unlocked.
         * Ideal for placement of data structures and code that is time critical.
         */
        L03SARAM    : origin = 0x008000, length = 0x004000

        /*
         * Zero wait state for data reads and writes.
         * One wait state for program reads and writes.
         * Ideal for placement of data structures.
         */
        L47SARAM    : origin = 0x00C000, length = 0x004000

        /*
         * External RAM chip.
         */
        XRAM        : origin = 0x100000, length = 0x080000

        /*-------------------------------------------------------------------------*/
        /*
         * This defines the memory ranges associated with the registers for the
         * memmory mapped periperhial control registers. Later data structures can
         * be foribly placed in the appropriate memmory ranged usings the sections
         * below.
         */
        /*-------------------------------------------------------------------------*/
        DEV_EMU     : origin = 0x000880, length = 0x000180     /* device emulation registers */
        FLASH_REGS  : origin = 0x000A80, length = 0x000060     /* FLASH registers */
        CSM         : origin = 0x000AE0, length = 0x000010     /* code security module registers */
        ADC_MIRROR  : origin = 0x000B00, length = 0x000010     /* ADC Results register mirror */
        XINTF       : origin = 0x000B20, length = 0x000020     /* external interface registers */
        CPU_TIMER0  : origin = 0x000C00, length = 0x000008     /* CPU Timer0 registers */
        CPU_TIMER1  : origin = 0x000C08, length = 0x000008     /* CPU Timer0 registers (CPU Timer1 & Timer2 reserved TI use)*/
        CPU_TIMER2  : origin = 0x000C10, length = 0x000008     /* CPU Timer0 registers (CPU Timer1 & Timer2 reserved TI use)*/
        PIE_CTRL    : origin = 0x000CE0, length = 0x000020     /* PIE control registers */
        DMA         : origin = 0x001000, length = 0x000200     /* DMA registers */
        MCBSPA      : origin = 0x005000, length = 0x000040     /* McBSP-A registers */
        MCBSPB      : origin = 0x005040, length = 0x000040     /* McBSP-B registers */
        ECANA       : origin = 0x006000, length = 0x000040     /* eCAN-A control and status registers */
        ECANA_LAM   : origin = 0x006040, length = 0x000040     /* eCAN-A local acceptance masks */
        ECANA_MOTS  : origin = 0x006080, length = 0x000040     /* eCAN-A message object time stamps */
        ECANA_MOTO  : origin = 0x0060C0, length = 0x000040     /* eCAN-A object time-out registers */
        ECANA_MBOX  : origin = 0x006100, length = 0x000100     /* eCAN-A mailboxes */
        ECANB       : origin = 0x006200, length = 0x000040     /* eCAN-B control and status registers */
        ECANB_LAM   : origin = 0x006240, length = 0x000040     /* eCAN-B local acceptance masks */
        ECANB_MOTS  : origin = 0x006280, length = 0x000040     /* eCAN-B message object time stamps */
        ECANB_MOTO  : origin = 0x0062C0, length = 0x000040     /* eCAN-B object time-out registers */
        ECANB_MBOX  : origin = 0x006300, length = 0x000100     /* eCAN-B mailboxes */
        EPWM1       : origin = 0x006800, length = 0x000022     /* Enhanced PWM 1 registers */
        EPWM2       : origin = 0x006840, length = 0x000022     /* Enhanced PWM 2 registers */
        EPWM3       : origin = 0x006880, length = 0x000022     /* Enhanced PWM 3 registers */
        EPWM4       : origin = 0x0068C0, length = 0x000022     /* Enhanced PWM 4 registers */
        EPWM5       : origin = 0x006900, length = 0x000022     /* Enhanced PWM 5 registers */
        EPWM6       : origin = 0x006940, length = 0x000022     /* Enhanced PWM 6 registers */
        ECAP1       : origin = 0x006A00, length = 0x000020     /* Enhanced Capture 1 registers */
        ECAP2       : origin = 0x006A20, length = 0x000020     /* Enhanced Capture 2 registers */
        ECAP3       : origin = 0x006A40, length = 0x000020     /* Enhanced Capture 3 registers */
        ECAP4       : origin = 0x006A60, length = 0x000020     /* Enhanced Capture 4 registers */
        ECAP5       : origin = 0x006A80, length = 0x000020     /* Enhanced Capture 5 registers */
        ECAP6       : origin = 0x006AA0, length = 0x000020     /* Enhanced Capture 6 registers */
        EQEP1       : origin = 0x006B00, length = 0x000040     /* Enhanced QEP 1 registers */
        EQEP2       : origin = 0x006B40, length = 0x000040     /* Enhanced QEP 2 registers */
        GPIOCTRL    : origin = 0x006F80, length = 0x000040     /* GPIO control registers */
        GPIODAT     : origin = 0x006FC0, length = 0x000020     /* GPIO data registers */
        GPIOINT     : origin = 0x006FE0, length = 0x000020     /* GPIO interrupt/LPM registers */
        SYSTEM      : origin = 0x007010, length = 0x000020     /* System control registers */
        SPIA        : origin = 0x007040, length = 0x000010     /* SPI-A registers */
        SCIA        : origin = 0x007050, length = 0x000010     /* SCI-A registers */
        XINTRUPT    : origin = 0x007070, length = 0x000010     /* external interrupt registers */
        ADC         : origin = 0x007100, length = 0x000020     /* ADC registers */
        SCIB        : origin = 0x007750, length = 0x000010     /* SCI-B registers */
        SCIC        : origin = 0x007770, length = 0x000010     /* SCI-C registers */
        I2CA        : origin = 0x007900, length = 0x000040     /* I2C-A registers */
        CSM_PWL     : origin = 0x33FFF8, length = 0x000008     /* Part of FLASHA.  CSM password locations. */
        PARTID      : origin = 0x380090, length = 0x000001     /* Part ID register location */
    }

    /*
     *  Allocate sections to memory blocks.
     *  Note:
     *      codestart   user defined section in DSP28_CodeStartBranch.asm
     *                  used to redirect code execution when booting to flash
     */

    SECTIONS
    {
        /* places c_int00 at the start of flash. This is a workaround per E2E */
        boot : > 0x300000 PAGE = 0
        {
            -l"C:\ti\xdctools_3_22_04_46\packages\ti\targets\rts2800\lib\boot.a28FP" <boot_cg.o28FP> (.text)
        }
    }

    SECTIONS
    {
        REBOOT_FLAGS_FILE : > REBOOT_FLAGS REBOOT_FLAGS

        /* Allocate program areas: */
        .cinit              : > APP         PAGE = 0 /* constants use to initialize global vars and const in ram */
        .pinit              : > APP         PAGE = 0 /* table of constructors to be call at startup              */
        .text               : > APP         PAGE = 0 /* executable code and constants                            */
        codestart           : > BEGIN       PAGE = 0
        csmpasswds          : > CSM_PWL     PAGE = 0
        csm_rsvd            : > CSM_RSVD    PAGE = 0
       
        /* Allocate uninitalized data sections: */
        .taskStack          : >  L03SARAM | L47SARAM | M01SARAM PAGE = 1
        .stack              : >  L47SARAM | M01SARAM            PAGE = 1 /* the stack                   */
        .ebss               : >> /*L47SARAM | M01SARAM |*/ XRAM PAGE = 1 /* global and static variables */
        .esysmem            : >  L47SARAM | M01SARAM            PAGE = 1 /* far heap                    */
        .sysmem             : >  L47SARAM | M01SARAM            PAGE = 1 /* heap                        */
        .cio                : >  L47SARAM | M01SARAM            PAGE = 1 /* buffers for System_printf   */

        /* Initalized sections go in Flash */
        .econst             : >  APP        PAGE = 0 /* far constant variabls             */
        .switch             : >  APP        PAGE = 0 /* jump tables for switch structures */
        .args               : >  APP        PAGE = 0

        /* Allocate IQ math areas: */
        IQmath              : >  APP        PAGE = 0, TYPE = NOLOAD
        IQmathTables        : >  IQTABLES   PAGE = 0, TYPE = NOLOAD
        FPUmathTables       : >  FPUTABLES  PAGE = 0, TYPE = NOLOAD
       
        /* Allocate ADC_cal function (pre-programmed by factory into TI reserved memory) */
        .adc_cal            : load = ADC_CAL,   PAGE = 0, TYPE = NOLOAD

        /*** The PIE Vector table is called PIEVECT by DSP/BIOS ***/
        PieVectTableFile  : > PIEVECT,     PAGE = 1,  TYPE = DSECT

        /*-------------------------------------------------------------------------*/
        /*
         * Periperhial Sections
         * This creates sections where the software define data structures that
         * represent peripherial control registers can be placed. These data
         * structures are placed over the register structures using the
         * #pragma DATA_SECTION(item, "code section"); syntax.
         */
        /*-------------------------------------------------------------------------*/
        DevEmuRegsFile    : > DEV_EMU,     PAGE = 1
        FlashRegsFile     : > FLASH_REGS,  PAGE = 1
        CsmRegsFile       : > CSM,         PAGE = 1
        AdcMirrorFile     : > ADC_MIRROR,  PAGE = 1
        XintfRegsFile     : > XINTF,       PAGE = 1
        CpuTimer0RegsFile : > CPU_TIMER0,  PAGE = 1
        CpuTimer1RegsFile : > CPU_TIMER1,  PAGE = 1
        CpuTimer2RegsFile : > CPU_TIMER2,  PAGE = 1
        PieCtrlRegsFile   : > PIE_CTRL,    PAGE = 1
        DmaRegsFile       : > DMA,         PAGE = 1
        McbspaRegsFile    : > MCBSPA,      PAGE = 1
        McbspbRegsFile    : > MCBSPB,      PAGE = 1
        ECanaRegsFile     : > ECANA,       PAGE = 1
        ECanaLAMRegsFile  : > ECANA_LAM    PAGE = 1
        ECanaMboxesFile   : > ECANA_MBOX   PAGE = 1
        ECanaMOTSRegsFile : > ECANA_MOTS   PAGE = 1
        ECanaMOTORegsFile : > ECANA_MOTO   PAGE = 1
        ECanbRegsFile     : > ECANB,       PAGE = 1
        ECanbLAMRegsFile  : > ECANB_LAM    PAGE = 1
        ECanbMboxesFile   : > ECANB_MBOX   PAGE = 1
        ECanbMOTSRegsFile : > ECANB_MOTS   PAGE = 1
        ECanbMOTORegsFile : > ECANB_MOTO   PAGE = 1
        EPwm1RegsFile     : > EPWM1        PAGE = 1
        EPwm2RegsFile     : > EPWM2        PAGE = 1
        EPwm3RegsFile     : > EPWM3        PAGE = 1
        EPwm4RegsFile     : > EPWM4        PAGE = 1
        EPwm5RegsFile     : > EPWM5        PAGE = 1
        EPwm6RegsFile     : > EPWM6        PAGE = 1
        ECap1RegsFile     : > ECAP1        PAGE = 1
        ECap2RegsFile     : > ECAP2        PAGE = 1
        ECap3RegsFile     : > ECAP3        PAGE = 1
        ECap4RegsFile     : > ECAP4        PAGE = 1
        ECap5RegsFile     : > ECAP5        PAGE = 1
        ECap6RegsFile     : > ECAP6        PAGE = 1
        EQep1RegsFile     : > EQEP1        PAGE = 1
        EQep2RegsFile     : > EQEP2        PAGE = 1
        GpioCtrlRegsFile  : > GPIOCTRL     PAGE = 1
        GpioDataRegsFile  : > GPIODAT      PAGE = 1
        GpioIntRegsFile   : > GPIOINT      PAGE = 1
        SysCtrlRegsFile   : > SYSTEM,      PAGE = 1
        SpiaRegsFile      : > SPIA,        PAGE = 1
        SciaRegsFile      : > SCIA,        PAGE = 1
        XIntruptRegsFile  : > XINTRUPT,    PAGE = 1
        AdcRegsFile       : > ADC,         PAGE = 1
        ScibRegsFile      : > SCIB,        PAGE = 1
        ScicRegsFile      : > SCIC,        PAGE = 1
        I2caRegsFile      : > I2CA,        PAGE = 1
        CsmPwlFile        : > CSM_PWL,     PAGE = 1
        PartIdRegsFile    : > PARTID,      PAGE = 1
        XRamFile          : > XRAM,        PAGE = 1

        /*-------------------------------------------------------------------------*/
        /*
         * Sections for placing flash api code in memmory.
         */
        /*-------------------------------------------------------------------------*/
        FLASH_API:
        {
            /*
             * This says to take take both the code and constants from the TI
             * provided Flash28335...lib file and place in this section. Since
             * this section is placed in L03 the linker will allocate contingent
             * space in L03 for this code and constants. It is up to us to copy
             * this content from Flash to ram via.
             *
             * extern Uint16 FLASH_API_LOADSTART;
             * extern Uint16 FLASH_API_RUNSTART;
             * extern Uint16 FLASH_API_LOADSIZE;
             * copy api from flash to ram
             * memcpy((uint16_t*)&FLASH_API_RUNSTART,
             *        (uint16_t*)&FLASH_API_LOADSTART,
             *        (unsigned long)&FLASH_API_LOADSIZE);
             *
             */
            -lFlash28335_API_V210.lib(.econst)
            -lFlash28335_API_V210.lib(.text)
            -lFlash28335_API_V210.lib(.ebss)
        }
                              /*
                               * Store the code in flash.
                               */
                              LOAD = APP,      PAGE = 0

                              /*
                               * Allocate space for all data/code assigned to this section in
                               * L03 ram. We will have to copy from flash to this memory range
                               * in code.
                               */
                              RUN  = XRAM, PAGE = 1

                              /*
                               * create a variable FLASH_API_LOADSTART which sits
                               * at the start of the FLASH_API section in flash
                               */
                              LOAD_START(_FLASH_API_LOADSTART),

                              /*
                               * create a var FLASH_API_LOADSIZE which is the size
                               * of the FLASH_API section in flash
                               */
                              LOAD_SIZE(_FLASH_API_LOADSIZE),

                              /*
                               * create a var FLASH_API_RUNSTART which sits
                               * at the allocated location in ram for the FLASH_API code.
                               */
                              RUN_START(_FLASH_API_RUNSTART)


        /*-------------------------------------------------------------------------*/
        /*
         * Sections for placing code in memmory for speed reasons as code runs
         * faster out of ram then flash.
         */
        /*-------------------------------------------------------------------------*/
        FAST_VARS:
        {
            /*
             * You can allocate individual functions in the section with
             * #pragma CODE_SECTION(function, "FAST_CODE") or you can allocate whole
             * sections of files as such
             * -lFlash28335_API_V210.lib(.econst)
             * -lFlash28335_API_V210.lib(.text)
             * for libraries

             * or
             * bearing.obj(.econst)
             * bearing.obj(.text)
             * for compiled sources.
             *
             * At startup it is up to us to copy this content from Flash to ram via.
             * extern Uint16 FAST_CODE_LOADSTART;
             * extern Uint16 FAST_CODE_RUNSTART;
             * extern Uint16 FAST_CODE_LOADSIZE;
             * copy api from flash to ram
             * memcpy((uint16_t*)&FAST_CODE_RUNSTART,
             *        (uint16_t*)&FAST_CODE_LOADSTART,
             *        (unsigned long)&FAST_CODE_LOADSIZE);
             *
             * With the variables defined below.
             */
         }
         RUN  = L03SARAM , PAGE = 1

        /*-------------------------------------------------------------------------*/
        /*
         * Sections for placing code in memmory for speed reasons as code runs
         * faster out of ram then flash.
         */
        /*-------------------------------------------------------------------------*/
        FAST_CODE:
        {
            /*
             * You can allocate individual functions in the section with
             * #pragma CODE_SECTION(function, "FAST_CODE") or you can allocate whole
             * sections of files as such
             * -lFlash28335_API_V210.lib(.econst)
             * -lFlash28335_API_V210.lib(.text)
             * for libraries

             * or
             * bearing.obj(.econst)
             * bearing.obj(.text)
             * for compiled sources.
             *
             * At startup it is up to us to copy this content from Flash to ram via.
             * extern Uint16 FAST_CODE_LOADSTART;
             * extern Uint16 FAST_CODE_RUNSTART;
             * extern Uint16 FAST_CODE_LOADSIZE;
             * copy api from flash to ram
             * memcpy((uint16_t*)&FAST_CODE_RUNSTART,
             *        (uint16_t*)&FAST_CODE_LOADSTART,
             *        (unsigned long)&FAST_CODE_LOADSIZE);
             *
             * With the variables defined below.
             */

         }
                              /*
                               * Store the code in flash.
                               */
                              LOAD = APP,       PAGE = 0

                              /*
                               * Allocate space for all data/code assigned to this section in
                               * L03 ram or M01 ram. We will have to copy from flash to this
                               * memory range in code.
                               */
                              RUN  = L03SARAM, PAGE = 1

                              /*
                               * create a variable FAST_CODE_LOADSTART which sits
                               * at the start of the FAST_CODE section in flash
                               */
                              LOAD_START(_FAST_CODE_LOADSTART),

                              /*
                               * create a var FAST_CODE_LOADSIZE which is the size
                               * of the FAST_CODE section in flash
                               */
                              LOAD_SIZE(_FAST_CODE_LOADSIZE),

                              /*
                               * create a var FAST_CODE_RUNSTART which sits
                               * at the allocated location in ram for the FAST_CODE code.
                               */
                              RUN_START(_FAST_CODE_RUNSTART)
    }



  • We have not done anything with GEL (maybe I should learn how to use it). As far as loading BIOS variables external ram I guess the C initialization code does such for me.

  • For the record. All the code we use, except for some time critical stuff that we manually copy to ram, is run from flash. This include BIOS code.

    We have moved the .ebss section to external ram, this includes all the static and global vars for both our application and bios.

    The hitch we had was with the task stacks, which have to stay in internal ram.

  • Hi Steve this was helpful and I can use some of this(I already did (-:  ) I had 2 questions

    Steve we also run from flash but had a debug RAM version prior to adding SYSBIOS that ran from external RAM so we could debug faster

    1) How exactly did you force the task stacks into internal RAM? (this makes sense ) for us your posted linker command had a .taskStack section

    how did you get sysbios to put the task stack in that section or did you just let them default to .stack

    2) Is there a reason you needed the reset function to init the external RAM we are calling this from main but at the moment our app does not use the external memory

    I played with putting all the sysbios kernel api into internal RAM but the linker did not like the syntax I found

    http://processors.wiki.ti.com/index.php/SYS/BIOS_FAQs#3_Placing_SYS.2FBIOS_code_in_different_memory_segments

    Translate this page to cs - Česky de - Deutsch es - Español fi - Suomi fr - Français hu - Magyar it - Italiano ja - 日本語 ko - 한국어 pl - Polski pt - Português ru - Русский sv - Svenska vi - Tiếng Việt zh-CN - ‪中文(中国大陆)‬ Translate Show originalSYS/BIOS FAQs



     
    Contents [hide]
    1 1 Making a debug-able Custom SYS/BIOS Library
    2 2 Removing Asserts from the Custom SYS/BIOS Library
    3 3 Placing SYS/BIOS code in different memory segments
    4 4 Exception Dump Decoding Using the CCS Register View
    5 5 Using CCS and ROV to view a core dump file
    6 6 Overriding the default Timer frequency
    7 7 How to build SYS/BIOS apps on Linux using an external makefile
    8 8 Making an Error site’s file name available to an Error raise hook
    9 9 Relocating/Renaming the SYS/BIOS 'src' subdirectory for BIOS.LibType_Custom
    10 10 Example showing how to add Task hooks to the system
    11 11 Example showing how use custom output functions with SysMin
    12 12 Tricking the CCS M3 Debugger into Providing a Blocked Task's Call Stack
     

    --------------------------------------------------------------------------------

    1 Making a debug-able Custom SYS/BIOS Library
    By default, the following setting in your .cfg script:

    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    BIOS.libType = BIOS.LibType_Custom;... will generate a highly optimized, minimally debug-able custom SYS/BIOS library that your application will link with.

    The optimizations are achieved by including the "-o3" compiler option during the compilation phase. This aggressive optimization setting results in very efficient code at the expense of debug-ability.

    To create a custom library that is more debug-able, you can modify the optimization setting by adding the following line to your config script:

    BIOS.customCCOpts = BIOS.customCCOpts.replace("-o3", "-o0");This will change the optimization level from "-o3" to "-o0". (You can replace "-o0" with whatever setting you want).

    For ARM targets (ie 'M3', 'A8Fnv', 'Arm9'), you should also add the following line to your config script to remove the "--opt_for_speed=2" compiler option:

    BIOS.customCCOpts = BIOS.customCCOpts.replace("--opt_for_speed=2", "");Note: This modification will result in much slower SYS/BIOS performance as well as a larger code footprint.

    To view the set of compiler options used to create the custom SYS/BIOS library, add the following to your config script:

    print(BIOS.customCCOpts);Note: Whatever you do, DO NOT REMOVE the "--program_level_compile" compiler option from BIOS.customCCOpts.

    Note: The 'BIOS.libType' option was added in 6.32.01

    2 Removing Asserts from the Custom SYS/BIOS Library
    Runtime Assert checking is very useful during application development. However, there is a significant performance penalty associated with them. Once your application is up and running to your satisfaction, you can remove the runtime Assert checking code from the custom SYS/BIOS library by adding the following line to your config script:

    BIOS.assertsEnable = false;This configuration parameter only applies when you are using the custom SYS/BIOS build option:

    BIOS.libType = BIOS.LibType_Custom;Note: The 'BIOS.libType' option was added in SYS/BIOS 6.32.01

    3 Placing SYS/BIOS code in different memory segments
    Placing SYS/BIOS code in different memory regions can be done by adding a secondary .cmd file to your project. The linker can handle more than one .cmd file. Placing interrupt-related code and scheduler code in on-chip or L2 memory can help in systems with tight latency requirements since this code will always be "close" to the CPU and not out in slower off-chip memory. The cache will try to keep code in L1/L2, but forcing time critical code to L2 RAM will help. The L2 memory can be split between Cache and RAM and on some devices there is dedicated L2 that cannot be used for cache.

    SECTIONS
    {

       /* place all the knl APIs in IRAM */
       .knl: { *.*(.text:*ti_sysbios_knl*) } > IRAM
     
       /* place all the Hwi APIs in IROM */
       .hwi: { *.*(.text:*ti_sysbios*_Hwi_*) } > IROM
     
       /* place the remainder of the SYS/BIOS APIs in DDR */
       .sysbios: { *.*(.text:*ti_sysbios*) } > DDR
          
    }

  • Let me do one answer at a time>

    "1) How exactly did you force the task stacks into internal RAM? (this makes sense ) for us your posted linker command had a .taskStack section."

    By creating the taskStack section in the CMD file and adding this to the BIOS config. Under the options for tasks in the BIOS config there is a field "Default stack section" I put .taskStack there. Also there is a "Idle task stack section". You will need to do the same with it if you are using an idle task.

  • can you be more verbose and share the commands? It sounds like you added something to a .cfg file which one? and what did you add?

  • 2) Is there a reason you needed the reset function to init the external RAM we are calling this from main but at the moment our app does not use the external memory.

    Yes the having the reset function, which runs before the c-runtime initialization, was necessary because of the static/global variables placed in external ram with the linker command file. XRAM needed to be available to the c-runtime initialization so that the initializers for globals would occur.

    IE it is the c_int00 that gives the global x below it's value at init time.

    //

    int x = 0xFFFF;

  • Looking at the current state of our command file we are only putting .ebss and some large manually placed data structures in XRAM.

        .ebss               : >> /*L47SARAM | M01SARAM |*/ XRAM PAGE = 1 /* global and static variables

    Since we are doing, mostly, static BIOS setup, this puts all BIOS static variables in XRAM...

    Looking at subset of my map file confirms.....

    00112240   _xdc_runtime_Error_Module__state__V
    00112242   ___xdc__init__addr
    00112244   _xdc_runtime_Memory_Module__state__V
    00112246   _ti_sysbios_knl_Task_Instance_State_5_hookEnv__A
    00112248   _ti_sysbios_knl_Task_Instance_State_6_hookEnv__A
    0011224a   _ti_sysbios_knl_Task_Instance_State_0_hookEnv__A
    0011224c   _ti_sysbios_knl_Task_Instance_State_1_hookEnv__A
    0011224e   _ti_sysbios_knl_Task_Instance_State_4_hookEnv__A
    00112250   _ti_sysbios_knl_Task_Instance_State_2_hookEnv__A
    00112252   _ti_sysbios_knl_Task_Instance_State_3_hookEnv__A
    00112254   _ti_sysbios_gates_GateHwi_Object__table__V
    00112256   _xdc_runtime_LoggerBuf_Module__state__V
    0011225a   _ti_sysbios_gates_GateHwi_Module__root__V
    0011225e   _ti_sysbios_hal_Timer_Module__root__V
    00112262   _ti_sysbios_knl_Task_Module__root__V
    00112266   _xdc_runtime_Text_Module__state__V
    0011226a   _xdc_runtime_Registry_Module__state__V
    0011226e   _ti_sysbios_family_c28_Timer_Module__root__V
    00112272   _xdc_runtime_Startup_Module__state__V
    00112276   _ti_sysbios_family_c28_TimestampProvider_Module__state__V
    0011227a   _ti_sysbios_knl_Swi_Module__root__V
    00112280   _ti_sysbios_knl_Queue_Module__root__V
    00112284   _ti_sysbios_hal_Timer_Object__table__V
    00112288   _ti_sysbios_gates_GateMutex_Module__root__V
    0011228c   _xdc_runtime_System_Module__state__V
    00112290   _xdc_runtime_SysMin_Module__state__V
    00112294   _ti_sysbios_family_c28_Hwi_Module__root__V
    00112298   _ti_sysbios_knl_Semaphore_Module__root__V
    0011229c   _ti_sysbios_knl_Clock_Module__root__V
    001122a0   _ti_sysbios_heaps_HeapMem_Module__root__V
    001122a4   _ti_sysbios_hal_Hwi_Module__root__V
    001122a8   _xdc_runtime_LoggerBuf_Module__root__V
    001122ac   _ti_sysbios_family_c28_Timer_Module__state__V
    001122b4   _xdc_runtime_System_Module_State_0_atexitHandlers__A
    001122c0   _ti_sysbios_heaps_HeapMem_Object__table__V
    001122ca   _ti_sysbios_knl_Swi_Module__state__V
    001122d6   _ti_sysbios_family_c28_Hwi_Module__state__V
    001122e2   _ti_sysbios_BIOS_Module__state__V
    00112300   _ti_sysbios_knl_Clock_Module__state__V
    00112314   _ti_sysbios_knl_Swi_Object__table__V
    00112328   _ti_sysbios_knl_Task_Module__state__V
    00112340   _ti_sysbios_gates_GateMutex_Object__table__V
    00112380   _ti_sysbios_family_c28_Timer_Object__table__V
    001123c0   _ti_sysbios_knl_Swi_Module_State_0_readyQ__A
    00112400   _ti_sysbios_knl_Task_Module_State_0_readyQ__A
    00112440   _ti_sysbios_knl_Semaphore_Object__table__V
    001124c0   _ti_sysbios_utils_Load_Module__state__V
    00112540   _xdc_runtime_SysMin_Module_State_0_outbuf__A
    001125c0   _ti_sysbios_family_c28_Hwi_Object__table__V
    00112640   _ti_sysbios_knl_Task_Object__table__V
    00112700   _TSK_idle
    00112740   _ti_sysbios_family_c28_Hwi_Module_State_0_dispatchTable__A
    00112840   _ti_sysbios_heaps_HeapMem_Instance_State_0_buf__A

  • I tried to add a screenshot but it didn't take. The net effect in the .cfg file is....

    Task.defaultStackSection = ".taskStack";
    Task.idleTaskStackSection = ".taskStack";

  • In looking over my map file to answer your question I realized I had a large data structure, essentially constant, not marked as 'const'. As such it was going in external ram and an initializer in .cinit was created for it. Adding const got rid of the .cinit and put it in flash...... Helping you helped me.

  • Good deal. One last question (-:   Didn't you say the Task stack must be in internal RAM where does it say that and what happens when they are not? I am wondering what kind of nightmares to expect once our app grows huge again and what kinda fun to expect trying to get the debug from external RAM thing going again

    Its basically a trick where the gel file load the XINTF registers and then clever rework of the .cmd file routes all the code and data in INTERNAL/EXTERNAL RAM so SW breakpoints can be used. we use all the periphs and most with DMA which cuts the internal RAM in half so this sound like it could get ugly later juggling sections

  • "Good deal. One last question (-:   Didn't you say the Task stack must be in internal RAM where does it say that and what happens when they are not? I am wondering what kind of nightmares to expect once our app grows huge again and what kinda fun to expect trying to get the debug from external RAM thing going again"

    I had to find out the hard way that the stack pointer size prevents stacks from being located in the higher address external ram regions. I believe the stack pointer is 16 bits. Zone zero may work since it is well within the range of a 16 bit address. Zones 6, 7 certainly wont. Our external ram is on zone 6.

    "Its basically a trick where the gel file load the XINTF registers and then clever rework of the .cmd file routes all the code and data in INTERNAL/EXTERNAL RAM so SW breakpoints can be used. we use all the periphs and most with DMA which cuts the internal RAM in half so this sound like it could get ugly later juggling sections."

    Lucky you getting to use software breakpoints. The limitation of 2 hardware breakpoints, 1 if you use cio, is VERY annoying. Sooner or later I need to figure out how to do the DMA with SPI bus on the McBSP.

  • I have a TI pdF on using DMA on C28XX I was told was discontinued maybe I can share it with you to return the favor. we have this implemented BUT I am forseeing some issues on how to reuse these drivers in SYSBIOS maybe we can compare notes in the future let me know if you cant find the pdf I THINK I saw another engineer who may have the electronic version I could attach but thats probally another thread (-:

  • I will try to find the document. I don't have to implement DMA at this time but I suspect it will be an optimization I will need to make in the future. I will keep your offer in mind.

  • Is it http://www.ti.com/lit/ug/sprufb8d/sprufb8d.pdf ?

  • http://focus.ti.com/docs/training/catalog/events/event.jhtml?sku=OLT107001

    cheers