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.

Problems using MPC in DM648

Hi All-

In an effort to make our application more robust and stable, I have implemented exception handling in the DM648. However, I am having trouble with the memory protection aspect.

The DM648 data sheet says very little about it, and the C64+ MegaModule documention and DSP/BIOS documentation are very general, so I am not certain what to do. Here is what I found:

Simply adding "bios.MEM.USEMPC = true;" to my .tcf, without changing any of the permissions, causes an immediate exception (122--L1D_CMPA L1D CPU memory protection fault event).

Adding

 // Set code space to execute-only (user & supervisor)
 perm = MPC_MPPA_UX | MPC_MPPA_SX | MPC_MPPA_LOCAL;
 
 Status=MPC_setBufferPA((void *)0xE00000,0x8000,0,perm);

 // Set data spaces to data r/w only (user & supervisor)
 perm = MPC_MPPA_UR | MPC_MPPA_UW | MPC_MPPA_SR | MPC_MPPA_SW | MPC_MPPA_LOCAL;

Status=MPC_setBufferPA((Ptr)0xF00000,0x8000,0,perm);

To my code does not stop getting immediate exceptions, though the calls succeed (Status=0).

All attempts to set/read anything about L2 (e.g.,  Status=MPC_getPageSize((Ptr)0xA00000,0,&pageSize);) result in failures (Status=5).

Further, I cannot find any registers in the DM648 that get modified when I change the permissions for L1P and L1D. I am very confused about what is supposed to be happening--the DM648 data sheet only mentions memory protection in the context of the EDMA controller, but the DM648 "subsystem user's guide" (SPRUEU6) mentions:

"The DMC, PMC, and UMC memory controllers in the C64x+ Megamodule are equipped with a set of registers that specify the permissions for each memorypage: L1DMPPA[31:16] for L1D Region 1 , L1PMPPA[31:16] for L1P Region 1, and L2MPPA[31:0] for L2 Port 0. Registers L1DMPPA16, L1PMPPA16, and L2MPPA0 control the page at the smallest address in their respective memory map ranges; i.e. L1DMPPA16 controls the page at address 0x00F00000, L1DPMPPA16 controls the page at address 0x00E00000, and L2MPPA0 controls the page at address 0x00800000"

Where are these registers? Where are they documented? The C64+ Megamodule document (SPRU871) also had discussion of MPPA, MPFAR, etc., but says to refer to specific device data sheet for what is implemented on what regions of memory.

