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.

Speeding up SYS/BIOS boot time

Other Parts Discussed in Thread: SYSBIOS

Good afternoon,

We have a sys/bios project running on a AM335x board.  The sys/bios version is 6.42.3.35 and the XDC tools version is 3.31.0.24_core.

Our boot loader sets up the memory interfaces and the CPU clock to 1GHz, loads the image into position and then launches it.  Between this point and our codes starting to run in main() takes about 24 seconds.

Is this delay typical and if not what can I try to improve it?

I have tried turning optimization on/off, changing BIOS.libType and playing with a few other bits but nothing I have done seems to make any difference to this delay,

Thank you

Sean

  • Sean,

    The boot time is much too long. One thought is to enable cache as early as possible. Are you using u-boot as your boot loader? If so, try a search with the following:

    site:ti.com am335x u-boot cache

    ~Ramsey

  • Hi Ramsey,

    Sorry it has taken me a while to get back with this.  We are using our own boot loader and at the moment we disable the cache and MMU before launching the main application and the main application then sets it up.

    I have tried leaving them enabled but then the SYS/BIOS application will not boot.  I spent a while playing around with this removing/adding the sys/bios modules and the parts where I enable them in the code but to no joy.

    How should I have SYS/BIOS setup to allow it to boot when the MMU and cache are already enabled?

    Many thanks

    Sean

  • Sean,

    I don't have any thoughts on that. I suggest you try to build and run a SYS/BIOS example and see how long it takes to boot. Look in the TI Resource Explorer, then select SYS/BIOS and your device. I would start with something simple, one of the generic examples.

    ~Ramsey

  • Hi Ramsey,

    That is where I stated from and it has always taken this long to boot.  If you have no thoughts on this are you able to direct someone from TI here who might?

    My bootloader is based on the StarterWare bootloader and calls CacheEnable in cache.c with CACHE_ALL and I use the following code to enable the MMU.

    void MmuConfigAndEnable(void)
    {
    
    #define START_ADDR_DDR                     (0x80000000)
    #define START_ADDR_DEV                     (0x44000000)
    #define START_ADDR_OCMC                    (0x40300000)
    #define START_ADDR_SRAM                    (0x402F0400)
    #define NUM_SECTIONS_DDR                   (512)
    #define NUM_SECTIONS_DEV                   (960)
    #define NUM_SECTIONS_OCMC                  (1)
    #define NUM_SECTIONS_SRAM                  (1)
    
    	/*
    	** Define DDR memory region of AM335x. DDR can be configured as Normal
    	** memory with R/W access in user/privileged modes. The cache attributes
    	** specified here are,
    	** Inner - Write through, No Write Allocate
    	** Outer - Write Back, Write Allocate
    	*/
    	REGION regionDdr = {
    						MMU_PGTYPE_SECTION, START_ADDR_DDR, NUM_SECTIONS_DDR,
    						MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
    														 MMU_CACHE_WB_WA),
    						MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
    						(unsigned int*)pageTable
    					   };
    	/*
    	** Define OCMC RAM region of AM335x. Same Attributes of DDR region given.
    	*/
    	REGION regionOcmc = {
    						 MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC,
    						 MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
    														  MMU_CACHE_WB_WA),
    						 MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
    						 (unsigned int*)pageTable
    						};
    	/*
    	** Define SRAM region of AM335x. Same Attributes of DDR region given.
    	*/
    	REGION regionSram = {
    						 MMU_PGTYPE_SECTION, START_ADDR_SRAM, NUM_SECTIONS_SRAM,
    						 MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
    														  MMU_CACHE_WB_WA),
    						 MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
    						 (unsigned int*)pageTable
    						};
    
    	/*
    	** Define Device Memory Region. The region between OCMC and DDR is
    	** configured as device memory, with R/W access in user/privileged modes.
    	** Also, the region is marked 'Execute Never'.
    	*/
    	REGION regionDev = {
    						MMU_PGTYPE_SECTION, START_ADDR_DEV, NUM_SECTIONS_DEV,
    						MMU_MEMTYPE_DEVICE_SHAREABLE,
    						MMU_REGION_NON_SECURE,
    						MMU_AP_PRV_RW_USR_RW  | MMU_SECTION_EXEC_NEVER,
    						(unsigned int*)pageTable
    					   };
    
    	/* Initialize the page table and MMU */
    	MMUInit((unsigned int*)pageTable);
    
    	/* Map the defined regions */
    	MMUMemRegionMap(&regionDdr);
    	MMUMemRegionMap(&regionOcmc);
    	MMUMemRegionMap(&regionSram);
    	MMUMemRegionMap(&regionDev);
    
    	/* Now Safe to enable MMU */
    	MMUEnable((unsigned int*)pageTable);
    }

    It would be good to get the thoughts of someone who understands how SYS/BIOS works as to whether I am doing anything here that might upset it while booting and where the cache and MMU should be enabled when booting SYS/BIOS.

    Kind regards

    Sean

  • Good morning,

    Is anybody able to offer any help or suggestions on how I can improve this?

    Or is anybody running a similar setup able to confirm what sort of boot times I should be seeing?

    Many thanks

  • Sean,

    Time 24 seconds is too large. I had a similar situation when I did bios heap large 10 MB or declared an array of similar size. These volumes of data need to tag = NOINIT in .cmd file.

    Many thanks

    Vladimir
  • I think, big time goes to initializing variables in the .bss section with zeroes at MMU and Cache off state.
  • Thank you Vladimir this does indeed seem to be the issue however my attempts to set it to NOINIT have failed.

    I did test with the heap at 32MB and then 256MB though to confirm whether this was the issues and the boot times were 17 seconds and 38.

    So now we know what the problem is can anybody from TI please help me particularly with the following?

    1. I am currently using the Starterware MMU and cache implementations because I couldn't get the SYS/BIOS ones to work, If I am able to get the SYS/BIOS ones to work will these be setup before this zeroing is happening and there for help with the issue?
    2. If not is there a way to get SYS/BIOS to run the starterware code to setup the cache and mmu before it runs the zeroing?
    3. Is there a way to stop .bss being initialized to 0?
    4. Finally is there a way to setup SYS/BIOS so that it will boot when the mmu and cache have already been setup in the bootloader?

    My functions from Starterware with a few modifications that sets up the MMU and Cache look like this:

    void MmuConfigAndEnable(void)
    {
    
    #define START_ADDR_DDR                     (0x80000000)
    #define START_ADDR_DEV                     (0x44000000)
    #define START_ADDR_OCMC                    (0x40300000)
    #define START_ADDR_SRAM                    (0x402F0400)
    #define NUM_SECTIONS_DDR                   (256)
    #define NUM_SECTIONS_DEV                   (960)
    #define NUM_SECTIONS_OCMC                  (1)
    #define NUM_SECTIONS_SRAM                  (1)
    
    	/*
    	** Define DDR memory region of AM335x. DDR can be configured as Normal
    	** memory with R/W access in user/privileged modes. The cache attributes
    	** specified here are,
    	** Inner - Write through, No Write Allocate
    	** Outer - Write Back, Write Allocate
    	*/
    	REGION regionDdr = {
    						MMU_PGTYPE_SECTION, START_ADDR_DDR, NUM_SECTIONS_DDR,
    						MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
    														 MMU_CACHE_WB_WA),
    						MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
    						(unsigned int*)pageTable
    					   };
    	/*
    	** Define OCMC RAM region of AM335x. Same Attributes of DDR region given.
    	*/
    	REGION regionOcmc = {
    						 MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC,
    						 MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
    														  MMU_CACHE_WB_WA),
    						 MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
    						 (unsigned int*)pageTable
    						};
    	/*
    	** Define SRAM region of AM335x. Same Attributes of DDR region given.
    	*/
    	REGION regionSram = {
    						 MMU_PGTYPE_SECTION, START_ADDR_SRAM, NUM_SECTIONS_SRAM,
    						 MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
    														  MMU_CACHE_WB_WA),
    						 MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
    						 (unsigned int*)pageTable
    						};
    
    	/*
    	** Define Device Memory Region. The region between OCMC and DDR is
    	** configured as device memory, with R/W access in user/privileged modes.
    	** Also, the region is marked 'Execute Never'.
    	*/
    	REGION regionDev = {
    						MMU_PGTYPE_SECTION, START_ADDR_DEV, NUM_SECTIONS_DEV,
    						MMU_MEMTYPE_STRONG_ORD_SHAREABLE,
    						MMU_REGION_NON_SECURE,
    						MMU_AP_PRV_RW_USR_RW  | MMU_SECTION_EXEC_NEVER,
    						(unsigned int*)pageTable
    					   };
    
    	/* Initialize the page table and MMU */
    	MMUInit((unsigned int*)pageTable);
    
    	/* Map the defined regions */
    	MMUMemRegionMap(&regionDdr);
    	MMUMemRegionMap(&regionOcmc);
    	MMUMemRegionMap(&regionSram);
    	MMUMemRegionMap(&regionDev);
    
    	/* Now Safe to enable MMU */
    	MMUEnable((unsigned int*)pageTable);
    }
    
    void CacheEnable(unsigned int enFlag)
    {
    //    if(enFlag & CACHE_ICACHE)
        { 
            CP15ICacheFlush();
            CP15ICacheEnable();
        }
    
    //    if(enFlag & CACHE_DCACHE)
        {   
            /* For Cortex A8, L2EN has to be enabled for L2 Cache */
            if(PRIMARY_PART_CORTEX_A8 == CP15MainIdPrimPartNumGet())
            {
                CP15AuxControlFeatureEnable(CORTEX_A8_L2EN);
            }
    
            CP15DCacheFlush();
            CP15DCacheEnable();
        }
    }
    

    The .cfg file currently have looks like this, allthough I have gone through many different versions trying to get it to work:

    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Error = xdc.useModule('xdc.runtime.Error');
    var Log = xdc.useModule('xdc.runtime.Log');
    var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
    var Main = xdc.useModule('xdc.runtime.Main');
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');
    
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var Memory = xdc.useModule('xdc.runtime.Memory');
    var ti_sysbios_family_arm_a8_intcps_Hwi = xdc.useModule('ti.sysbios.family.arm.a8.intcps.Hwi');
    var Idle = xdc.useModule('ti.sysbios.knl.Idle');
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    //var Cache = xdc.useModule('ti.sysbios.hal.Cache');
    //var ti_sysbios_family_arm_a8_Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    
    /*
     * Uncomment this line to globally disable Asserts.
     * All modules inherit the default from the 'Defaults' module.  You
     * can override these defaults on a per-module basis using Module.common$. 
     * Disabling Asserts will save code space and improve runtime performance.
    Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
     */
    
    /*
     * Uncomment this line to keep module names from being loaded on the target.
     * The module name strings are placed in the .const section. Setting this
     * parameter to false will save space in the .const section.  Error and
     * Assert messages will contain an "unknown module" prefix instead
     * of the actual module name.
    Defaults.common$.namedModule = false;
     */
    
    /*
     * Minimize exit handler array in System.  The System module includes
     * an array of functions that are registered with System_atexit() to be
     * called by System_exit().
     */
    System.maxAtexitHandlers = 4;       
    
    /* 
     * Uncomment this line to disable the Error print function.  
     * We lose error information when this is disabled since the errors are
     * not printed.  Disabling the raiseHook will save some code space if
     * your app is not using System_printf() since the Error_print() function
     * calls System_printf().
    Error.raiseHook = null;
     */
    
    /* 
     * Uncomment this line to keep Error, Assert, and Log strings from being
     * loaded on the target.  These strings are placed in the .const section.
     * Setting this parameter to false will save space in the .const section.
     * Error, Assert and Log message will print raw ids and args instead of
     * a formatted message.
    Text.isLoaded = false;
     */
    
    /*
     * Uncomment this line to disable the output of characters by SysMin
     * when the program exits.  SysMin writes characters to a circular buffer.
     * This buffer can be viewed using the SysMin Output view in ROV.
    SysMin.flushAtExit = false;
     */
    
    /*
     * The BIOS module will create the default heap for the system.
     * Specify the size of this default heap.
     */
    BIOS.heapSize = 32*1024*1024;	//128M
    
    /*
     * Build a custom SYS/BIOS library from sources.
     */
    BIOS.libType = BIOS.LibType_Custom;
    
    /* System stack size (used by sISRs and Swis) */
    Program.stack = 1048573;	//1M
    
    /* Circular buffer size for System_printf() */
    SysMin.bufSize = 0x200;
    
    /* 
     * Create and install logger for the whole system
     */
    var loggerBufParams = new LoggerBuf.Params();
    loggerBufParams.numEntries = 16;
    var logger0 = LoggerBuf.create(loggerBufParams);
    Defaults.common$.logger = logger0;
    Main.common$.diags_INFO = Diags.ALWAYS_ON;
    
    System.SupportProxy = SysMin;
    Defaults.common$.diags_ASSERT = Diags.ALWAYS_ON;
    Defaults.common$.diags_INTERNAL = Diags.ALWAYS_ON;
    
    /* 
     * Disable the mmu so we can set it up in c
     */
    var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
    Cache.enableCache = true;
    Mmu.enableMMU = true;
    
    // descriptor attribute structure 
    var attrs = { 
        type: Mmu.FirstLevelDesc_SECTION,  // SECTION descriptor 
        bufferable: true,                  // bufferable 
        cacheable: true,                   // cacheable 
    }; 
    
    // Set the descriptor for each entry in the address range 
    for (var i=0x80000000; i < 0x90000000; i = i + 0x00100000) { 
        // Each 'SECTION' descriptor entry spans a 1MB address range 
        Mmu.setFirstLevelDescMeta(i, i, attrs); 
    } 
    
    Mmu.setFirstLevelDescMeta(0x40300000, 0x40300000, attrs);
    Mmu.setFirstLevelDescMeta(0x402F0400, 0x402F0400, attrs);
    
    // Force peripheral section to be NON cacheable strongly-ordered memory
    var peripheralAttrs = {
        type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
        bufferable : false,                // bufferable
        cacheable  : false,                // cacheable
        shareable  : false,                // shareable
        noexecute  : true,                 // not executable
    };
    
    // Set the descriptor for each entry in the address range
    for (var i=0x44000000; i < 0x80000000; i = i + 0x00100000) {
        // Each 'SECTION' descriptor entry spans a 1MB address range
        Mmu.setFirstLevelDescMeta(i, i, peripheralAttrs);
    }
    
    
    Memory.defaultHeapSize = 10485760;
    Idle.idleFxns[0] = "&idle_function";
    
    BIOS.cpuFreq.lo = 1000000000;
    Task.idleTaskStackSize = 8388608;	//8M
    Task.defaultStackSize = 4096;
    BIOS.clockEnabled = false;
    BIOS.swiEnabled = false;
    //ti_sysbios_family_arm_a8_Cache.enableCache = true;
    
    Program.sectMap[".c_int00"] = new Program.SectionSpec(); 
    Program.sectMap[".c_int00"].loadAddress = 0x80000000; 
    Program.sectMap[".c_int00"].runAddress = 0x80000000;
    Mmu.defaultAttrs.type = Mmu.FirstLevelDesc_SECTION;
    

    I would really appreciate any further input on this.

    Thanks

    Sean

  • Hi Sean!

    Section .bss can not be done NOINIT.

    You will have to limit the heap size of the Bios and make threads(variables) require large heap dynamically created on the heap Heapmem. Create an alternative to this heap via Heapmem module Sysbios. Place this heap in the new section, for example .mysection, and make NOINIT section. When you create a new task in the task settings specify size of memory need and name of heap descriptor "Heapmem".

    Regards, Vladimir.

  • What are the purposes you need such a large size BIOS.heapSize and Task.idleTaskStackSize?
  • Thank you Vladimir,

    I have been trying to do this with mixed success.  The following reduces the heap size but I end up with a huge image file.

    var heapMemParams = new HeapMem.Params();
    heapMemParams.size = 48*1024*1024;
    heapMemParams.sectionName = ".noinit";
    Program.global.noinitHeap = HeapMem.create(heapMemParams);
    Memory.defaultHeapInstance = Program.global.noinitHeap;

    As does this version:

    var heapSection = new Program.SectionSpec();
    heapSection.loadSegment = "DDR3";
    heapSection.type = "NOINIT";
    heapSection.type = "NOLOAD";
    
    /* Create heap as global variable so it can be used in C code */
    var heapMemParams = new HeapMem.Params();
    heapMemParams.size = 128*1024*1024;
    heapMemParams.sectionName = ".heapSection";
    Program.global.noinitHeap = HeapMem.create(heapMemParams);
    Memory.defaultHeapInstance = Program.global.noinitHeap;

    So how do I get my heapSection to be kept out of the image file?

    With this I get a boot time of 20 seconds which still seems too long, is anybody from TI able to comment or advise at all on this??

    Sean

  • Hi Sean,
    I have created a section with some cfg tools. But I set NOINIT attribute in .cmd file. Here is my example:

    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var heapMem0Params = new HeapMem.Params();
    heapMem0Params.instance.name = "heapMem0";
    heapMem0Params.size = 33554432;
    heapMem0Params.sectionName = ".nocache";
    Program.global.heapMem0 = HeapMem.create(heapMem0Params);

    Here's my additional .cmd file:

    SECTIONS
    {
    	.init: { boot*(.text)} > 0x80000000 /* make sure we can boot!            */
    
        GROUP: load > 0x80000400
        {
            .text: { *(.text). += 0x010; } /* Hole at the beginning */
            .const:
            .vecs:
        } crc_table(flash_crc_tab, algorithm = TMS570_CRC64_ISO)
    
        .dmadata: { *(.dmadata)} > 0x82000000
        //.nocache: { *(.nocache)} > 0x83000000 type =  NOINIT
        GROUP: load > 0x83000000
        {
            .nocache: type =  NOINIT
            .far: type =  NOINIT
        }
    }

    Regards, Vladimir