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.

TM4C123GH6PZ: FlashProtectSet() in the flash protected as Execute-only

Genius 5840 points
Part Number: TM4C123GH6PZ

Hello,

Can FlashProtectSet() in the flash region that is protected as Execute-only works fine?

After protecting the flash region A as Execute-only by setting FlashProtectSet(), I tried to execute FlashProtectSet() on the flash region A for next flash region B .

But then, fault ISR is called.

I configured linker command file and set --embedded_constants to off with reference to below thread, but the problem is remained.

If the answer for my question is no, are there any way to execute FlashProtectSet() on the execute-only flash region?

Regards,

U-SK

  • Hello U-SK,

    The answer to your question is described along with the API definitions:

    //! This function sets the protection for the specified block of flash.  Refer
    //! to the device data sheet to determine the granularity for each protection
    //! option.  Blocks that are read/write can be made read-only or execute-only.
    //! Blocks that are read-only can be made execute-only.  Blocks that are
    //! execute-only cannot have their protection modified.  Attempts to make the
    //! block protection less stringent (that is, read-only to read/write)
    //! result in a failure (and are prevented by the hardware).

    Once you have set it to execute-only, the protection cannot be modified and attempts to do so will generate a failure.

    It looks like the API doesn't check for it being execute-only for the execute-only setting, so I am guessing that instead of returning -1, it tries to modify the location and that triggers the FaultISR.

    Also note the last comment about the API:

    //! Changes to the flash protection are maintained only until the next reset.
    //! This protocol allows the application to be executed in the desired flash
    //! protection environment to check for inappropriate flash access (via the
    //! flash interrupt).  To make the flash protection permanent, use the
    //! FlashProtectSave() function.

  • Hi Ralph Jacobi,

    Thank you for your reply.

    Is my understanding that FlashProtectSet() can protect as execute-only at only 1 block(2kbyte) flash region and cannot protect any other flash blocks correct?

    Could you tell me how to protect multiple blocks of flash as execute-only?

    Regards,

    U-SK

  • Hello U-SK,

    You can protect multiple regions with it, you just should not try and hit the same region twice.

    Can you show the code that is used for trying to protect multiple regions so I can see what may be the error with your process?

  • Hi Ralph Jacobi,

    Thank you for your reply.

    Following is my application code.

    #define df_FLASH_MEMORY_BLOCK_SIZE	( 2048 )
    #define df_FLASH_EX_ADDRESS_TOP		0x00000800UL
    #define df_FLASH_EX_ADDRESS_END		0x00025FFFUL
    
    static void fn_FlashMemory_Protect_Set( void )
    {
    	uint32_t ul_target_addr = ULONG_INIT;
    
    	for ( ul_target_addr = df_FLASH_EX_ADDRESS_TOP; ul_target_addr < df_FLASH_EX_ADDRESS_END; ul_target_addr += df_FLASH_MEMORY_BLOCK_SIZE ) {
    		FlashProtectSet( ul_target_addr, FlashExecuteOnly );
    	}
    
    	FlashProtectSave();
    }
    

    My linker command file is following.

    /******************************************************************************
     *
     * timers_ccs.cmd - CCS linker configuration file for timers.
     *
     * Copyright (c) 2012-2017 Texas Instruments Incorporated.  All rights reserved.
     * Software License Agreement
     * 
     * Texas Instruments (TI) is supplying this software for use solely and
     * exclusively on TI's microcontroller products. The software is owned by
     * TI and/or its suppliers, and is protected under applicable copyright
     * laws. You may not combine this software with "viral" open-source
     * software in order to form a larger program.
     * 
     * THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
     * NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
     * NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
     * CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
     * DAMAGES, FOR ANY REASON WHATSOEVER.
     * 
     * This is part of revision 2.1.4.178 of the EK-TM4C123GXL Firmware Package.
     *
     *****************************************************************************/
    
    --retain=g_pfnVectors
    
    /* The following command line options are set as part of the CCS project.    */
    /* If you are building using the command line, or for some reason want to    */
    /* define them here, you can uncomment and modify these lines as needed.     */
    /* If you are using CCS for building, it is probably better to make any such */
    /* modifications in your CCS project and leave this file alone.              */
    /*                                                                           */
    /* --heap_size=0                                                             */
    /* --stack_size=256                                                          */
    /* --library=rtsv7M3_T_le_eabi.lib                                           */
    
    /* The starting address of the application.  Normally the interrupt vectors  */
    /* must be located at the beginning of the application.                      */
    #define APP_BASE 0x00000000
    #define RAM_BASE 0x20000000
    
    /* System memory map */
    
    MEMORY
    {
        /**********************************************************/
        /* Application stored in and executes from internal flash */
        /**********************************************************/
        /* [FLASH] Vector Table Area ( 2032[Byte] ) */
        FLASH_1 (RX) : origin = APP_BASE, length = 0x000007F0
    
        /* [FLASH] Software Version Area ( 16[Byte] ) */
        FLASH_VER (RX) : origin = 0x000007F0, length = 0x00000010
    
        /* [FLASH] Program Area ( 150[Byte] ) */
        FLASH_EX (X) : origin = 0x00000800, length = 0x0025800
    
        /* [FLASH] Data Area ( 104[Byte] ) */
        FLASH_2 (RX) : origin = 0x00026000, length = 0x001A000
    
        /**********************************************************/
        /* Application uses internal RAM for data                 */
        /**********************************************************/
        /* [SRAM] RAM Area */
        SRAM (RWX) : origin = 0x20000000, length = 0x00008000
    }
    
    /* Section allocation in memory */
    
    SECTIONS
    {
        .intvecs    :   > APP_BASE
        .softversion:   > FLASH_VER
        .text       :   > FLASH_EX
        .const      :   > FLASH_2
        .cinit      :   > FLASH_2
        .pinit      :   > FLASH_2
        .init_array : > FLASH_2
    
        .vtable     :   > RAM_BASE
        .data       :   > SRAM
        .bss        :   > SRAM
        .sysmem     :   > SRAM
        .stack      :   > SRAM
    }
    
    __STACK_TOP = __stack + 256;

    It was confirmed that the address specified by FlashProtectSet() was updated with the size of 2kB.

    So I don't think same flash region is modified twice.

    Could you tell me the reason why FaultISR is called?

    Regards,

    U-SK 

  • Hi,

    Do you have any updates?

    Regards,

    U-SK

  • Hello U-SK,

    I am not able to create a FaultISR with your code when running on a device which has not had any flash blocks protected before and a standard configuration for the command linker file.

    However, when I used your custom linker file, then I saw the Fault ISR occur. I have not had time to debug that further, but the issue is directly related to your customized linker configuration.

    Can you explain the methodology behind how you have the linker file setup?

  • Hi Ralph Jacobi,

    Thank you for your reply.

    >Can you explain the methodology behind how you have the linker file setup?

    I would like to protect just only FLASH_EX region and setup other region to readable.

    I would like to protect my code only, so ".text" section set to  FLASH_EX.

    Could you tell me how to fix my linker command file in order to realize what I want to do and not to call faultISR?

    I think faultISR is called because FlashProtectSet() is executed in the region that is the tartget of protect.

    Should I execute FlashProtectSet() in SRAM?

    Regards,

    U-SK

    Regards,

    U-SK

  • Hello U-SK,

    I wouldn't think so since it is set to 'execute only' so execution should be fine. Even if you unravel the for loop and have both calls set like:

        FlashProtectSet( 0x00000800UL, FlashExecuteOnly );
        FlashProtectSet( (0x00000800UL + 0x200), FlashExecuteOnly );

    The FaultISR still triggers.

    I haven't tried to do something like this before so I'll need more time to debug why altering the memory mapping is impacting this in such a manner.

  • Hello U-SK,

    Alright so the root cause of the issue for this is regarding how the linker file in configured regarding the libraries. What is happening is that driverlib is not compiled to have Embedded Constants turned off and therefore the driverlib API calls are causing the FaultISR.

    One workaround would be to use the ROM calls, but since not all TivaWare APIs are in ROM or for some APIs the ROM version should not be used due to software bug fixes/errata etc.

    Another way that isn't recommended would be to set driverlib to not use Embedded Constants but this would negative impact the performance of driverlib, Furthermore, there is no reason to protect the driverlib code as TivaWare is open source.

    So the best way to handle this would be to place the libraries outside of the protected space by further adjusting the linker file. In this case, the Run Time Support library is also placed outside of the protected space:

     

    SECTIONS
    {
        .intvecs    :   > FLASH_1
        .softversion:   > FLASH_VER
        .libraries  :   > FLASH_2
        {
          --library=driverlib.lib (.text)
          --library=rtsv7M4_T_le_v4SPD16_eabi.lib(.text)
        }
        .text       :   > FLASH_EX
        .const      :   > FLASH_2
        .cinit      :   > FLASH_2
        .pinit      :   > FLASH_2
        .init_array :   > FLASH_2
    
        .vtable     :   > RAM_BASE
        .data       :   > SRAM
        .bss        :   > SRAM
        .sysmem     :   > SRAM
        .stack      :   > SRAM
    }

    Using that configuration, the project should build and run correctly.

    I did run into one other quirk regarding that driverlib.lib was not being seen by the compiler despite being part of the file search path, but was able to resolve that by following another E2E post to add driverlib to the Link Order. If you run into the same, reference this: 

  • Hi Ralph,

    I'm able to run my project using linker command file you suggested.

    Thank you!

    U-SK