I am not trying to implement supervisor/user mode, I just want to better trap rogue code, by using the MPC functionality to, e.g., generate an exception if program fetch is done from a memory page that is strictly data. Please advise on how to accomplish this in the context of DSP/BIOS (I'm using version 5_41_02_14) on the DM648, or by brute force register setting. Also, side question, is there anything that can possibly be done w/r/t memory protection in the external SDRAM?

Thanks in advance,

Jim Gort

  • Jim,

    BIOS's MPC support for DM648 L2 is probably broken, but read on...

    James Gort said:

    Simply adding "bios.MEM.USEMPC = true;" to my .tcf, without changing any of the permissions, causes an immediate exception (122--L1D_CMPA L1D CPU memory protection fault event).

    In order to determine the cause of the exception, you can look in the MPFAR/MPFSR of the afffected controller.  L1D's are:
        0x0184ac00 - MPFAR - Fault Address Register
        0x0184ac04 - MPFSR - Fault Status Register
    The MPFAR would contain the faulting address, and the MPFSR would contain the lacking permission bits (i.e., 1-bits in the MPFSR are bits that were *not* set in the MPPA, and those bits would need to be set in the MPPA to prevent the exception).

    The NRP register is also an important piece of information regarding exceptions - it indicates or directly points to the area of code that caused the exception.  So, knowing the area of code, and knowing the specific address/fault type will help determine what's causing this.

    My initial impression is that this immediate exception has to do with a clash in cache configuration and RAM usage.  What are your cache settings for L1D?

    James Gort said:

    Further, I cannot find any registers in the DM648 that get modified when I change the permissions for L1P and L1D. I am very confused about what is supposed to be happening--the DM648 data sheet only mentions memory protection in the context of the EDMA controller, but the DM648 "subsystem user's guide" (SPRUEU6) mentions:

    From http://focus.ti.com/lit/ds/symlink/tms320dm648.pdf...

    MPPAs for L1D start at 0x0184ae00.  For the DM648 there is no region 0 hence L1DMPPA[15:0] are not implemented and the first page in L1D is covered by L1DMPPA[16], and since MPPA registers are 32-bits, address 0x0184ae40 corresponds to the MPPA for L1D address 0x00e00000.

    The same applies for L1P on DM648 - no region 0, MPPA16 covers the start addr of L1P 0x00f00000.  Here are the addresses for L1P MPC:
        0x0184a400 - MPFAR/MPFSR
        0x0184a600 - MPPAs
    so 0x00f00000's MPPA register is 0x0184a640.

    In BIOS 5 MPC support, DM648 is assumed to be the same as a TCI6482, and build mechanics cause the 6482 settings to be used for DM648.  This looks to be OK for L1D and L1P, but for DM648 L2 SRAM (at 0x00a00000) is not where it is for 6482 (at 0x00800000), so I suspect that MPC L2 handling is wrong/broken for DM648.  The MPC library would need to be rebuilt with the correct L2 SRAM configuration for the DM648.

    Users have been known to workaround incorrect MPC configuration by "faking it out", i.e., if you want a setting of the MPPA for address 0x00a00000 you would pass address 0x00100000 to the BIOS MPC functions (The DM648 has L2 port 0 as 0x00800000 and L2 port 1 as 0x00a00000, and BIOS 5 MPC believes all parts have L2 port 1 as 0x00100000).  By passing 0x00100000, L2MPPA[32] is programmed, which actually corresponds to 0x00a00000 on DM648.  The page size is another issue - it differs depending on the region size.  I believe for DM648 there is 512 KB starting at 0x00a00000, and 32 MPPA registers covers that range, so writing MPPA32 covers address range 0x00a00000 - 0x00a04000.  I may be a bit off in my translations/math here, but I wanted to give an quick "abstract" on the situation.

    James Gort said:

    Also, side question, is there anything that can possibly be done w/r/t memory protection in the external SDRAM?

    I'm not sure, newer parts are coming up with MPC for external memories, but certainly the BIOS MPC library can't handle it.

    Regards,

    - Rob

     

  • Hi Rob-

    Thank you so much for your prompt and detailed response. I just want to make sure I got the mapping correct to "fake" as a 6482. I want to set the MPPA's for the first 1/2 of L2 on the DM648, they are at locations 0x184A200 - 0x184A240 (16 of them), correct?

    These are the ones I see change when I change my base (from 0xA00000 to 0x800000 -- base of L2 RAM in 648 and base of L2 RAM in 6482) and size (from 256K in 648 to 1M in 6482--each are 1/2 the total).

    Thanks,

    Jim

  • James Gort said:

    Thank you so much for your prompt and detailed response. I just want to make sure I got the mapping correct to "fake" as a 6482. I want to set the MPPA's for the first 1/2 of L2 on the DM648, they are at locations 0x184A200 - 0x184A240 (16 of them), correct?

    Not quite - L2 is a strange beast in its variety of configuration across different parts.

    James Gort said:

    These are the ones I see change when I change my base (from 0xA00000 to 0x800000 -- base of L2 RAM in 648 and base of L2 RAM in 6482) and size (from 256K in 648 to 1M in 6482--each are 1/2 the total).

    Indeed, I would expect L2MPPA[15:0] to be set when you use 0x00800000 with a DM648, since 0x00800000 on DM648 is L2 P0 (port 0) and L2MPPA[31:0] correspond to its port 0.  However, on DM648 0x00a00000 is configured as L2 P1, and BIOS's MPC module uses 0x00100000 as L2 P1's base address.  It's definitely confusing since both configurations have 0x00800000 in L2.  So, to summarize a little:
        L2 is divided into two "ports", P0 & P1
        Each port has 32 MPPA registers spread out over its address range
        L2MPPA[31:0] apply to P0, L2MPPA[63:32] apply to P1
    DM648 has (I believe) L2 P1 at 0x00a00000, so in order to affect MPPAs for 0x00a00000 -> 0x00a40000 you would write L2MPPA[47:32].  So, in the "spoof" handling for DM6482, you would use address 0x00100000 since BIOS's MPC module believes that 0x00100000 corresponds to the base of L2 P1.  BIOS's MPC also believes that L2 P1's size is 64KB, so each MPPA (32 of them) covers 2 KB (16 KB on DM648).  If you say MPC_setBufferPA(0x00100000, 0x800) that should set L2MPPA[32] only, which corresponds to 0x00a00000 -> 0x00a04000 on DM648.

    Let us know if this works out for you.

    Regards,

    - Rob

  • Hi Rob-

    I'm still confused. I tried:

     Status=MPC_setBufferPA((Ptr)0x100000,0x6000,0,perm);
     Status=MPC_setBufferPA((Ptr)0x106000,0x2000,0,perm);

    and the same 16 (L2MPPA[15..0], per the 6482 data sheet--all I know is 0x184A200-0x184A240) get set as when I used:

     Status=MPC_setBufferPA((Ptr)0xA00000,0xC0000,0,perm);
     Status=MPC_setBufferPA((Ptr)0xAC0000,0x40000,0,perm);

    Further, I can't find any mention of L2MPPA[63..32] in the 6482 data sheet. It seems that maybe same set of 32 (L2MPPA[31..0]) control L2, regardless of which "port" they were programmed for?

    Jim

  • Also, I looked deeper into why I am getting memory fault exceptions when I enable the MPC.

    I am getting the exception when the BIOS initializes the CLK module--both the NRP from the NMI and the memory fault register agree--and I stepped through the code: the BIOS is trying to read from address 0x2AC0008 when it initizlizes the CLK module, and there is nothing there (on the DM648)! Is this because of some setting I have or don't have in  my .tcf, or is it a problem with the BIOS port for DM648? Guessing its the latter, as interestingly there *is* something there on the 6482 -- peripheral configuration stuff.

    Good news is the exception was found! Bad news is, I can't use exception handling on the DM648, unless there is a work-around, like faking my memory map or something. Please advise.

    Jim

  • James Gort said:

    I'm still confused. I tried:

     Status=MPC_setBufferPA((Ptr)0x100000,0x6000,0,perm);
     Status=MPC_setBufferPA((Ptr)0x106000,0x2000,0,perm);

    and the same 16 (L2MPPA[15..0], per the 6482 data sheet--all I know is 0x184A200-0x184A240) get set as when I used:

     Status=MPC_setBufferPA((Ptr)0xA00000,0xC0000,0,perm);
     Status=MPC_setBufferPA((Ptr)0xAC0000,0x40000,0,perm);

    Do you mean 0x00800000 instead of 0x00a00000?  I ask because I thought you had errors from calling MPC with the 0x00a00000 address?

    James Gort said:

    Further, I can't find any mention of L2MPPA[63..32] in the 6482 data sheet. It seems that maybe same set of 32 (L2MPPA[31..0]) control L2, regardless of which "port" they were programmed for?

    Yeah, I just read the same thing about the 6482 - only L2MPPA[31..0] are implemented.

    The general C64x+ Megamodule documentation states that each L2 port has 32 MPPA registers.  From http://focus.ti.com/lit/ug/spru871k/spru871k.pdf:

     

    L2 implements 64 memory protection pages, with 32 pages per memory port. L2MPPA0 through

    L2MPPA31 correspond to port 0 and L2MPPA32 through L2MPPA63 correspond to port 1.

    So, I'm not sure what's up with that.  I'm starting to believe that on DM648 the 0x00a00000 address block is on L2 P0, since that's the block with the L2 cache and the megamodule doc states that port 0 supports the cache interface.

    I'm fairly certain that with BIOS MPC for 6482, when you specify 0x00100000 it performs writes to the L2MPPA[63..32] range, and it's possible that doing so results in writes to the L2MPPA[31..0] range on a DM648 (shadowing).  Both parts have L2 ROM and it wouldn't surprise me if the ROMs have no MPPAs (unimplemented).

    So, if DM648 address 0x00a00000 is on L2 P0, then that corresponds to 0x00800000 on TCI6482, so perhaps you could play around with using 0x00800000 in the BIOS MPC functions.

    I'm starting to confuse myself with all this spoofing, so I'll stop here.

    Regards,

    - Rob

     

     

  • James Gort said:

    I am getting the exception when the BIOS initializes the CLK module--both the NRP from the NMI and the memory fault register agree--and I stepped through the code: the BIOS is trying to read from address 0x2AC0008 when it initizlizes the CLK module, and there is nothing there (on the DM648)! Is this because of some setting I have or don't have in  my .tcf, or is it a problem with the BIOS port for DM648? Guessing its the latter, as interestingly there *is* something there on the 6482 -- peripheral configuration stuff.

    Yeah, I think that much of the reason for BIOS treating the DM648 as a TCI6482 is because of the CLK architecture, so if what you say above is true then that assumption was not right.

    James Gort said:

    Good news is the exception was found! Bad news is, I can't use exception handling on the DM648, unless there is a work-around, like faking my memory map or something. Please advise.

    I'm going to alert BIOS folks to this new detail, and am hoping they will be able to respond to this point.  There may be a configuration setting you can use to prevent that bad access on DM648.

    Regards,

    - Rob

  • James,

    The address 0x2AC0008 is coming from the function CLK_enableTimer which power enables the timer for TCI6482 devices.  It looks like that isn't needed for your DM648 device.  What you can do to try to get around this problem is to define this exact function in a *.c file, make it an empty funciton and included as part of your project.  This should override the one defined in the BIOS library.

    Judah

  • Hi Judah-

    Thank you for your response. This indeed fixed the problem with exception from DM648 BIOS init. However, I am now chasing down another memory exception, much further down in the code, that hits when:

       m_hUart_OUT = GIO_create("/UART0",IOM_OUTPUT,NULL,&chanParams,&gioAttrs);

    is called. I'm not sure (yet) if this is due to BIOS issue, or and issue with our use of the call, or an issue with how I set up the MPPA's in the DM648. But, until I figure it out, don't want to close this thread.

    Jim

  • Hi Guys--

    OK, got to bottom of final issue. The UART driver that came with the DM648 EVM (pspdrivers....) was calling PAL_osSemCreate(NULL, ....). That is, with NULL as the char*  name for the semaphore. Inside PAL_osSemCreate, a string copy was being done.... Instead of casting to a null termimated string, the string was just NULL (interpreted as a pointer to address 0), and hence the MPC exception.

    MPC is cool. Thanks for your help on this Judah and Rob.

    Jim Gort