Adafruit I2S MEMS Microphone Breakout with the NRF9160 DK

Hello,

I am working on a project where I can have Voice over IP on the NRF9160 DK. I am now working with a I2S microphone (https://www.adafruit.com/product/3421) at the moment I have trouble programming I2S. I read the I2S documentation on the zephyr website but I have still trouble understanding it and there is also no example where I can look at. I don't know how to setup the struct device (https://docs.zephyrproject.org/2.0.0/reference/peripherals/i2s.html?highlight=i2s#) that you use in the functions to setup i2s and read/write the buffer. I also don't know which pin i have to connect to the microphone, because the pin names are not the same or can i just connect  to any pin and write in the code to use that pin? If sombody has an I2S example I would really appreciate that. I also need to find a speaker that I can use any suggestions?

Thank you in advance

  • Hi Nahom,

    You can configure any of the available GPIO pins for the nrf9160.

    So you could use the command https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/reference/peripherals/i2s.html#_CPPv413i2s_configureP6device7i2s_dirP10i2s_config and in the .overlay file select which pins it should get. 

    See the device tree chapter in the NCS tutorials.

  • Hi Martin,

    I am having trouble with the i2s_configure function this is my code and overlay file. I call the recordaudio function in a different file and then I something goes wrong in i2s_init funtion  at i2s_configure. The code stops after the i2s_configure  function.

    Thank you in advance

    #include <zephyr.h>
    #include <device.h>
    #include <drivers/i2s.h>
    #include <sys/printk.h>
    #include <stdbool.h>
    
    #include "microphone.h"
    #include "button.h"
    #include "udp.h"
    
    #define  MICROPHONE_SAMPLE_FREQ (8000)
    #define  MICROPHONE_SAMPLE_PER_FRAME (1)
    #define  MICROPHONE_NUM_CHANNELS (1)
    #define  MICROPHONE_SAMPLE_BIT_WIDTH (24)
    #define  MICROPHONE_SAMPLE_BYTES (2)
    #define  MICROPHONE_BLOCK_SIZE (4)
    #define  DEVICE_NAME  "I2S_0" 
    
    
    struct k_mem_slab mic_mem_slab;
    struct device *i2s_device;
    
    K_MEM_SLAB_DEFINE(mic_mem_slab,MICROPHONE_BLOCK_SIZE,MICROPHONE_SAMPLE_FREQ,4);
    
    void i2s_init()
    {
      struct i2s_config i2s_cfg;
      int config;
      
      i2s_device=device_get_binding(DEVICE_NAME);
      
      i2s_cfg.word_size=MICROPHONE_SAMPLE_BIT_WIDTH;
      i2s_cfg.channels=MICROPHONE_NUM_CHANNELS;
      i2s_cfg.format=I2S_FMT_DATA_FORMAT_I2S;
      i2s_cfg.options=I2S_OPT_FRAME_CLK_MASTER |I2S_OPT_BIT_CLK_MASTER;//?
      i2s_cfg.frame_clk_freq=MICROPHONE_SAMPLE_FREQ;
      i2s_cfg.mem_slab=&mic_mem_slab;
      i2s_cfg.block_size=MICROPHONE_BLOCK_SIZE*MICROPHONE_SAMPLE_FREQ;
      i2s_cfg.timeout=K_FOREVER;
      
      config=i2s_configure(i2s_device,I2S_DIR_RX,&i2s_cfg);
      if(config!=0){
          printk("i2s_configure failed with %d error", config);
      }
     
    
    }
    
    void recordaudio(void)
    {
      int ret;
      int trigger;
      void *buf;  //uint32_t
      size_t size;
      //configure i2s and start
      i2s_init();
      printk("Starting recording...");
      
      trigger=i2s_trigger(i2s_device,I2S_DIR_RX,I2S_TRIGGER_START); 
      if(trigger!=0){
        printk("TRIGGER_START failed with %d error", trigger);
      }
      
      while(startrecording==true){
        ret=i2s_read(i2s_device,&buf,&size);
        if(ret!=0){
          printk("i2s_read failed with %d error", ret);
        }
      }
        i2s_trigger(i2s_device,I2S_DIR_RX,I2S_TRIGGER_STOP);
        if(trigger!=0){
          printk("TRIGGER_STOP failed with %d error", trigger);
        }
    
        i2s_trigger(i2s_device,I2S_DIR_RX,I2S_TRIGGER_DROP);
        if(trigger!=0){
          printk("TRIGGER_DROP failed with %d error", trigger);
        }
      printk("Exiting program...");
    }
    
    
    

    &i2s0 {
    	    status = "okay";
            sdout-pin=<8>;
    	    lrck-pin=<9>;
            sck-pin=<10>;
            sdin-pin=<11>;
            mck-pin=<12>;
    };
    

  • Hi Nahom,
    Sorry for the delay.
    It does look like I2S is not enabled to be used in the non-secure area (will make a pull request on this as well),
    so you need to change the nrf/subsys/spm files Kconfig and the spm.c to the following:

    spm.c (see line 354)

    /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <zephyr.h>
    #include <sys/printk.h>
    #include <sys/util.h>
    #include <linker/linker-defs.h>
    #include <device.h>
    #include <drivers/gpio.h>
    #include <hal/nrf_spu.h>
    #include "spm_internal.h"
    
    #if !defined(CONFIG_ARM_SECURE_FIRMWARE)
    #error "Module requires compiling for Secure ARM Firmware"
    #endif
    
    /* Include required APIs for TrustZone-M */
    #include <arm_cmse.h>
    #include <cortex_m/tz.h>
    
    #include <nrfx.h>
    
    #if USE_PARTITION_MANAGER
    #include <pm_config.h>
    #define NON_SECURE_APP_ADDRESS PM_APP_ADDRESS
    #else
    #define NON_SECURE_APP_ADDRESS DT_FLASH_AREA_IMAGE_0_NONSECURE_OFFSET_0
    #endif /* USE_PARTITION_MANAGER */
    
    /* This reflects the configuration in DTS. */
    #define NON_SECURE_RAM_OFFSET 0x10000
    
    #define NON_SECURE_FLASH_REGION_INDEX \
    	((NON_SECURE_APP_ADDRESS) / (FLASH_SECURE_ATTRIBUTION_REGION_SIZE))
    #define NON_SECURE_RAM_REGION_INDEX \
    	((NON_SECURE_RAM_OFFSET) / (RAM_SECURE_ATTRIBUTION_REGION_SIZE))
    
    /*
     *  * The security configuration for depends on where the non secure app
     *  * is placed. All flash regions before the region which contains the
     *  * non secure app is configured as Secure.
     *
     *                FLASH
     *  1 MB  |---------------------|
     *        |                     |
     *        |                     |
     *        |                     |
     *        |                     |
     *        |                     |
     *        |     Non-Secure      |
     *        |       Flash         |
     *        |                     |
     *  X kB  |---------------------|
     *        |                     |
     *        |     Secure          |
     *        |      Flash          |
     *  0 kB  |---------------------|
     *
     *  * The security configuration for SRAM is applied:
     *
     *                SRAM
     * 256 kB |---------------------|
     *        |                     |
     *        |                     |
     *        |                     |
     *        |     Non-Secure      |
     *        |    SRAM (image)     |
     *        |                     |
     * 128 kB |.................... |
     *        |     Non-Secure      |
     *        |  SRAM (BSD Library) |
     *  64 kB |---------------------|
     *        |      Secure         |
     *        |       SRAM          |
     *  0 kB  |---------------------|
     */
    
    extern void irq_target_state_set(unsigned int irq, int secure_state);
    extern int irq_target_state_is_secure(unsigned int irq);
    
    /* printk wrapper, to turn off logs when booting silently */
    #define PRINT(...)                                                             \
    	do {                                                                   \
    		if (!IS_ENABLED(CONFIG_SPM_BOOT_SILENTLY)) {                   \
    			printk(__VA_ARGS__);                                   \
    		}                                                              \
    	} while (0)
    
    /* Local convenience macro to extract the peripheral
     * ID from the base address.
     */
    #define NRFX_PERIPHERAL_ID_GET(base_addr) \
    	(uint8_t)((uint32_t)(base_addr) >> 12)
    
    #ifdef CONFIG_SPM_BOOT_SILENTLY
    #define PERIPH(name, reg, config)                                              \
    	{                                                                      \
    		.id = NRFX_PERIPHERAL_ID_GET(reg), IS_ENABLED(config)          \
    	}
    #else
    #define PERIPH(name, reg, config)                                              \
    	{                                                                      \
    		name, .id = NRFX_PERIPHERAL_ID_GET(reg), IS_ENABLED(config)    \
    	}
    #endif
    
    /* Check if configuration exceeds the number of
     * DPPI Channels available on device.
     */
    #if (CONFIG_SPM_NRF_DPPIC_PERM_MASK >= (1 << DPPI_CH_NUM))
    #error "SPM_NRF_DPPIC_PERM_MASK exceeds number of available DPPI channels"
    #endif
    
    #if defined(CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS)
    
    static void spm_config_nsc_flash(void)
    {
    	/* Configure a single region in Secure Flash as Non-Secure Callable
    	 * (NSC) area.
    	 *
    	 * Area to configure is dynamically decided with help from linker code.
    	 *
    	 * Note: Any Secure Entry functions, exposing secure services to the
    	 * Non-Secure firmware, shall be located inside this NSC area.
    	 *
    	 * If the start address of the NSC area is hard-coded, it must follow
    	 * the HW restrictions: The size must be a power of 2 between 32 and
    	 * 4096, and the end address must fall on a SPU region boundary.
    	 */
    	u32_t nsc_size = FLASH_NSC_SIZE_FROM_ADDR(__sg_start);
    
    	__ASSERT((u32_t)__sg_size <= nsc_size,
    		"The Non-Secure Callable region is overflowed by %d byte(s).\n",
    		(u32_t)__sg_size - nsc_size);
    
    	nrf_spu_flashnsc_set(NRF_SPU, 0, FLASH_NSC_SIZE_REG(nsc_size),
    			FLASH_NSC_REGION_FROM_ADDR(__sg_start), false);
    
    	PRINT("Non-secure callable region 0 placed in flash region %d with size %d.\n",
    		NRF_SPU->FLASHNSC[0].REGION, NRF_SPU->FLASHNSC[0].SIZE << 5);
    }
    #endif /* CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS */
    
    
    static void config_regions(bool ram, size_t start, size_t end, u32_t perm)
    {
    	const size_t region_size = ram ? RAM_SECURE_ATTRIBUTION_REGION_SIZE
    					: FLASH_SECURE_ATTRIBUTION_REGION_SIZE;
    
    	for (size_t i = start; i < end; i++) {
    		if (ram) {
    			NRF_SPU->RAMREGION[i].PERM = perm;
    		} else {
    			NRF_SPU->FLASHREGION[i].PERM = perm;
    		}
    	}
    
    	PRINT("%02u %02u 0x%05x 0x%05x \t", start, end - 1,
    				region_size * start, region_size * end);
    	PRINT("%s", perm & (ram ? SRAM_SECURE : FLASH_SECURE) ? "Secure\t\t" :
    								"Non-Secure\t");
    	PRINT("%c", perm & (ram ? SRAM_READ : FLASH_READ)  ? 'r' : '-');
    	PRINT("%c", perm & (ram ? SRAM_WRITE : FLASH_WRITE) ? 'w' : '-');
    	PRINT("%c", perm & (ram ? SRAM_EXEC : FLASH_EXEC)  ? 'x' : '-');
    	PRINT("%c", perm & (ram ? SRAM_LOCK : FLASH_LOCK)  ? 'l' : '-');
    	PRINT("\n");
    }
    
    
    static void spm_config_flash(void)
    {
    	/* Regions of flash up to and including SPM are configured as Secure.
    	 * The rest of flash is configured as Non-Secure.
    	 */
    	const u32_t secure_flash_perm = FLASH_READ | FLASH_WRITE | FLASH_EXEC
    			| FLASH_LOCK | FLASH_SECURE;
    	const u32_t nonsecure_flash_perm = FLASH_READ | FLASH_WRITE | FLASH_EXEC
    			| FLASH_LOCK | FLASH_NONSEC;
    
    	PRINT("Flash regions\t\tDomain\t\tPermissions\n");
    
    	config_regions(false, 0, NON_SECURE_FLASH_REGION_INDEX,
    			secure_flash_perm);
    	config_regions(false, NON_SECURE_FLASH_REGION_INDEX,
    			NUM_FLASH_SECURE_ATTRIBUTION_REGIONS,
    			nonsecure_flash_perm);
    	PRINT("\n");
    
    #if defined(CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS)
    	spm_config_nsc_flash();
    	PRINT("\n");
    
    #if defined(CONFIG_SPM_SECURE_SERVICES)
    	int err = spm_secure_services_init();
    
    	if (err != 0) {
    		PRINT("Could not initialize secure services (err %d).\n", err);
    	}
    #endif
    #endif /* CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS */
    }
    
    static void spm_config_sram(void)
    {
    	/* Lower 64 kB of SRAM is allocated to the Secure firmware image.
    	 * The rest of SRAM is allocated to Non-Secure firmware image.
    	 */
    
    	const u32_t secure_ram_perm = SRAM_READ | SRAM_WRITE | SRAM_EXEC
    		| SRAM_LOCK | SRAM_SECURE;
    	const u32_t nonsecure_ram_perm = SRAM_READ | SRAM_WRITE | SRAM_EXEC
    		| SRAM_LOCK | SRAM_NONSEC;
    
    	PRINT("SRAM region\t\tDomain\t\tPermissions\n");
    
    	/* Configuration for Secure RAM Regions (0 - 64 kB) */
    	config_regions(true, 0, NON_SECURE_RAM_REGION_INDEX,
    			secure_ram_perm);
    	/* Configuration for Non-Secure RAM Regions (64 kb - end) */
    	config_regions(true, NON_SECURE_RAM_REGION_INDEX,
    			NUM_RAM_SECURE_ATTRIBUTION_REGIONS,
    			nonsecure_ram_perm);
    	PRINT("\n");
    }
    
    static bool usel_or_split(u8_t id)
    {
    	const u32_t perm = NRF_SPU->PERIPHID[id].PERM;
    
    	/* NRF_GPIOTE1_NS needs special handling as its
    	 * peripheral ID for non-secure han incorrect properties
    	 * in the NRF_SPM->PERIPHID[id].perm register.
    	 */
    	if (id == NRFX_PERIPHERAL_ID_GET(NRF_GPIOTE1_NS)) {
    		return true;
    	}
    
    	bool present = (perm & SPU_PERIPHID_PERM_PRESENT_Msk) ==
    		       SPU_PERIPHID_PERM_PRESENT_Msk;
    
    	/* User-selectable attribution */
    	bool usel = (perm & SPU_PERIPHID_PERM_SECUREMAPPING_Msk) ==
    		    SPU_PERIPHID_PERM_SECUREMAPPING_UserSelectable;
    
    	/* Split attribution */
    	bool split = (perm & SPU_PERIPHID_PERM_SECUREMAPPING_Msk) ==
    		     SPU_PERIPHID_PERM_SECUREMAPPING_Split;
    
    	return present && (usel || split);
    }
    
    static int spm_config_peripheral(u8_t id, bool dma_present)
    {
    	/* Set a peripheral to Non-Secure state, if
    	 * - it is present
    	 * - has UserSelectable/Split attribution.
    	 *
    	 * Assign DMA capabilities and lock down the attribution.
    	 *
    	 * Note: the function assumes that the peripheral ID matches
    	 * the IRQ line.
    	 */
    	NVIC_DisableIRQ(id);
    
    	if (usel_or_split(id)) {
    		NRF_SPU->PERIPHID[id].PERM = PERIPH_PRESENT | PERIPH_NONSEC |
    			(dma_present ? PERIPH_DMA_NOSEP : 0) |
    			PERIPH_LOCK;
    	}
    
    	/* Even for non-present peripherals we force IRQs to be routed
    	 * to Non-Secure state.
    	 */
    	irq_target_state_set(id, 0);
    	return 0;
    }
    
    static void spm_dppi_configure(u32_t mask)
    {
    	NRF_SPU->DPPI[0].PERM = mask;
    }
    
    static void spm_config_peripherals(void)
    {
    	struct periph_cfg {
    #ifndef CONFIG_SPM_BOOT_SILENTLY
    		char *name;
    #endif
    		u8_t id;
    		u8_t nonsecure;
    	};
    
    	/* - All user peripherals are allocated to the Non-Secure domain.
    	 * - All GPIOs are allocated to the Non-Secure domain.
    	 */
    	static const struct periph_cfg periph[] = {
    #ifdef NRF_P0
    		PERIPH("NRF_P0", NRF_P0, CONFIG_SPM_NRF_P0_NS),
    #endif
    #ifdef NRF_CLOCK
    		PERIPH("NRF_CLOCK", NRF_CLOCK, CONFIG_SPM_NRF_CLOCK_NS),
    #endif
    #ifdef NRF_RTC0
    		PERIPH("NRF_RTC0", NRF_RTC0, CONFIG_SPM_NRF_RTC0_NS),
    #endif
    #ifdef NRF_RTC1
    		PERIPH("NRF_RTC1", NRF_RTC1, CONFIG_SPM_NRF_RTC1_NS),
    #endif
    #ifdef NRF_NVMC
    		PERIPH("NRF_NVMC", NRF_NVMC, CONFIG_SPM_NRF_NVMC_NS),
    #endif
    #ifdef NRF_UARTE1
    		PERIPH("NRF_UARTE1", NRF_UARTE1, CONFIG_SPM_NRF_UARTE1_NS),
    #endif
    #ifdef NRF_UARTE2
    		PERIPH("NRF_UARTE2", NRF_UARTE2, CONFIG_SPM_NRF_UARTE2_NS),
    #endif
    #ifdef NRF_TWIM2
    		PERIPH("NRF_TWIM2", NRF_TWIM2, CONFIG_SPM_NRF_TWIM2_NS),
    #endif
    #ifdef NRF_SPIM3
    		PERIPH("NRF_SPIM3", NRF_SPIM3, CONFIG_SPM_NRF_SPIM3_NS),
    #endif
    #ifdef NRF_TIMER0
    		PERIPH("NRF_TIMER0", NRF_TIMER0, CONFIG_SPM_NRF_TIMER0_NS),
    #endif
    #ifdef NRF_TIMER1
    		PERIPH("NRF_TIMER1", NRF_TIMER1, CONFIG_SPM_NRF_TIMER1_NS),
    #endif
    #ifdef NRF_TIMER2
    		PERIPH("NRF_TIMER2", NRF_TIMER2, CONFIG_SPM_NRF_TIMER2_NS),
    #endif
    #ifdef NRF_SAADC
    		PERIPH("NRF_SAADC", NRF_SAADC, CONFIG_SPM_NRF_SAADC_NS),
    #endif
    #ifdef NRF_PWM0
    		PERIPH("NRF_PWM0", NRF_PWM0, CONFIG_SPM_NRF_PWM0_NS),
    #endif
    #ifdef NRF_PWM1
    		PERIPH("NRF_PWM1", NRF_PWM1, CONFIG_SPM_NRF_PWM1_NS),
    #endif
    #ifdef NRF_PWM2
    		PERIPH("NRF_PWM2", NRF_PWM2, CONFIG_SPM_NRF_PWM2_NS),
    #endif
    #ifdef NRF_PWM3
    		PERIPH("NRF_PWM3", NRF_PWM3, CONFIG_SPM_NRF_PWM3_NS),
    #endif
    #ifdef NRF_WDT
    		PERIPH("NRF_WDT", NRF_WDT, CONFIG_SPM_NRF_WDT_NS),
    #endif
    #ifdef NRF_I2S
    		PERIPH("NRF_I2S", NRF_I2S, CONFIG_SPM_NRF_I2S_NS),
    #endif
    		/* There is no DTS node for the peripherals below,
    		 * so address them using nrfx macros directly.
    		 */
    		PERIPH("NRF_IPC", NRF_IPC_S, CONFIG_SPM_NRF_IPC_NS),
    		PERIPH("NRF_VMC", NRF_VMC_S, CONFIG_SPM_NRF_VMC_NS),
    		PERIPH("NRF_FPU", NRF_FPU_S, CONFIG_SPM_NRF_FPU_NS),
    		PERIPH("NRF_EGU1", NRF_EGU1_S, CONFIG_SPM_NRF_EGU1_NS),
    		PERIPH("NRF_EGU2", NRF_EGU2_S, CONFIG_SPM_NRF_EGU2_NS),
    		PERIPH("NRF_DPPIC", NRF_DPPIC_S, CONFIG_SPM_NRF_DPPIC_NS),
    
    		PERIPH("NRF_GPIOTE1", NRF_GPIOTE1_NS,
    				      CONFIG_SPM_NRF_GPIOTE1_NS),
    		PERIPH("NRF_REGULATORS", NRF_REGULATORS_S,
    				      CONFIG_SPM_NRF_REGULATORS_NS),
    	};
    
    	if (IS_ENABLED(CONFIG_SPM_NRF_DPPIC_NS)) {
    		spm_dppi_configure(CONFIG_SPM_NRF_DPPIC_PERM_MASK);
    	}
    
    	PRINT("Peripheral\t\tDomain\t\tStatus\n");
    
    	if (IS_ENABLED(CONFIG_SPM_NRF_P0_NS)) {
    		/* Configure GPIO pins to be Non-Secure */
    		NRF_SPU->GPIOPORT[0].PERM = 0;
    	}
    
    	for (size_t i = 0; i < ARRAY_SIZE(periph); i++) {
    		int err;
    
    #ifndef CONFIG_SPM_BOOT_SILENTLY
    		PRINT("%02u %-21s%s", i, periph[i].name,
    		      periph[i].nonsecure ? "Non-Secure" : "Secure\t");
    #endif
    
    		if (!periph[i].nonsecure) {
    			PRINT("\tSKIP\n");
    			continue;
    		}
    
    		err = spm_config_peripheral(periph[i].id, false);
    		if (err) {
    			PRINT("\tERROR\n");
    		} else {
    			PRINT("\tOK\n");
    		}
    	}
    	PRINT("\n");
    }
    
    
    static void spm_configure_ns(const tz_nonsecure_setup_conf_t
    	*spm_ns_conf)
    {
    	/* Configure core register block for Non-Secure state. */
    	tz_nonsecure_state_setup(spm_ns_conf);
    	/* Prioritize Secure exceptions over Non-Secure */
    	tz_nonsecure_exception_prio_config(1);
    	/* Set non-banked exceptions to target Non-Secure */
    	tz_nbanked_exception_target_state_set(0);
    	/* Configure if Non-Secure firmware should be allowed to issue System
    	 * reset. If not it could be enabled through a secure service.
    	 */
    	tz_nonsecure_system_reset_req_block(
    		IS_ENABLED(CONFIG_SPM_BLOCK_NON_SECURE_RESET)
    	);
    	/* Allow SPU to have precedence over (non-existing) ARMv8-M SAU. */
    	tz_sau_configure(0, 1);
    
    #if defined(CONFIG_ARMV7_M_ARMV8_M_FP) && defined(CONFIG_SPM_NRF_FPU_NS)
    	/* Allow Non-Secure firmware to use the FPU */
    	tz_nonsecure_fpu_access_enable();
    #endif /* CONFIG_ARMV7_M_ARMV8_M_FP */
    }
    
    void spm_jump(void)
    {
    	/* Extract initial MSP of the Non-Secure firmware image.
    	 * The assumption is that the MSP is located at VTOR_NS[0].
    	 */
    	u32_t *vtor_ns = (u32_t *)NON_SECURE_APP_ADDRESS;
    
    	PRINT("SPM: NS image at 0x%x\n", (u32_t)vtor_ns);
    	PRINT("SPM: NS MSP at 0x%x\n", vtor_ns[0]);
    	PRINT("SPM: NS reset vector at 0x%x\n", vtor_ns[1]);
    
    	/* Configure Non-Secure stack */
    	tz_nonsecure_setup_conf_t spm_ns_conf = {
    		.vtor_ns = (u32_t)vtor_ns,
    		.msp_ns = vtor_ns[0],
    		.psp_ns = 0,
    		.control_ns.npriv = 0, /* Privileged mode*/
    		.control_ns.spsel = 0 /* Use MSP in Thread mode */
    	};
    
    	spm_configure_ns(&spm_ns_conf);
    
    	/* Generate function pointer for Non-Secure function call. */
    	TZ_NONSECURE_FUNC_PTR_DECLARE(reset_ns);
    	reset_ns = TZ_NONSECURE_FUNC_PTR_CREATE(vtor_ns[1]);
    
    	if (TZ_NONSECURE_FUNC_PTR_IS_NS(reset_ns)) {
    		PRINT("SPM: prepare to jump to Non-Secure image.\n");
    
    		/* Note: Move UARTE0 before jumping, if it is
    		 * to be used on the Non-Secure domain.
    		 */
    
    		/* Configure UARTE0 as non-secure */
    		spm_config_peripheral(
    			NRFX_PERIPHERAL_ID_GET(NRF_UARTE0), 0);
    
    		__DSB();
    		__ISB();
    
    		/* Jump to Non-Secure firmware */
    		reset_ns();
    
    		CODE_UNREACHABLE;
    
    	} else {
    		PRINT("SPM: wrong pointer type: 0x%x\n",
    		      (u32_t)reset_ns);
    	}
    }
    
    void spm_config(void)
    {
    	spm_config_flash();
    	spm_config_sram();
    	spm_config_peripherals();
    }
    


    Kconfig (line 215)
    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
    #
    
    menu "SPM"
    
    config SPM
    	bool "Use Secure Partition Manager"
    	default y if TRUSTED_EXECUTION_NONSECURE
    	select FW_INFO
    	imply ARM_FIRMWARE_USES_SECURE_ENTRY_FUNCS
    
    if SPM
    module=SPM
    source "${ZEPHYR_BASE}/../nrf/subsys/partition_manager/Kconfig.template.build_strategy"
    endif
    
    
    menuconfig IS_SPM
    	bool "Current app is SPM"
    	default n
    	select TRUSTED_EXECUTION_SECURE
    
    if IS_SPM
    # Define used by partition_manager.py to deduce size of partition.
    # Unable to use the size template due to non-trivial defaults.
    config PM_PARTITION_SIZE_SPM
    	hex "Flash space reserved for SPM"
    	default 0xc000 if SPM_SERVICE_RNG # To build correctly with MCUboot.
    	default 0x8000
    	help
    	  Flash space set aside for the SPM. Note, the name
    	  of this configuration needs to match the requirements set by the
    	  script 'partition_manager.py'. See pm.yml.
    
    config SPM_BOOT_SILENTLY
    	bool "Boot silently"
    	default n
    
    config SPM_SECURE_SERVICES
    	bool "Enable secure services"
    	default y
    	select ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS
    	help
    	  Secure services can be invoked from the Non-Secure Firmware via
    	  secure entry functions.
    
    if SPM_SECURE_SERVICES
    config SPM_SERVICE_RNG
    	bool "Request random numbers"
    	default y
    	select NORDIC_SECURITY_BACKEND
    	select FLOAT
    
    # NORDIC_SECURITY_BACKEND is not supported on 53 yet
    	depends on ! SOC_NRF5340_CPUAPP
    
    	help
    	  The Non-Secure Firmware is not allowed to use the crypto hardware.
    	  This service allows it to request random numbers from the SPM.
    
    config SPM_SERVICE_READ
    	bool "Read from memory"
    	default y
    	help
    	  The Non-Secure Firmware is not allowed to read the memory
    	  marked as secure. This service allows it to request random
    	  read operations within the ranges configured in
    	  secure_services.c.
    
    config SPM_SERVICE_REBOOT
    	bool "Enable system reset as a secure service"
    	default n
    	select REBOOT
    	help
    	  If Non-Secure Firmware is blocked from issuing system reset, this
    	  service will allow it to issue a request to do a system reset through
    	  a secure service.
    
    config SPM_SERVICE_FIND_FIRMWARE_INFO
    	bool "Find firmware info"
    	default y
    	help
    	  The Non-Secure Firmware is not allowed to read the memory
    	  marked as secure. This service allows it to request firmware info
    	  about image stored at a given address.
    
    config SPM_SERVICE_PREVALIDATE
    	bool "Prevalidate B1 upgrades (Requires Immutable Bootloader)"
    	default n
    	select SECURE_BOOT_CRYPTO
    	select SECURE_BOOT_VALIDATION
    	select BL_VALIDATE_FW_EXT_API_ATLEAST_OPTIONAL
    	help
    	  The B0 bootloader allows calls into it for prevalidating upgrades of
    	  the stage it verifies. The B0 bootloader is in secure memory, so this
    	  secure service is needed for the app to access the prevalidation
    	  function.
    
    endif # SPM_SECURE_SERVICES
    
    config SPM_BLOCK_NON_SECURE_RESET
    	bool "Block system reset calls from Non-Secure domain"
    	default n #FIXME: Remove mention of debugger with regards to reboot in help text when NRF91-313 has been resolved
    	help
    	  This will block the application running in Non-Secure from being able
    	  to issue a system reset of the chip without going through a secure
    	  service. If not enabled, a debugger will not be able to issue a
    	  system reset while the core is executing Non-Secure code.
    
    menu "Configure Non-Secure peripherals"
    
    config SPM_NRF_CLOCK_NS
    	bool "Clock control is Non-Secure"
    	default y
    
    config SPM_NRF_RTC0_NS
    	bool "RTC0 is Non-Secure"
    	default y
    
    config SPM_NRF_RTC1_NS
    	bool "RTC1 is Non-Secure"
    	default y
    
    config SPM_NRF_IPC_NS
    	bool "IPC is Non-Secure"
    	default y
    
    config SPM_NRF_NVMC_NS
    	bool "NVMC is Non-Secure"
    	default y
    
    config SPM_NRF_VMC_NS
    	bool "VMC is Non-Secure"
    	default y
    
    config SPM_NRF_P0_NS
    	bool "GPIO is Non-Secure"
    	default y
    
    config SPM_NRF_GPIOTE1_NS
    	bool "GPIOTE1 IRQ available in Non-Secure domain"
    	default y
    
    config SPM_NRF_UARTE1_NS
    	bool "UARTE1 is Non-Secure"
    	default y
    
    config SPM_NRF_UARTE2_NS
    	bool "UARTE2 is Non-Secure"
    	default n
    
    config SPM_NRF_EGU1_NS
    	bool "EGU1 is Non-Secure"
    	default y
    
    config SPM_NRF_EGU2_NS
    	bool "EGU2 is Non-Secure"
    	default y
    
    config SPM_NRF_FPU_NS
    	bool "FPU is Non-Secure"
    	default y
    
    config SPM_NRF_TWIM2_NS
    	bool "TWIM2 is Non-Secure"
    	default y
    
    config SPM_NRF_SPIM3_NS
    	bool "SPIM3 is Non-Secure"
    	default y
    
    config SPM_NRF_TIMER0_NS
    	bool "TIMER0 is Non-Secure"
    	default y
    
    config SPM_NRF_TIMER1_NS
    	bool "TIMER1 is Non-Secure"
    	default y
    
    config SPM_NRF_TIMER2_NS
    	bool "TIMER2 is Non-Secure"
    	default y
    
    config SPM_NRF_SAADC_NS
    	bool "SAADC is Non-Secure"
    	default y
    
    config SPM_NRF_PWM0_NS
    	bool "PWM0 is Non-Secure"
    	default y
    
    config SPM_NRF_PWM1_NS
    	bool "PWM1 is Non-Secure"
    	default y
    
    config SPM_NRF_PWM2_NS
    	bool "PWM2 is Non-Secure"
    	default y
    
    config SPM_NRF_PWM3_NS
    	bool "PWM3 is Non-Secure"
    	default y
    
    config SPM_NRF_REGULATORS_NS
    	bool "Regulators is Non-Secure"
    	default y
    
    config SPM_NRF_WDT_NS
    	bool "WDT is Non-Secure"
    	default y
    
    config SPM_NRF_I2S_NS
    	bool "I2S is Non-Secure"
    	default y
    endmenu
    
    config SPM_NRF_DPPIC_NS
    	bool "DPPIC is Non-Secure"
    	default y
    
    config SPM_NRF_DPPIC_PERM_MASK
    	hex "Set DPPIC PERM mask for Non-secure"
    	default 0x00000000
    	depends on SPM_NRF_DPPIC_NS
    	help
    	  The input mask is a mirror of the permission bits set in
    	  register SPU.DPPI.PERM[] to allow non-secure application to
    	  control DPPIC per the given input mask.
    	  The default value is to allow all DPPI channels to non-secure region.
    
    endif # IS_SPM
    
    # Set new default name for the veneers file.
    
    if ARM_FIRMWARE_USES_SECURE_ENTRY_FUNCS
    config ARM_ENTRY_VENEERS_LIB_NAME
    	string "Entry Veneers symbol file"
    	default "spm/libspmsecureentries.a"
    endif
    
    if ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS
    config ARM_ENTRY_VENEERS_LIB_NAME
    	string "Entry Veneers symbol file"
    	default "libspmsecureentries.a"
    endif
    
    endmenu # SPM
    


Related