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.

[FAQ] MCU-PLUS-SDK-AM263X: How to ensure the function access to certain critical variables are only restricted to certain functions ?

Part Number: MCU-PLUS-SDK-AM263X

For safety reasons, I want my system to be designed in this format -

Function Name
Permissions
Function A Read and Write
Function B Read Only
Function C / Rest of the SW No Access

This way it will allow the variable not to be modified by unexpected access.

  • This can be easily done with ARM MPU feature of the CPU by following the following steps

    • The region consisting of the variable is suppose to configured as "No Access" permission.

    • In the function A and B change the MPU region settings during the runtime and access the variables.
      • For Function A, provide R/W access.
      • For Function B, provide R access only.

    1 - Disable the MPUs, change the permissions and enable the MPUs.
    2 - Testing the RW Access based on the MPU permissions.
    3 - Disable the MPUs, change the permissions and enable the MPUs.

    Added the file for reference. This file can be used by using the following changes in the empty project. In the linker file, the variable is also required only to be address fixed as per MPU address in the above mentioned example (for demonstration).

    1541.hello_world_mpu_function_test.c
    /*
     *  Copyright (C) 2018-2021 Texas Instruments Incorporated
     *
     *  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.
     */
    
    
    #include <stdio.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    MpuP_RegionConfig temp_function = {
        .baseAddr = 0x70080000,
        .size = MpuP_RegionSize_1K,
        .attrs.isEnable = 1,
        .attrs.isCacheable = 1,
        .attrs.isBufferable = 0,
        .attrs.isSharable = 1,
        .attrs.isExecuteNever = 1,
        .attrs.tex = 0,
        .attrs.accessPerm = 0,
        .attrs.subregionDisableMask = 0
    };
    
    uint8_t variable_function[1024] __attribute__((section(".data.test_function"))) = {0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
    
    extern void MpuP_setRegionAsm(uint32_t regionId, uint32_t regionBaseAddr,
                  uint32_t sizeAndEnble, uint32_t regionAttrs);
    
    void MpuP_setRegionLocalFunction(uint32_t regionNum, void * addr, uint32_t size, MpuP_RegionAttrs *attrs)
    
    {
        uint32_t baseAddress, sizeAndEnable;
        uintptr_t key;
        uint32_t value = size;
    
        DebugP_assertNoLog( regionNum < 16U);
    
        /* size 5b field */
        value = (value & (uint32_t)0x1F);
    
        /* If N is the value in size field, the region size is 2N+1 bytes. */
        sizeAndEnable = ((uint32_t)(attrs->subregionDisableMask & (uint32_t)0xFF) << (uint32_t)8)
                      | ((uint32_t)(value            & (uint32_t)0x1F) << (uint32_t)1)
                      | ((uint32_t)(attrs->isEnable &  (uint32_t)0x1) << (uint32_t)0);
    
        /* align base address to region size */
        baseAddress = ((uint32_t)addr & ~( (1U <<((uint64_t)value+1U))-1U ));
    
        /* get region attribute mask */
        uint32_t regionAttrs =
              ((uint32_t)(attrs->isExecuteNever & (uint32_t)0x1) << (uint32_t)12)
            | ((uint32_t)(attrs->accessPerm     & (uint32_t)0x7) << (uint32_t)8)
            | ((uint32_t)(attrs->tex            & (uint32_t)0x7) << (uint32_t)3)
            | ((uint32_t)(attrs->isSharable     & (uint32_t)0x1) << (uint32_t)2)
            | ((uint32_t)(attrs->isCacheable    & (uint32_t)0x1) << (uint32_t)1)
            | ((uint32_t)(attrs->isBufferable   & (uint32_t)0x1) << (uint32_t)0);
    
        key = HwiP_disable();
    
        MpuP_setRegionAsm(regionNum, baseAddress, sizeAndEnable, regionAttrs);
    
        HwiP_restore(key);
    }
    
    void function_a(void)
    {
        /* Disable MPU */
        temp_function.attrs.isEnable = 0;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
        /* Change the Access Permission */
        temp_function.attrs.accessPerm = 3;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
        /* Enable MPU */
        temp_function.attrs.isEnable = 1;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        DebugP_log("Function A\r\n");
        /* Testing the Read Access */
        DebugP_log("Variable Function Data %x\r\n", variable_function[0]);
        /* Testing the Write Access */
        variable_function[0] = 0xFF;
        /* Testing the Read Access again to prevent optimization */
        DebugP_log("Variable Function Data %x\r\n", variable_function[0]);
    
        /* Disable MPU */
        temp_function.attrs.isEnable = 0;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        /* Revert the Access Permission */
        temp_function.attrs.accessPerm = 0;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        /* Enable MPU */
        temp_function.attrs.isEnable = 1;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    }
    
    void function_b(void)
    {
        /* Disable MPU */
        temp_function.attrs.isEnable = 0;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        /* Revert the Access Permission */
        temp_function.attrs.accessPerm = 6;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        /* Enable MPU */
        temp_function.attrs.isEnable = 1;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        DebugP_log("Function B\r\n");
        DebugP_log("Variable Function Data %x\r\n", variable_function[0]);
        /* Writing will lead to abort, so commented */
        //variable_function[0] = 0xAA;
    
        /* Disable MPU */
        temp_function.attrs.isEnable = 0;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        /* Revert the Access Permission */
        temp_function.attrs.accessPerm = 0;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    
        /* Enable MPU */
        temp_function.attrs.isEnable = 1;
        MpuP_setRegionLocalFunction(4, (void *)temp_function.baseAddr, temp_function.size, (MpuP_RegionAttrs *)&temp_function.attrs.isEnable);
    }
    
    void function_c(void)
    {
        DebugP_log("Function C\r\n");
        /* Reading will lead to abort, so commented */
        //DebugP_log("Variable Function Data %x\r\n", variable_function[0]);
        /* Writing will lead to abort, so commented */
        //variable_function[0] = 0xCC;
    }
    
    void hello_world_main(void *args)
    {
        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();
        //DebugP_log("Hello World!\r\n");
    
        /* A Function which can read and write the variable */
        function_a();
    
        /* A Function which can read the variable */
        function_b();
    
        /* A Function which cannot access the variable */
        function_c();
    
        Board_driversClose();
        Drivers_close();
    }
    
    

    This way, the system implementations are safer which will prevent accidental read/writes to this variables.

    Note : The safety metric for this implementation is not calculative and does not guarantee full system safety. Based on the above mentioned use-case this implementation allows selective functions to have higher privileges for a certain variables in comparison to rest of the functions in the system.