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.

SYS/BIOS CACHE on AM3359

Other Parts Discussed in Thread: AM3359, OMAP-L138, SYSBIOS

Hi,

       We are converting our StarterWare program to run on SYS/BIOS 6.35.01.29. The issue we are running into is that USB0 clocks are hanging in a loop in usb.c-->USB0ModuleClkConfig(), line#88. It seems that both address used in this function 0x44E0001C and 0x44E0047C have some type of issue with caching. We placed the register define addresses in the platform as an I/O area(see pic below). The loop hangs because the 0x44E0001C ()usb0 clk) is a 0x00030002 when it should be a 0x00000002. It seem that the writes to these registers is getting cached even thought the platform defines it as an io.

     So how does SYS/BIOS on the AM3359 properly define access to hardware registers (in this case CHIP_REGS) and insure that the range is not cached?

Thanks,

     John C.

  • Hi John,

    Here is example of SYS/BIOS configuration to turn off cache for a given part of memory and access peripherals. This is example from OMAP-L138 processor but probably the same idea is for yours.

    //************ CACHE DEFINITION ************

    var Cache = xdc.useModule('ti.sysbios.family.arm.arm9.Cache');

    var Mmu = xdc.useModule('ti.sysbios.family.arm.arm9.Mmu');

    Cache.enableCache = true;
    Mmu.enableMMU = true;
    var peripheralAttrs = {
    type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
    bufferable : false, // bufferable
    cacheable : false, // cacheable
    };

    var peripheralBaseAddr = 0x01E00000; /* substitute the 1MB base address of your peripheral here */

    Mmu.setFirstLevelDescMeta(peripheralBaseAddr, peripheralBaseAddr, peripheralAttrs);
    peripheralBaseAddr = 0x01D00000;
    Mmu.setFirstLevelDescMeta(peripheralBaseAddr, peripheralBaseAddr, peripheralAttrs);

    // ************ END CACHE DEFINITIONS ************

  • Thanks Damian for the quick response,

         We found some similar code in one of the SYS/BIOS examples:

    SYS_MMU_ENTRY applMmuEntries[] = {

        {(void*)0x48300000,(void*)0x48300000,0,0},  //PWM - Non bufferable| Non Cacheable
        {(void*)0x48200000,(void*)0x48200000,0,0},  //INTCPS,MPUSS - Non bufferable| Non Cacheable
        {(void*)0x48100000,(void*)0x48100000,0,0},  //I2C2,McSPI1,UART3,UART4,UART5, GPIO2,GPIO3,MMC1 - Non bufferable| Non Cacheable
        {(void*)0x48000000,(void*)0x48000000,0,0},  //UART1,UART2,I2C1,McSPI0,McASP0 CFG,McASP1 CFG,DMTIMER,GPIO1 -Non bufferable| Non Cacheable
        {(void*)0x44E00000,(void*)0x44E00000,0,0},  //Clock Module, PRM, GPIO0, UART0, I2C0, - Non bufferable| Non Cacheable
        {(void*)0x4A300000,(void*)0x4A300000,0,0},  //PRUSS1 - Non bufferable| Non Cacheable
        {(void*)0x49000000,(void*)0x49000000,0,0},  //EDMA3 - Non bufferable| Non Cacheable
        {(void*)0x4A100000,(void*)0x4A100000,0,0},  //CPSW - Non bufferable| Non Cacheable
        {(void*)0xFFFFFFFF,(void*)0xFFFFFFFF,0xFF,0xFF}
    };

    Then call mmuInit(applMmuEntries);

         Is this telling me that every hardware register set that we use needs to be defined in this mmu table? In StarterWare the MMU setup was for the main memory sections, not the register sets (which are massive.) Is SYS/BIOS setting up the MMU to not allow anything that is not defined in it's table ?

    Thanks,

         John C.

       

  • Well I am not sure with this example but with our processor we have had a situation where in default configuration of SYS/BIOS after creating SYS/BIOS project there were some parts of memory cacheable and some weren't. Because we needed t use peripherals like UPP etc. we needed to turn off cache for this memory and you could only turn on/off a 1MB block o memory at once using this method showed in my previous post. In practice we turned off cache for all memory that accessing to didn't work and voila - it worked. Rest of the cache was left as default.

  • Hi John C.,

    Have you seen the API documentation on the ti.sysbios.family.arm.a8.Mmu module?  I found the following (BIOS configuration code) example there which may be helpful to you:

    The following example demonstrates how to add a peripheral's address to the MMU table so that it can be accessed by code at runtime:
    var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');

    // Enable the cache
    Cache.enableCache = true;

    // Enable the MMU (Required for L1/L2 data caching)
    Mmu.enableMMU = true;

    // Force peripheral section to be NON cacheable
    var peripheralAttrs = {
        type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
        bufferable : false, // bufferable
        cacheable : false, // cacheable
        shareable : false, // shareable
        noexecute : true, // not executable
    };

    // Define the base address of the 1 Meg page
    // the peripheral resides in.
    var peripheralBaseAddr = 0xa0400000;

    // Configure the corresponding MMU page descriptor accordingly
    Mmu.setFirstLevelDescMeta(peripheralBaseAddr, peripheralBaseAddr, peripheralAttrs);

    You can find the API documentation in your BIOS installation.  For example, it's here on my PC:

    C:\ti\CCS5.3.0.00090\bios_6_34_02_18\docs\Bios_APIs.html

    Then navigate to ti.sysbios.family.arm.a8.Mmu


    Steve

  • Hey Steve,

                     The caching is definitely different than in StarterWare. Below is a 16Mbyte section for the FPGA in StarterWare:

        REGION regionFPGA = {
                            MMU_PGTYPE_SECTION, START_ADDR_FPGA, NUM_SECTIONS_FPGA,
                            MMU_MEMTYPE_DEVICE_SHAREABLE,
                            MMU_REGION_NON_SECURE,
                            MMU_AP_PRV_RW_USR_RW  | MMU_SECTION_EXEC_NEVER,
                            (unsigned int*)pageTable
                           };

        MMUMemRegionMap(&regionFPGA);

         I would have thought in SYS/BIOS that defining the platform address as IO should have made them nocache. Is the only way to make our fpga address of 0x10000000 by making 16 non cacheable MMU settings?

    Thanks,

         John C.

  • John Conover said:
    Is the only way to make our fpga address of 0x10000000 by making 16 non cacheable MMU settings?

    Yes

    Steve

  • Hi John

    I was looking at all the posts u made, and am still in a confusion state for setting MMU & cache in my sysbios project.i am working with bios_6_34_02_18 , xdctools_3_24_05_48 , AM3359 and am porting starterware rasterdisplay to sysbios and after much conversation with TI guys, i got to know MMUConfigAndEnable() &   CacheEnable(CACHE_ALL) , these two function need not to be implemented in my code rather configure these in app.cfg.

    Here is the confusion start based on RTSC memory map settings and its configuration in app.cfg. Can i use only DDR2 for all Code, Data, Stack in my RTSC ? And if this is possible how to configure that in app.cfg?

    Can u show some light here ?..Thanks

      Regards

  • Hi Satyaprakash,

                          You can split where Code, Data and the Stack end up in memory by modifying(or you could import and make your own) the platform in the SYS/BIOS directory(C:\ti\am335x_sysbios_ind_sdk_1.0.0.5\sdk\platform\am335x.) If you look at my first post, what we did in ours is that we wanted the stack going to the end of the DDR memory as the stack in the AM3359 grows from high address to low address (grows downward.) We also wanted a spot in memory that was not Cached so we could receive data from our FPGA. You can make areas within the sections defined in the platform by going to the SYS/BIOS->System->Program - Memory Section Placement screen and adding section names there. I put a picture of the specific config screen of our buf1 setting where we have data placed in specific memory. You can also scientifically place a data structure in that memory section by using a C attribute:

    u8_t    raw_data[RAW_BUFFER_SIZE] __attribute__((aligned(16))) __attribute__((section (".rawData")));

         Hope this helps,

         John C.

  • Hi John

    Thanks for ur reply, it is helpful. Here am giving what i did following ur post and some demo sysbios application.

    1 .Included below libraries to Project_Properties-->Build--->ARMLinker--->File Search Path

    "C:\ti\am335x_sysbios_ind_sdk_1.0.0.7\sdk\os_drivers\lib\sys_bios_driver.lib"

    "C:\ti\am335x_sysbios_ind_sdk_1.0.0.7\sdk\platform\am335x\lib\am335x_platform.lib"

    "C:\ti\am335x_sysbios_ind_sdk_1.0.0.7\sdk\starterware\binary\armv7a\cgt_ccs\am335x\drivers\drivers.lib"

    "C:\ti\am335x_sysbios_ind_sdk_1.0.0.7\sdk\starterware\binary\armv7a\cgt_ccs\am335x\beaglebone\platform\platform.lib"

    2 .Modified RTSC configuration by splitting DDR0 into 3-section for code,data,stack. And though i dont need any NOCACHE buffer,FPGA so i left those. Here below am sharing my map file content.

    MEMORY CONFIGURATION

             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      SRAM_LO               402f0000   00000400  00000000  00000400  RW X
      SRAM_HI               402f0400   0000fbe0  00000000  0000fbe0  RW X
      OCMC_SRAM             40300000   00010000  00000000  00010000  RW X
      REGS                  44000000   0c000000  00000000  0c000000  RW  
      DDR0                  80000000   00400000  000505d5  003afa2b  RW X
      DDR0_DAT              80400000   07900000  00006ae4  078f951c  RW X
      DDR0_END              87d00000   08300000  00002000  082fe000  RW X

    I assume its all correct. But apart from that, i dont know how configure Cache/MMU for my application. I was looking at  Steven Connell's  1st reply , it is confusing me a little though am new to this. For my display application, i have to do DMA between Frame-buffer memory and internal registers of LCD controller.

    Here Frame-buffer is part of my main memory .

    Can u guide me here in configuring MMU ?

    Regards

  • Hi Satyaprakash,

            What we have found are that there are three different areas of concern with SYS/BIOS for memory. The first is the Platform which you have done. The second is the .cfg file which you adjust from Code Composer. The last part is dependent on which areas of memory your application code needs to change. Because when SYS/BIOS starts it protects a lot of the ARM register memory locations. So if your driver code needs access to them EDMA/UART/USB/etc, you need to set the MMU table up to allow that. Using our code as an example we set up an mmu table entry:

    SYS_MMU_ENTRY applMmuEntries[] = {

        {(void*)0x48300000,(void*)0x48300000,0,0},  //PWM - Non bufferable| Non Cacheable
        {(void*)0x48200000,(void*)0x48200000,0,0},  //INTCPS,MPUSS - Non bufferable| Non Cacheable
        {(void*)0x48100000,(void*)0x48100000,0,0},  //I2C2,McSPI1,UART3,UART4,UART5, GPIO2,GPIO3,MMC1 - Non bufferable| Non Cacheable
        {(void*)0x48000000,(void*)0x48000000,0,0},  //UART1,UART2,I2C1,McSPI0,McASP0 CFG,McASP1 CFG,DMTIMER,GPIO1 -Non bufferable| Non Cacheable
        {(void*)0x44E00000,(void*)0x44E00000,0,0},  //Clock Module, PRM, GPIO0, UART0, I2C0, - Non bufferable| Non Cacheable
        {(void*)0x4A300000,(void*)0x4A300000,0,0},  //PRUSS1 - Non bufferable| Non Cacheable
        {(void*)0x49000000,(void*)0x49000000,0,0},  //EDMA3 - Non bufferable| Non Cacheable
        {(void*)0x4A100000,(void*)0x4A100000,0,0},  //CPSW - Non bufferable| Non Cacheable
        {(void*)0x47400000,(void*)0x47400000,0,0},  // USBSS, USB0, USB0_PHY, USB1, USB1_PHY...
        {(void*)0x50000000,(void*)0x50000000,0,0},  //
        {(void*)0x10000000,(void*)0x10000000,0,0},  // FPGA
        {(void*)0x10100000,(void*)0x10100000,0,0},  // FPGA
        {(void*)0x10200000,(void*)0x10200000,0,0},  // FPGA
        {(void*)0x10300000,(void*)0x10300000,0,0},  // FPGA
        {(void*)START_ADDR_DDR_REGION2_NON_CACHED,   (void*)START_ADDR_DDR_REGION2_NON_CACHED,0,0},  // Buffer for raw data
        {(void*)0xFFFFFFFF,(void*)0xFFFFFFFF,0xFF,0xFF}
    };

         Then we call mmuInit(applMmuEntries), where mmuInit is located in the sys_mmu.c file of /os_drivers/src directory. This will allow your application code to work with the EDMA registers (which you need to setup for the frame buffer DMA.)

         With these three you should be able get your application code to manipulate a frame buffer and have the LCD DMA operate correctly. Also make sure you frame buffer is in NON-CACHE memory as when the CPU changes it, the DMA engine needs to see the changes. We did this by assigning the frame buffer to a NON-CACHED section of memory (.buf1) defined from the .cfg in Code Composer:

    // Memory that is used as the local frame buffer.
    unsigned char g_pucBuffer[GrOffScreen24BPPSize(480, 272, PIXEL_24_BPP_UNPACKED)] __attribute__((aligned(32768))) __attribute__((section (".buf1")));

         Hope this helps,

         John C.

  • Hi John

    Thanks to you for explaining all.

    Below MMU table entry am using now in my code and it works fine, with this MMU entry i resolved all exception & hung issues.

    SYS_MMU_ENTRY applMmuEntries[] = {

        {(void*)0x48300000,(void*)0x48300000,0,0},  //PWM - Non bufferable| Non Cacheable
        {(void*)0x48200000,(void*)0x48200000,0,0},  //INTCPS,MPUSS - Non bufferable| Non Cacheable
        {(void*)0x48100000,(void*)0x48100000,0,0},  //I2C2,McSPI1,UART3,UART4,UART5, GPIO2,GPIO3,MMC1 - Non bufferable| Non Cacheable
        {(void*)0x48000000,(void*)0x48000000,0,0},  //UART1,UART2,I2C1,McSPI0,McASP0 CFG,McASP1 CFG,DMTIMER,GPIO1 -Non bufferable| Non Cacheable
        {(void*)0x44E00000,(void*)0x44E00000,0,0},  //Clock Module, PRM, GPIO0, UART0, I2C0, - Non bufferable| Non Cacheable
        {(void*)0x4A300000,(void*)0x4A300000,0,0},  //PRUSS1 - Non bufferable| Non Cacheable
        {(void*)0x4830E000,(void*)0x4830E000,0,0},  //LcdDMA
        {(void*)0x4A100000,(void*)0x4A100000,0,0},  //CPSW - Non bufferable| Non Cacheable
        {(void*)0xFFFFFFFF,(void*)0xFFFFFFFF,0xFF,0xFF}

    };

    And regarding DMA, what i found display controller is having on-chip DMA engine. And it is given in AM3359-Tech_Ref_Manual. So i mapped respective registers in MMU table, that u can see above"LcdDMA". But as u mentioned, EDMA has to be mapped to MMU table,,so is that necessary in my case ??   

    And regarding NON-CACHED framebuffer memory, i got now, how to specify ".buf1" in .cfg and include that to MMU table. But here in my case am using double framebuffer (framebuffer0 & framebuffer1) and both are default cached i assume. Then is that i have to include in MMU table & specify the second buffer as ".buf2" like ".buf1" ??

    And  can u explain a little regarding the last section of ur previous post, where to add those lines and what it does.

    John Conover

    // Memory that is used as the local frame buffer.
    unsigned char g_pucBuffer[GrOffScreen24BPPSize(480, 272, PIXEL_24_BPP_UNPACKED)] __attribute__((aligned(32768))) __attribute__((section (".buf1")));

    Regards

    Satyaprakash

  • Hi Satyaprakash,

         Sorry to take so long to get back to you.

         If your DMA seems to be running then you might not need to. Because we do manipulate some DMA registers while we are running we do put it in.

         As far as including the .buf1 in the MMU table you do not. .buf1 is a "Section" of a memory "Segment". So a Section is part of a memory Segment. The caching property is part of the memory Segment assignment. So if you look at my first post you can see certain memory segments have io Access. The io means that the processor must not cache the data in these areas as it is considered a Input or Output(IO). In the SYS/BIOS .cfg (a couple posts up) you assign  the .buf1 Segment to the NOCACHE memory Segment and because it is in that memory, it will not be cached. You only need to include the second buffer in .buf1 segment as well:

    volatile unsigned char txData[NAND_DATA_BUFF_SIZE] __attribute__((section (".buf1")));
    volatile unsigned char rxData[NAND_DATA_BUFF_SIZE] __attribute__((section (".buf1")));

         The buffer assignment has two "attribute"s. The first is the aligned() which tells the linker that the beginning of the buffer needs to start at an address in memory that is a multiple of 32768 bytes. If you were to look at the address in hexidecimal format: 32768 = 0x00008000. So the linker would insure that the buffer begins at addresses like 0x00008000 or 0x0001000(65536). The attribute of section() tells the linker to place the buffer in the .buf1 Segment. So anything with a section(".buf1") attribute will be placed in the .bug1 Segment unless there is no room and in that case you will get a linker error.

         Hope this helps.

    John C.

  • Hi John

    Thanks again for all ur effort.

      Yes i understood what u said but one confusion in my mind, how CPU will know certain NOCACHED memory section user has created for Framebuffer0 & Framebuffer1 , at present am using both the Framebuffers based upon the FB register flags what i found from Technical_Ref_Manual.

        0x4830_E000 is starting & 0x4830_EFFF is end  address for LCD controller and to access Framebuffer, am using given flags. FB0 base =  44h / FB0 ceiling = 48h, FB1 base = 4Ch / FB1 ceiling = 50h.

    And as i mentioned in my previous post , i have included 0x4830_E000 into TLB table though SYSBIOS protects it.

    So please put some light here.

    Regards

    Satyaprakash