Reserved resources for Zephyr / NCS, eg. DPPI's on the nRF54 ?

If I am to do a custom SPI Slave driver to achieve ultra low latency handling and would like it to coexist with NCS / Zephyr, is there a document describing this ?

E.g. which resources are reserved by by NCS / Zephyr ?

I will be testing it on the nRF54L15 DK's SPIS21.

Thanks,

Thorkild

  • If I could also get some information on how to compile a bare-metal example using the SPI that would be really helpfull:

    The attached file is my attempt to configure the SPIS21 on the register level, but it crashes when booted.

    spi_custom.c 

    *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [00:00:00.002,258] <err> os: ***** MPU FAULT *****
    [00:00:00.002,264] <err> os:   Data Access Violation
    [00:00:00.002,268] <err> os:   MMFAR Address: 0x35c
    [00:00:00.002,279] <err> os: r0/a1:  0x00000000  r1/a2:  0x00000001  r2/a3:  0x00000000
    [00:00:00.002,285] <err> os: r3/a4:  0x500c7000 r12/ip:  0x00000009 r14/lr:  0x000017c1
    [00:00:00.002,289] <err> os:  xpsr:  0x01000000
    [00:00:00.002,293] <err> os: Faulting instruction address (r15/pc): 0x000016d2
    [00:00:00.002,312] <err> os: >>> ZEPHYR FATAL ERROR 19: Unknown error on CPU 0
    [00:00:00.002,326] <err> os: Current thread: 0x200008a8 (unknown)
    [00:00:00.072,471] <err> os: Halting system
    

    The PDK/DK is attached to a Raspberry PI acting as SPI master and I have another example running programmed using NCS/Zephyr and using the "spi_transceive_dt" command. 

  • I don't see the SPU handled, my notes might help; here I set the LED pins and also a UART, something similar is required for SPIS.

    // SAU Arm security attribution unit
    // SPU Nordic system protection unit
    // MPC Nordic memory privilege controller
    // The Arm Cortex-M based CPU support Arm TrustZone for secure, non-secure, and non-secure callable memory regions.
    // The security attribution unit (SAU) and implementation defined attribution unit (IDAU) define the access
    // permissions based on the security state.
    // The IDAU configuration divides system memory space into secure (S) and non-secure (NS) regions. The IDAU is preset
    // in hardware and is not available for user configuration.
    // The SAU provides configurable regions for the Arm Cortex-M CPU, and is used to define non-secure callable (NSC) regions
    //
    // The Arm Cortex-M33 CPU must configure its SAU regions when the CPU starts - see Section 7
    // SAU configuration registers are documented in the Arm Cortex-M33 Technical Reference Manual, revision r1p0
    // LOCK.LOCKSAU When set to Locked, this prevents further modifications to the SAU registers see Section 4
    
    // This section describes the differences in functionality between product revisions.
    // r0p0
    //  First release.
    // r0p1
    //  Updated CPUID reset value, 0x410FD211.
    //  The Cortex®-M33 processor optionally supports stalls to guarantee the delivery of trace packets. As a result, the ITM_TCR.STALLENA bit field is now RW.
    //  Various engineering errata fixes.
    // r0p2
    //  Updated CPUID reset value, 0x410FD212.
    //  Various engineering errata fixes.
    // r0p3
    //  Updated CPUID reset value, 0x410FD213.
    //  Various engineering errata fixes.
    // r0p4
    //  Updated CPUID reset value, 0x410FD214.
    //  Various engineering errata fixes.
    // r1p0
    //  Updated CPUID reset value, 0x411FD210.
    //  Implementation of the Custom Datapath Extension (CDE) with support for the Arm Custom Instructions (ACIs).
    //  Support for Software Test Library (STL) and Software Built-In Self Test (SBIST) controller.
    //  Various engineering errata fixes.
    
    // Port pins are sequential; however that is not guaranteed to remain so, so start using macro now
    #define MAP(port, pin) (((port) << 5) | ((pin) & 0x1F))
    #define PORT_VAL(pin)  ((pin>>5) & 0x0F)
    #define PIN_VAL(pin)    (pin     & 0x1F)
    
    // nRF54L15 I/O Pin Listing
    //
    //                                     Pin  Name  Schematic Name Extra Functions  Description of Options  Notes
    //                                     ===  ===== ============== ================ ======================  ================================
    #define LED_GREEN_PIN_0  MAP(2,  9) // ..   P2.09
    #define LED_GREEN_PIN_1  MAP(1, 10) // ..   P1.10
    #define LED_GREEN_PIN_2  MAP(2, 07) // ..   P2.07
    #define LED_GREEN_PIN_3  MAP(1, 14) // ..   P1.14
    STATIC_ASSERT(PORT_VAL(LED_GREEN_PIN_0) ==    2, "PORT_VAL(LED_GREEN_PIN_0) differs from 2");
    STATIC_ASSERT(PIN_VAL(LED_GREEN_PIN_0)  ==    9, "PIN_VAL(LED_GREEN_PIN_0)  differs from 9");
    STATIC_ASSERT(LED_GREEN_PIN_0           == 0x49, "LED_GREEN_PIN_0 differs from 0x49 or P2.09");
    
       // Table 9: Peripheral Address Format
       // NRF_P1_NS_BASE 0x400D8200
       // |||                                      [31:29] Address region 2: Peripherals on APB Bus
       //    |                                     [28]    Security 0: Non-secure, 1: Secure
       //      ||||                                [27:24] Reserved Set to zero
       //           |||| ||                        [23:18] Peripheral APB bus
       //           |||| ||                                1: APB peripherals in MCU power domain   SPU00
       //           |||| ||                                2: APB peripherals in RADIO power domain SPU10
       //           |||| ||                                3: APB peripherals in PERI power domain  SPU20 <==
       //           |||| ||                                4: APB peripherals in LP power domain    SPU30
       //                  || ||||                [17:12] Peripheral subordinate index  NRF_P1: 011000 = 24
       //                  || ||||                        Used for configuring the SPU — System protection unit on page
       //                  || ||||                        209, as the index n of register SPU.PERIPH[n].PERM.
       //                          |||||||||||||| [11:0]  Peripheral address space
       // 3322 2222 2222 1111 1111 1100 0000 0000 Dec
       // 1098 7654 3210 9876 5432 1098 7654 3210
       //
       // 1111 1111 1111 1111 0000 0000 0000 0000 Hex
       // FEDC BA98 7654 3210 FEDC BA98 7654 3210
       //
       // 0100 0000 0000 1101 1000 0010 0000 0000 NRF_P1_NS_BASE 0x400D8200
    
       // Table 9: Peripheral Address Format
       // NRF_UARTE20_NS_BASE 0x400C6000UL
       // |||                                      [31:29] Address region 2: Peripherals on APB Bus
       //    |                                     [28]    Security 0: Non-secure, 1: Secure
       //      ||||                                [27:24] Reserved Set to zero
       //           |||| ||                        [23:18] Peripheral APB bus (overlaps sub index)
       //           |||| ||                                1: APB peripherals in MCU power domain   SPU00
       //           |||| ||                                2: APB peripherals in RADIO power domain SPU10
       //           |||| ||                                3: APB peripherals in PERI power domain  SPU20
       //           |||| ||                                4: APB peripherals in LP power domain    SPU30
       //              | |||| ||||                [20:12] Peripheral Id & Interrupt Vector, assume  9-bit
       //                  || ||||                [17:12] Peripheral subordinate index
       //                  || ||||                        Used for configuring the SPU — System protection unit on page
       //                  || ||||                        209, as the index n of register SPU.PERIPH[n].PERM.
       //                          |||||||||||||| [11:0]  Peripheral address space
       // 3322 2222 2222 1111 1111 1100 0000 0000 Dec
       // 1098 7654 3210 9876 5432 1098 7654 3210
       //
       // 1111 1111 1111 1111 0000 0000 0000 0000 Hex
       // FEDC BA98 7654 3210 FEDC BA98 7654 3210
       //
       // 0100 0000 0000 1100 0110 0000 0000 0000 NRF_UARTE20_NS_BASE
    
    // NRF_P1_NS in LP power domain  SPU30
    STATIC_ASSERT( NRF_P0_NS_BASE == 0x4010A000UL, "NRF_P1_NS_BASE differs from 0x4010A000");
    STATIC_ASSERT((NRF_P0_NS_BASE & 0xE0000000UL) >> 29 ==   2, "NRF_P0_NS & 0xE0000000 should be 2");   // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_P0_NS_BASE & 0x10000000UL) >> 28 ==   0, "NRF_P0_NS & 0x10000000 should be 0");   // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_P0_NS_BASE & 0x0F000000UL) >> 24 ==   0, "NRF_P0_NS & 0x0F000000 should be 0");   // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_P0_NS_BASE & 0x00FC0000UL) >> 18 ==   4, "NRF_P0_NS & 0x00FC0000 should be 4");   // [23:18] APB Bus 4: LP power domain  SPU30
    STATIC_ASSERT((NRF_P0_NS_BASE & 0x0003F000UL) >> 12 ==  10, "NRF_P0_NS & 0x0003F000 should be 10");  // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_P0_NS_BASE & 0x001FF000UL) >> 12 == 266, "NRF_P0_NS & 0x001FF000 should be 266"); // [20:12] Peripheral Id & Interrupt Vector
    // NRF_P1_S in LP power domain  SPU30
    STATIC_ASSERT( NRF_P0_S_BASE  == 0x5010A000UL, "NRF_P1_S_BASE  differs from 0x4010A000");
    STATIC_ASSERT((NRF_P0_S_BASE  & 0xE0000000UL) >> 29 ==   2, "NRF_P0_S  & 0xE0000000 should be 2");   // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_P0_S_BASE  & 0x10000000UL) >> 28 ==   1, "NRF_P0_S  & 0x10000000 should be 1");   // [28]    Security 0: Non-secure 1: Secure
    STATIC_ASSERT((NRF_P0_S_BASE  & 0x0F000000UL) >> 24 ==   0, "NRF_P0_S  & 0x0F000000 should be 0");   // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_P0_S_BASE  & 0x00FC0000UL) >> 18 ==   4, "NRF_P0_S  & 0x00FC0000 should be 4");   // [23:18] APB Bus 4: LP power domain  SPU30
    STATIC_ASSERT((NRF_P0_S_BASE  & 0x0003F000UL) >> 12 ==  10, "NRF_P0_S  & 0x0003F000 should be 10");  // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_P0_S_BASE  & 0x001FF000UL) >> 12 == 266, "NRF_P0_S  & 0x001FF000 should be 266"); // [20:12] Peripheral Id & Interrupt Vector
    
    // NRF_P1_NS in PERI power domain SPU20
    STATIC_ASSERT( NRF_P1_NS_BASE == 0x400D8200UL, "NRF_P1_NS_BASE differs from 0x400D8200");
    STATIC_ASSERT((NRF_P1_NS_BASE & 0xE0000000UL) >> 29 ==   2, "NRF_P1_NS & 0xE0000000 should be 2");   // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_P1_NS_BASE & 0x10000000UL) >> 28 ==   0, "NRF_P1_NS & 0x10000000 should be 0");   // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_P1_NS_BASE & 0x0F000000UL) >> 24 ==   0, "NRF_P1_NS & 0x0F000000 should be 0");   // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_P1_NS_BASE & 0x00FC0000UL) >> 18 ==   3, "NRF_P1_NS & 0x00FC0000 should be 3");   // [23:18] APB Bus 3: PERI power domain SPU20
    STATIC_ASSERT((NRF_P1_NS_BASE & 0x0003F000UL) >> 12 ==  24, "NRF_P1_NS & 0x0003F000 should be 24");  // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_P1_NS_BASE & 0x001FF000UL) >> 12 == 216, "NRF_P1_NS & 0x001FF000 should be 216"); // [20:12] Peripheral Id & Interrupt Vector
    // NRF_P1_S in PERI power domain SPU20
    STATIC_ASSERT( NRF_P1_S_BASE  == 0x500D8200UL, "NRF_P1_S_BASE  differs from 0x400D8200");
    STATIC_ASSERT((NRF_P1_S_BASE  & 0xE0000000UL) >> 29 ==   2, "NRF_P1_S  & 0xE0000000 should be 2");   // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_P1_S_BASE  & 0x10000000UL) >> 28 ==   1, "NRF_P1_S  & 0x10000000 should be 1");   // [28]    Security 0: Non-secure 1: Secure
    STATIC_ASSERT((NRF_P1_S_BASE  & 0x0F000000UL) >> 24 ==   0, "NRF_P1_S  & 0x0F000000 should be 0");   // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_P1_S_BASE  & 0x00FC0000UL) >> 18 ==   3, "NRF_P1_S  & 0x00FC0000 should be 3");   // [23:18] APB Bus 3: PERI power domain SPU20
    STATIC_ASSERT((NRF_P1_S_BASE  & 0x0003F000UL) >> 12 ==  24, "NRF_P1_S  & 0x0003F000 should be 24");  // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_P1_S_BASE  & 0x001FF000UL) >> 12 == 216, "NRF_P1_S  & 0x001FF000 should be 216"); // [20:12] Peripheral Id & Interrupt Vector
    
    // NRF_P2_NS in MCU power domain SPU00
    STATIC_ASSERT( NRF_P2_NS_BASE == 0x40050400UL, "NRF_P2_NS_BASE differs from 0x40050400");
    STATIC_ASSERT((NRF_P2_NS_BASE & 0xE0000000UL) >> 29 ==  2, "NRF_P2_NS & 0xE0000000 should be 2");  // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_P2_NS_BASE & 0x10000000UL) >> 28 ==  0, "NRF_P2_NS & 0x10000000 should be 0");  // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_P2_NS_BASE & 0x0F000000UL) >> 24 ==  0, "NRF_P2_NS & 0x0F000000 should be 0");  // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_P2_NS_BASE & 0x00FC0000UL) >> 18 ==  1, "NRF_P2_NS & 0x00FC0000 should be 0");  // [23:18] APB Bus 1: MCU power domain   SPU00
    STATIC_ASSERT((NRF_P2_NS_BASE & 0x0003F000UL) >> 12 == 16, "NRF_P2_NS & 0x0003F000 should be 16"); // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_P2_NS_BASE & 0x001FF000UL) >> 12 == 80, "NRF_P2_NS & 0x001FF000 should be 80"); // [20:12] Peripheral Id & Interrupt Vector
    // NRF_P2_S in MCU power domain SPU00
    STATIC_ASSERT( NRF_P2_S_BASE  == 0x50050400UL, "NRF_P2_S_BASE  differs from 0x50050400");
    STATIC_ASSERT((NRF_P2_S_BASE  & 0xE0000000UL) >> 29 ==  2, "NRF_P2_S  & 0xE0000000 should be 2");  // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_P2_S_BASE  & 0x10000000UL) >> 28 ==  1, "NRF_P2_S  & 0x10000000 should be 1");  // [28]    Security 0: Non-secure 1: Secure
    STATIC_ASSERT((NRF_P2_S_BASE  & 0x0F000000UL) >> 24 ==  0, "NRF_P2_S  & 0x0F000000 should be 0");  // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_P2_S_BASE  & 0x00FC0000UL) >> 18 ==  1, "NRF_P2_S  & 0x00FC0000 should be 0");  // [23:18] APB Bus 1: MCU power domain   SPU00
    STATIC_ASSERT((NRF_P2_S_BASE  & 0x0003F000UL) >> 12 == 16, "NRF_P2_S  & 0x0003F000 should be 16"); // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_P2_S_BASE  & 0x001FF000UL) >> 12 == 80, "NRF_P2_S  & 0x001FF000 should be 80"); // [20:12] Peripheral Id & Interrupt Vector
    
    // UARTE00_NS in MCU power domain SPU00
    STATIC_ASSERT( NRF_UARTE00_NS_BASE == 0x4004A000UL, "NRF_UARTE00_NS_BASE differs from 0x4004A000");
    STATIC_ASSERT((NRF_UARTE00_NS_BASE & 0xE0000000UL) >> 29 ==   2, "NRF_UARTE00_NS & 0xE0000000 should be 2");  // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_UARTE00_NS_BASE & 0x10000000UL) >> 28 ==   0, "NRF_UARTE00_NS & 0x10000000 should be 0");  // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_UARTE00_NS_BASE & 0x0F000000UL) >> 24 ==   0, "NRF_UARTE00_NS & 0x0F000000 should be 0");  // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_UARTE00_NS_BASE & 0x00FC0000UL) >> 18 ==   1, "NRF_UARTE00_NS & 0x00FC0000 should be 1");  // [23:18] APB Bus 1: MCU power domain   SPU00
    STATIC_ASSERT((NRF_UARTE00_NS_BASE & 0x0003F000UL) >> 12 ==  10, "NRF_UARTE00_NS & 0x0003F000 should be 10"); // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_UARTE00_NS_BASE & 0x001FF000UL) >> 12 ==  74, "NRF_UARTE00_NS & 0x001FF000 should be 74"); // [20:12] Peripheral Id & Interrupt Vector
    // UARTE00_S in MCU power domain SPU00
    STATIC_ASSERT( NRF_UARTE00_S_BASE  == 0x5004A000UL, "NRF_UARTE00_S_BASE  differs from 0x5004A000");
    STATIC_ASSERT((NRF_UARTE00_S_BASE  & 0xE0000000UL) >> 29 ==   2, "NRF_UARTE00_S  & 0xE0000000 should be 2");  // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_UARTE00_S_BASE  & 0x10000000UL) >> 28 ==   1, "NRF_UARTE00_S  & 0x10000000 should be 1");  // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_UARTE00_S_BASE  & 0x0F000000UL) >> 24 ==   0, "NRF_UARTE00_S  & 0x0F000000 should be 0");  // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_UARTE00_S_BASE  & 0x00FC0000UL) >> 18 ==   1, "NRF_UARTE00_S  & 0x00FC0000 should be 1");  // [23:18] APB Bus 1: MCU power domain   SPU00
    STATIC_ASSERT((NRF_UARTE00_S_BASE  & 0x0003F000UL) >> 12 ==  10, "NRF_UARTE00_S  & 0x0003F000 should be 10"); // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_UARTE00_S_BASE  & 0x001FF000UL) >> 12 ==  74, "NRF_UARTE00_S  & 0x001FF000 should be 74"); // [20:12] Peripheral Id & Interrupt Vector
    
    // UARTE20_NS in PERI power domain SPU20
    STATIC_ASSERT(NRF_UARTE20_NS_BASE == 0x400C6000UL, "NRF_UARTE20_NS_BASE differs from 0x400C6000");
    STATIC_ASSERT((NRF_UARTE20_NS_BASE & 0xE0000000UL) >> 29 ==   2, "NRF_UARTE20_NS & 0xE0000000 should be 2");   // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_UARTE20_NS_BASE & 0x10000000UL) >> 28 ==   0, "NRF_UARTE20_NS & 0x10000000 should be 0");   // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_UARTE20_NS_BASE & 0x0F000000UL) >> 24 ==   0, "NRF_UARTE20_NS & 0x0F000000 should be 0");   // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_UARTE20_NS_BASE & 0x00FC0000UL) >> 18 ==   3, "NRF_UARTE20_NS & 0x00FC0000 should be 3");   // [23:18] APB bus 3: PERI power domain SPU20
    STATIC_ASSERT((NRF_UARTE20_NS_BASE & 0x0003F000UL) >> 12 ==   6, "NRF_UARTE20_NS & 0x0003F000 should be 6");   // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_UARTE20_NS_BASE & 0x001FF000UL) >> 12 == 198, "NRF_UARTE20_NS & 0x001FF000 should be 198"); // [20:12] Peripheral Id & Interrupt Vector
    // UARTE20_S in PERI power domain SPU20
    STATIC_ASSERT(NRF_UARTE20_S_BASE  == 0x500C6000UL, "NRF_UARTE20_S_BASE  differs from 0x500C6000");
    STATIC_ASSERT((NRF_UARTE20_S_BASE  & 0xE0000000UL) >> 29 ==   2, "NRF_UARTE20_S  & 0xE0000000 should be 2");   // [31:29] Address region 2: Peripherals
    STATIC_ASSERT((NRF_UARTE20_S_BASE  & 0x10000000UL) >> 28 ==   1, "NRF_UARTE20_S  & 0x10000000 should be 1");   // [28]    Security 0: Non-secure, 1: Secure
    STATIC_ASSERT((NRF_UARTE20_S_BASE  & 0x0F000000UL) >> 24 ==   0, "NRF_UARTE20_S  & 0x0F000000 should be 0");   // [27:24] Reserved Set to zero
    STATIC_ASSERT((NRF_UARTE20_S_BASE  & 0x00FC0000UL) >> 18 ==   3, "NRF_UARTE20_S  & 0x00FC0000 should be 3");   // [23:18] APB bus 3: PERI power domain SPU20
    STATIC_ASSERT((NRF_UARTE20_S_BASE  & 0x0003F000UL) >> 12 ==   6, "NRF_UARTE20_S  & 0x0003F000 should be 6");   // [17:12] Peripheral subordinate index
    STATIC_ASSERT((NRF_UARTE20_S_BASE  & 0x001FF000UL) >> 12 == 198, "NRF_UARTE20_S  & 0x001FF000 should be 198"); // [20:12] Peripheral Id & Interrupt Vector
    
    // The peripheral "Id" column in the table maps to the range 0-63 in each of 5 x NRF_SPUx0S (so 0-5x64-1) and so is 6-bit.
    // The Product Specification states "A peripheral can occupy single or multiple interrupts. For single interrupts, the
    // interrupt number follows the peripheral ID. For example, the peripheral with ID=4 is connected to interrupt number 4
    // in the nested vectored interrupt controller (NVIC)" which I now see are spread across SPU00_S to SPU_30_S
    // See Fig.1 Block Diagram
    // SPU00 Supports FEATURE.GPIO[n]  GPIO P2 and x00 UARTE00 is 74-64   = SPU00 Index 10
    // SPU10 Supports                  RADIO   and x10
    // SPU20 Supports FEATURE.GPIO[n]  GPIO P1 and x20 UARTE20 is 198-192 = SPU20 Index 6
    // SPU30 Supports FEATURE.GPIO[n]  GPIO P0 and x30 UARTE30 is 260-256 = SPU30 Index 4
    NRF_SPU_Type * const NRF_SPU_List[] = {
       NRF_SPU00_S,                //  Dummy, APB bus index is 1-4 not 0-3; maybe Index 0 is system   0-63
       NRF_SPU00_S,                //  0x50040000UL SPU00 Supports FEATURE.GPIO[n]  GPIO P2 and x00  64-127
       NRF_SPU10_S,                //  0x50080000UL SPU10 Supports                  RADIO   and x10 128-191
       NRF_SPU20_S,                //  0x500C0000UL SPU20 Supports FEATURE.GPIO[n]  GPIO P1 and x20 192-255
       NRF_SPU30_S                 //  0x50100000UL SPU30 Supports FEATURE.GPIO[n]  GPIO P0 and x30 256-319
    };
    
          uint32_t APB_Bus = 3;
          // Get the address to the associated peripheral's SPU instance
          NRF_SPU_Type *pSPU = NRF_SPU_List[APB_Bus];
    
          // LED_GREEN_PIN_0  MAP(2,  9) // ..   P2.09
          // LED_GREEN_PIN_1  MAP(1, 10) // ..   P1.10
          // LED_GREEN_PIN_2  MAP(2, 07) // ..   P2.07
          // LED_GREEN_PIN_3  MAP(1, 14) // ..   P1.14
          // Ensure Feature is available for non-secure usage
          if (mPeripherals[i].SourceSpec == NRF_P0_NS_BASE)
          {
             // Uart pins
          }
          else if (mPeripherals[i].SourceSpec == NRF_P1_NS_BASE)
          {
             pSPU->FEATURE.GPIO[PORT_VAL(LED_GREEN_PIN_1)].PIN[PIN_VAL(LED_GREEN_PIN_1)] = 0;
             pSPU->FEATURE.GPIO[PORT_VAL(LED_GREEN_PIN_3)].PIN[PIN_VAL(LED_GREEN_PIN_3)] = 0;
          }
          else if (mPeripherals[i].SourceSpec == NRF_P2_NS_BASE)
          {
             pSPU->FEATURE.GPIO[PORT_VAL(LED_GREEN_PIN_0)].PIN[PIN_VAL(LED_GREEN_PIN_0)] = 0;
             pSPU->FEATURE.GPIO[PORT_VAL(LED_GREEN_PIN_2)].PIN[PIN_VAL(LED_GREEN_PIN_2)] = 0;
          }
          else if (mPeripherals[i].SourceSpec == NRF_UARTE20_S_BASE)
          {
             // Uart pins
             pSPU->FEATURE.GPIO[PORT_VAL(TX_PIN_NUMBER)].PIN[PIN_VAL(TX_PIN_NUMBER)] = 0;
             pSPU->FEATURE.GPIO[PORT_VAL(RX_PIN_NUMBER)].PIN[PIN_VAL(RX_PIN_NUMBER)] = 0;
          }

    After that the port io and serial works as expected:

       // Configuration                Direction                Input                          Pullup                 Drive Level        Sense Level
       // ===========================  =======================  =============================  =====================  =================  ====================
       nrf_gpio_cfg(LED_GREEN_PIN_0,   NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL,   NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
       nrf_gpio_cfg(LED_GREEN_PIN_1,   NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL,   NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
       nrf_gpio_cfg(LED_GREEN_PIN_2,   NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL,   NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
       nrf_gpio_cfg(LED_GREEN_PIN_3,   NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL,   NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
    
       while (1) {
          if (ToggleLEDs)
          {
             nrf_gpio_pin_set(LED_GREEN_PIN_0);     // LED_GREEN_PIN_0  MAP(2,  9) // ..   P2.09
             nrf_gpio_pin_set(LED_GREEN_PIN_1);     // LED_GREEN_PIN_1  MAP(1, 10) // ..   P1.10
             nrf_gpio_pin_clear(LED_GREEN_PIN_2);   // LED_GREEN_PIN_2  MAP(2, 07) // ..   P2.07
             nrf_gpio_pin_clear(LED_GREEN_PIN_3);   // LED_GREEN_PIN_3  MAP(1, 14) // ..   P1.14
          }
          else
          {
             nrf_gpio_pin_clear(LED_GREEN_PIN_0);   // LED_GREEN_PIN_0  MAP(2,  9) // ..   P2.09
             nrf_gpio_pin_clear(LED_GREEN_PIN_1);   // LED_GREEN_PIN_1  MAP(1, 10) // ..   P1.10
             nrf_gpio_pin_set(LED_GREEN_PIN_2);     // LED_GREEN_PIN_2  MAP(2, 07) // ..   P2.07
             nrf_gpio_pin_set(LED_GREEN_PIN_3);     // LED_GREEN_PIN_3  MAP(1, 14) // ..   P1.14
          }
          ToggleLEDs = !ToggleLEDs;
          for (volatile uint32_t i=0; i<1000000; i++) ;
          ReportBuildId();
       }

Related