This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPM secure services issue

Hello,

I have a low power application, which is activated by a push button press. (The DC-DC converter is also in shutdown mode normally, so the NRF9160 does not have power most of the time.) I want to detect the edges of the power enabling push button (short / long press), however the NRF9160's secure mode app (SPM) takes about 350 ms to finish. Because of this I cannot detect the falling edge of the push button, because the main application is not running at that time.

Do you have any idea why does it take so much time for the SPM to finish? Is there a way to reduce it lower than 100 ms.

Alternatively I can implement the edge detect logic in the Secure part, but in this case I need a way to forward information to the Non Secure part.

I've found about the secure_services.h file, which provides a spm_request_read() function, which should be able to read from the Secure part of RAM when called from the Non Secure application. However I cannot make it work. I tried to write to a specific address in the SPM main.c, then read it from the application main.c .

Here's my code:

SPM main.c

 

#define S_NS_COMMON_VAR_ADDR 0x20001000
unsigned int volatile * const s_ns_common_var = (unsigned int *) S_NS_COMMON_VAR_ADDR;

void main(void)
{
    *s_ns_common_var = 0xDEADBEEF;
     printk("Common var addr: %x\tvalue: %x\n", s_ns_common_var, *s_ns_common_var);
	spm_config();
	spm_jump();
}

MAIN app main.c

#define S_NS_COMMON_VAR_ADDR 0x20001000

#include "secure_services.h"
void main(void)
{
	int ret;

    const int num_bytes_to_read = 4;
	const int read_address = S_NS_COMMON_VAR_ADDR;
	u8_t buf[num_bytes_to_read];

	printk("\nRead %d bytes from address 0x%x\n", num_bytes_to_read, read_address);
	ret = spm_request_read(buf, read_address, num_bytes_to_read);
	if (ret != 0) {
		printk("Could not read data (err: %d)\n", ret);
	}
	//...
}

The error code is -1, which means "EPERM" (I think that means the MAIN app doesn't have permission). 

The address 0x20001000 is in the RAM, in the Secure part. 

/* Default SRAM planning when building for nRF9160 with
 * ARM TrustZone-M support
 * - Lowest 64 kB SRAM allocated to Secure image (sram0).
 * - 64 kB SRAM reserved for and used by the BSD socket
 *   library.
 * - Upper 128 kB allocated to Non-Secure image (sram0_ns).
 */

&sram0 {
	reg = <0x20000000 DT_SIZE_K(64)>;
};

&sram0_bsd {
	reg = <0x20010000 DT_SIZE_K(64)>;
};

&sram0_ns {
	reg = <0x20020000 DT_SIZE_K(128)>;
};

Do you have any idea what can be the problem?

Best regards,

Bence

  • I think I found the answer for the second question.

    This is from secure_services.c:

    __TZ_NONSECURE_ENTRY_FUNC
    int spm_request_read(void *destination, u32_t addr, size_t len)
    {
    	static const struct read_range ranges[] = {
    #ifdef PM_MCUBOOT_ADDRESS
    		/* Allow reads of mcuboot metadata */
    		{.start = PM_MCUBOOT_PAD_ADDRESS,
    		 .size = PM_MCUBOOT_PAD_SIZE},
    #endif
    		{.start = FICR_PUBLIC_ADDR,
    		 .size = FICR_PUBLIC_SIZE},
    		{.start = FICR_RESTRICTED_ADDR,
    		 .size = FICR_RESTRICTED_SIZE},
    	};
    
    	if (destination == NULL || len <= 0) {
    		return -EINVAL;
    	}
    
    	for (size_t i = 0; i < ARRAY_SIZE(ranges); i++) {
    		u32_t start = ranges[i].start;
    		u32_t size = ranges[i].size;
    
    		if (addr >= start && addr + len <= start + size) {
    			memcpy(destination, (const void *)addr, len);
    			return 0;
    		}
    	}
    
    	return -EPERM;
    }
    #endif /* CONFIG_SPM_SERVICE_READ */

    It seems that you cannot read from anywhere in the Secure region but only from FICR and MCUBOOT_PAD. I can modify this function to add custom regions which can be read. 

    However it would be better if I could reduce the running time of the Secure part from 350 ms to below 100 ms.

  • Hi,

     

    481 ms with printing (ie: untouched):

    168 ms with CONFIG_SPM_BOOT_SILENTLY=y:

    168 ms with CONFIG_SERIAL=n:

     

    To override spm, I would recommend that you add this to your samples/nrf9160/my_application/CMakeLists.txt file, just below the "cmake_minimum_required(VERSION 3.13.1)" line:

    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/spm.conf")
      set(spm_CONF_FILE
        prj.conf
        ${CMAKE_CURRENT_LIST_DIR}/spm.conf
      )
    endif()
     
    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.conf")
      set(mcuboot_CONF_FILE
        prj.conf
        ${CMAKE_CURRENT_LIST_DIR}/mcuboot.conf
      )
    endif()
     
    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
      set(mcuboot_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
      set(spm_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
    endif()

     

    Now, if you create the file my_application/spm.conf, it should be automatically loaded when you reconfigure you project.

    Paste in CONFIG_SERIAL=n into the spm.conf file, and you should see the same boot-up time as I have above here.

     

    Kind regards,

    Håkon

Related