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.

66AK2H14: Managing Exceptions with Memory Protection ?

Part Number: 66AK2H14
Other Parts Discussed in Thread: SYSBIOS

Hi everyone,

I red in sprugw0c, DSP corePac documentation, that in case of invalid access an exception its send to CPU. Memory Protection Fault Registers are updated in order to recover information about the occured exception.

My question is does CPU is alerted of its invalid access and know that its access has not been done ?

Also can I manage exceptions ? (with module ti.sysbios.family.c64p.Exception??)

Best Regards,

François

  • Hi,

    Please check this Wiki: 

    Actions taken on access violation

    Hardware memory protection performs the following when an access violation is detected:

    • The access is denied (reads return garbage, writes are blocked)
    • Faulting address is captured in the MPFAR register
    • Type of faulting access is captured in the MPFSR register
    • Event is generated to alert the system on the violation

    Routing of events

    Each memory protection violation will result in a system event being asserted. Tables 7 and 8 show the events generated by various modules. To make sure the SW is notified when a violation is made, these events need to be routed to the DSP core as an interrupt or exception. Some of the events are directly routed to the interrupt controller of the CorePacs, while other events are routed via the system level interrupt controller INTC0. Consult the device datasheet for specific routing of the events.

    The DSP cores could of course poll the events instead of using interrupts/exceptions. However, due to the nature of memory protection, the DSP cores should get notified as soon as possible of memory protection violations, while the violations should not occur at all in normal SW operation. Therefore it is recommended to use interrupts or exceptions instead of polling.

    Interrupts vs. Exceptions

    The C66x DSP core supports interrupts as well as exceptions. The main conceptual difference between these is that interrupts are considered normal disruptions of the processing flow, while exceptions are considered serious error situations that are sometimes non-recoverable. In particular, the C66x DSP core begins the processing of exceptions as soon as it detects them, even if the pipeline of the DSP core is in a non-interruptible state. In such cases it is not safe to return back to the interrupted program flow. A comprehensive description of the C66x interrupts and exceptions is given in SPRUGH7.

    Any events that correspond to faulting accesses done by the DSP core should typically be considered as fatal and routed as exceptions. Events corresponding to faulting DMA accesses could be routed as interrupts or exceptions depending of the intended use of the data, but in most cases exceptions is the right choice. The only reason to use interrupts instead is if it is known that the fault can be somehow taken care of in SW, and it is desired to always return to the original program flow after the interrupt.

    Exception handler considerations

    When a memory protection violation results in an exception, the DSP core immediately saves the processor context and branches to the NMI vector for exception handling as described in SPRUGH7. The exception handler should find out which events caused the exception, and then read the associated memory protection fault registers to find out details of the fault. Note that due to the distributed memory protection architecture, it may be that a particular access causes memory protection events of several modules to be asserted, and thus also several fault registers may contain useful information of the fault. It can therefore be useful to dump and clear the fault registers of all modules (instead of only the one associated with the event that caused the exception) and save them to system logs for further analysis, along with register dumps, memory dumps, and other information that might be useful for post-mortem analysis.

    For exception, yes, you can use the  ti.sysbios.family.c64p.Exception

    Regards, Eric

  • Thank you so much Eric for the sum up,

    I think, I have now all information to use as well exceptions.

    Best Regards,

    François

  • In trying this code:

    /*
     * Author:  F. Poulain
     * Date:    04/07/2019
     *
     * Last Update: 08/07/2019
     *
     * The goal of this test is to test data protection between DSP cores.
     *
     * In this test DSP core0 is read/write accesses, DSP core1 is read only and DSP core2 doesn't have any accesses.
     *
     */
    
    #include <xdc/std.h>
    
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Log.h>
    
    #include <ti/sysbios/BIOS.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    
    #include <ti/sysbios/hal/Core.h>
    #include <ti/sysbios/family/c64p/Hwi.h>
    #include <ti/sysbios/family/c64p/MemoryProtect.h>
    #include <ti/sysbios/family/c64p/Exception.h>
    #include <ti/sysbios/family/c66/Cache.h>
    
    #include <c6x.h>
    #include <csl_xmc.h>
    #include <csl_xmcAux.h>
    
    #include <string.h>
    
    #include <func.h>
    #include <parameters.h>
    
    #define XMPAXL6     (0x08000030)
    #define XMPAXH6     (0x08000034)
    #define XMPAXL7     (0x08000038)
    #define XMPAXH7     (0x0800003C)
    
    /*
     *  ======== mem_protectFxn ========
     */
    Void mem_protectFxn(UArg a0, UArg a1)
    {
        Uint32 core_id = DNUM;
    
        Exception_evtExpMaskEnable(124);
    
    
        /*
         * XMPAXH |31---------BADDR---------12|11---Reserved---5|4--SEGZ--0|
         * XMPAXL |31---------------RADDR-----------------8|7---PERM------0|
         */
    
        Uint32 *xmpaxl=NULL;
        Uint32 *xmpaxh=NULL;
    
        /*********************************************
         *  DSP#0 (read/write allowed in 1st segment)
         *********************************************/
    
        if (DNUM==0)
        {
            /* DDR 1st segment */
            xmpaxl = (Uint32*) XMPAXL6;
            xmpaxh = (Uint32*) XMPAXH6;
    
            *xmpaxl = 0xB0000000 + 0xB6; // allows SR, SW, UR; UW
            *xmpaxh = 0xB0000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
    
            /* DDR 2nd segment */
            xmpaxl = (Uint32*) XMPAXL7;
            xmpaxh = (Uint32*) XMPAXH7;
    
            *xmpaxl = 0xB0100000 + 0x80; // no permissions
            *xmpaxh = 0xB1000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
        }
    
        /*********************************************
         *  DSP#1 (read/write allowed in 2nd segment)
         *********************************************/
    
        if (DNUM==1)
        {
            /* DDR 1st segment */
            xmpaxl = (Uint32*) XMPAXL6;
            xmpaxh = (Uint32*) XMPAXH6;
    
            *xmpaxl = 0xB0000000 + 0x80; // no permissions
            *xmpaxh = 0xB0000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
    
            /* DDR 2nd segment */
            xmpaxl = (Uint32*) XMPAXL7;
            xmpaxh = (Uint32*) XMPAXH7;
    
            *xmpaxl = 0xB0100000 + 0xB6; // allows SR, SW, UR; UW
            *xmpaxh = 0xB1000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
        }
    
    
        /*********************************************
         *              TEST PROTECTION
         *********************************************/
    
        if (DNUM==0)
        {
            memset((void*)0xB0000000, 0x10, 0x100);
        }
    
        if (DNUM==1)
        {
            memset((void*)0xB0000000, 0x11, 0x100);
        }
    
        System_flush(); /* force SysMin output to console */
    }
    
    /*
     *  ======== main ========
     */
    Int main()
    {
        System_printf("enter main()\n");
        BIOS_start();    /* does not return */
        return(0);
    }
    

    I do not understand why when core1 (in my example) made a violation, this violation has not been report.


    Could you help me to find my issue ?

    Regards,

    François

  • Hi,

    All your setting of MPAXL/H looked strange. The default MPAX set up on the system reset are as follows:

    000000BF 0000001E 800000BF 8000001E
    121010FF 2101000B 00C400FF 0C400014

    From MPAXL/H_1, the physical address 8:0000:0000 is mapped to logical address 8000:0000 with size 2GB (0x1E), the permission is SR/SW/SX and UR/UW/UX (0xBF). That is 8:0000:0000 - 8:7FFF:FFFF are mapped to 8000:0000 to FFFF:FFFF.

    Certainly you can have additional MPAX set up for the DDR region using higher MAPX pairs, it takes precedence over the lower MPAX pairs. If you want to do something for logical address B000:0000. The physical address would be typically 8:3000:0000 from DDR3A.

    So you would have MPAX6L=830000XX and MPAX6H=B00000YY for your trial, where XX is permission and YY is segment size. Then use MPAXL/H_7 for another region. Let me know is this works for you.

    Regards, Eric

  • Hi,

    Thanks for your remark, you're totally right. Even though my code's working, I do not really doing what I want, now with your suggestion, I'm in the right way. But as before the non allowed writes aren't made, but  I have no exceptions returned.

    I give you some other information in following posts:

    Best Regards,

    François

  • /*
     * Author:  F. Poulain
     * Date:    04/07/2019
     *
     * Last Update: 08/07/2019
     *
     * The goal of this test is to test data protection between DSP cores.
     *
     * In this test DSP core0 is read/write accesses, DSP core1 is read only and DSP core2 doesn't have any accesses.
     *
     */
    
    #include <xdc/std.h>
    
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Log.h>
    
    #include <ti/sysbios/BIOS.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    
    #include <ti/sysbios/hal/Core.h>
    #include <ti/sysbios/family/c64p/Hwi.h>
    #include <ti/sysbios/family/c64p/MemoryProtect.h>
    #include <ti/sysbios/family/c64p/Exception.h>
    #include <ti/sysbios/family/c66/Cache.h>
    
    #include <c6x.h>
    #include <csl_xmc.h>
    #include <csl_xmcAux.h>
    
    #include <string.h>
    
    #include <func.h>
    #include <parameters.h>
    
    #define XMPAXL6     (0x08000030)
    #define XMPAXH6     (0x08000034)
    #define XMPAXL7     (0x08000038)
    #define XMPAXH7     (0x0800003C)
    
    /*
     *  ======== context_displayFxn ========
     */
    
    Void context_displayFxn(UArg a0, UArg a1)
    {
        Context_info();
        System_flush(); /* force SysMin output to console */
    }
    
    /*
     *  ======== mem_protectFxn ========
     */
    Void mem_protectFxn(UArg a0, UArg a1)
    {
        Uint32 core_id = DNUM;
    
        Exception_evtExpMaskEnable(124);
    
        /*
         * XMPAXH |31---------BADDR---------12|11---Reserved---5|4--SEGZ--0|
         * XMPAXL |31---------------RADDR-----------------8|7---PERM------0|
         */
    
        Uint32 *xmpaxl=NULL;
        Uint32 *xmpaxh=NULL;
    
        /*********************************************
         *  DSP#0 (read/write allowed in 1st segment)
         *********************************************/
    
        if (DNUM==0)
        {
            /* DDR 1st segment */
            xmpaxl = (Uint32*) XMPAXL6;
            xmpaxh = (Uint32*) XMPAXH6;
    
            *xmpaxl = 0x83000000 + 0xB6; // allows SR, SW, UR; UW
            *xmpaxh = 0xB0000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
    
            /* DDR 2nd segment */
            xmpaxl = (Uint32*) XMPAXL7;
            xmpaxh = (Uint32*) XMPAXH7;
    
            *xmpaxl = 0x83100000 + 0x80; // no permissions
            *xmpaxh = 0xB1000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
        }
    
        /*********************************************
         *  DSP#1 (read/write allowed in 2nd segment)
         *********************************************/
    
        if (DNUM==1)
        {
            /* DDR 1st segment */
            xmpaxl = (Uint32*) XMPAXL6;
            xmpaxh = (Uint32*) XMPAXH6;
    
            *xmpaxl = 0x83000000 + 0x80; // no permissions
            *xmpaxh = 0xB0000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
    
            /* DDR 2nd segment */
            xmpaxl = (Uint32*) XMPAXL7;
            xmpaxh = (Uint32*) XMPAXH7;
    
            *xmpaxl = 0x83100000 + 0xB6; // allows SR, SW, UR; UW
            *xmpaxh = 0xB1000000 + 0x17; // segz = '10111' --> 0x17 --> 16MB
        }
    
    
        /*********************************************
         *              TEST PROTECTION
         *********************************************/
    
        if (DNUM==0)
        {
            memset((void*)0xB0000000, 0x10, 0x100);
            memset((void*)0xB1000000, 0x20, 0x100);
        }
    
        if (DNUM==1)
        {
            memset((void*)0xB0000000, 0x11, 0x100);
            memset((void*)0xB1000000, 0x21, 0x100);
        }
    
        System_flush(); /* force SysMin output to console */
    }
    
    /*
     *  ======== main ========
     */
    Int main()
    {
        System_printf("enter main()\n");
        BIOS_start();    /* does not return */
        return(0);
    }
    

  • #include <xdc/std.h>
    
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Log.h>
    
    #include <ti/sysbios/BIOS.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    
    #include <ti/sysbios/hal/Core.h>
    #include <ti/sysbios/family/c64p/MemoryProtect.h>
    #include <ti/sysbios/family/c64p/Exception.h>
    #include <ti/sysbios/family/c66/Cache.h>
    
    #include <c6x.h>
    #include <string.h>
    
    
    #include <func.h>
    #include <parameters.h>
    
    Void Context_info()
    {
        System_printf("SMP Environment: %d DSP core(s)\n", Core_numCores);
    }
    
    Void myExcep_handler(Void)
    {
        System_printf("Exception occurred\n");
    }
    
    Void myExcep_handler_extn(Void)
    {
        System_printf("External exception occurred\n");
    }
    
    Void myExcep_handler_intn(Void)
    {
        System_printf("Internal exception occurred\n");
    }
    
    Void myExcep_handler_nmi(Void)
    {
        System_printf("NMI exception occurred\n");
    }
    
    Void myISR(Void)
    {
        System_printf("Enter in ISR\n");
    }
    

  • My app.cfg contains:

    BIOS.mpeEnabled = true;
    
    /* Exception */
    Exception.enableExternalMPC = true;
    Exception.enablePrint = true;
    Exception.useInternalBuffer = false; 
    Exception.exceptionHook = "&myExcep_handler";
    Exception.externalHook = "&myExcep_handler_extn";
    Exception.internalHook = "&myExcep_handler_intn";
    Exception.nmiHook = "&myExcep_handler_nmi";
    Exception.returnHook = null; 
    
    /* Hw Interupt */
    Hwi.enableException = true;

    Do you need other thingd that will help you to help me ?

    Regards,

    François

  • Hi,

    I didn't find any recent code example for this. The wiki page  http://processors.wiki.ti.com/index.php/MemoryProtectionOnKeystoneDevices has a download for C6616. 

    However, the code used older CSL functions and I can't compile it now with CSL from Processor SDK RTOS, I missed a file called #include ti/csl/csl_memprot.h>. I found another package called K2_STK_DSP. It has the same CSL problem. So I am still looking for an existing MPU example.

    Regards, Eric  

  • Hi Eric,

    I finally found my issue, I miss some events to route as exception to DSP core. In my case, for DSP core 0 L2 protection against DSP core 1, I need to route event 119 through 127 and not only event 120, 122, 124, 126.



    Regards,

    François