NCS nRF91: using PRS after mcuboot used SPI

Hi,

we are using an nRF9160 on a custom board with NCS 1.8.0. I have been able to reproduce the following behaviour with a nRF9160 DK 1.0 and NCS 1.9.1

For our application, we need mcuboot to have its secondary on an external SPI flash. We use SPI3 for that and of course configure it for mcuboot in its device tree.

In our main application, we need 3 UARTs (we use UART0,1,2) and on the "3" block, we need to use SPI and I2C "simultaneously" using PRS with the nrfx drivers. Of course that SPI3 and I2C3 are not running at the same time, but they get initialized, used and deinitialized consecutively. just one time it's a spim3 and one time it's a twim3.

But some strange problems start to occur, when using the function block 3 slightly different. 

If you init the spim/twim as "blocking", i.e. without a callback function for events, and initialize, transfer and deinitialize consecutively, everything seems to work fine. 

But when I want to use a callback function, I get a fault at runtime. 

void main(void)
{
  printk("Hello World ! %s\n", CONFIG_BOARD);

  eErr = nrfx_spim_init(&sSpimInstance, &sDevCfgSpim, NULL, NULL);
  eErr = nrfx_spim_xfer(&sSpimInstance, &sSpiRxTxData, 0); /* xfer necessary to get crash */
  nrfx_spim_uninit(&sSpimInstance);

  eErr = nrfx_twim_init(&sTwimInstance, &sDevCfg, Main_EvtHandler, &sTwimInstance); /* crash */
  nrfx_twim_enable(&sTwimInstance);  
  nrfx_twim_uninit(&sTwimInstance);
}

I always seem to crash at this function it looks like: __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn),that wants to enable the interrupt for that function block for the callback.

I only seem to get these crashes when I use SPI3 also for the mcuboot flash access. For the MCUBOOT I obviously have the SPI3 "activated" in the device tree, while in my main application, i have it disabled in the device tree. My guess is, that MCUBOOT marks something somewhere, that the regular application cannot unmark or something, when just using nrfx drivers and not devicetree-zephyr-stuff.

When the Function block is used to do one thing, the other seems not to work anymore. Likewise I get a crash when using certain functions "between" the xfer and the deinit like so:

void main(void)
{
  printk("Hello World ! %s\n", CONFIG_BOARD);

  eErr = nrfx_spim_init(&sSpimInstance, &sDevCfgSpim, Main_TestEvtHandlerSpi, NULL);
  eErr = nrfx_spim_xfer(&sSpimInstance, &sSpiRxTxData, 0);
  k_sem_take(&sMain_Sem, K_MSEC(500)); /* crash */
  nrfx_spim_uninit(&sSpimInstance);
}

This does not seem to be related to the SPI3 being used by MCUBOOT, but it's frustrating nonetheless.

I have attached a project for the DK that reproduces the fault. 

It would be interesting to see, if there's a way to make this work, since ti is crucial to our project.


1033.hello_world_twim.zip

  • After fixing the first issue a new popped up:

    I: MX25R64: SFDP v 1.6 AP ff with 3 PH
    I: PH0: ff00 rev 1.6: 16 DW @ 30
    I: MX25R64: 8 MiBy flash
    I: PH1: ffc2 rev 1.0: 4 DW @ 110
    *** Booting Zephyr OS build v2.7.99-ncs1-1  ***
    I: Starting bootloader
    I: Swap type: none
    E: Unable to find bootable image

    Do you not get this?

    I can see that it fails to validate the primary slot, since both of these statements evaluates to true. Do you know why it fails here, since you don't see it on your side?

    It is probably something obvious. I will continue to investigate this tomorrow, so I can reproduce the issue you see.

    Best regards,

    Simon

  • Hi, sorry for taking so long to reply.
    1. yes, I am using the nRF9160dk_nrf9160_ns.

    2. your problem is most likely due to this:  Invalid private key with ed25519 

    I have changed this in my SDK installation, so of course it works. so It's my bad.

    In my sample project you just need to change signature type to RSA instead of ED25519 in nRF_mcuboot.conf. That should fix it.

  • I'm able to reproduce your issue and will look into it today/Monday

  • Try the following main.c:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <sys/printk.h>
    #include <string.h>
    #include <nrfx_twim.h>
    #include <nrfx_spim.h>
    #include <drivers/src/prs/nrfx_prs.h>
    
    nrfx_twim_t sTwimInstance = NRFX_TWIM_INSTANCE(3);
    nrfx_spim_t sSpimInstance = NRFX_SPIM_INSTANCE(3);
    volatile nrfx_err_t eErr;
    
    nrfx_twim_config_t sDevCfg = 
    {
      .scl = 6,                
      .sda = 5,                
      .frequency = NRF_TWIM_FREQ_400K,          
      .interrupt_priority = 7, 
      .hold_bus_uninit = false 
    };
    
    nrfx_spim_config_t sDevCfgSpim = 
    {
      .sck_pin        = 7,
      .mosi_pin       = 8,
      .miso_pin       = 9,
      .ss_pin         = NRFX_SPIM_PIN_NOT_USED,
      .ss_active_high = false,
      .irq_priority   = 7,
      .orc            = 0xFF,
      .frequency      = NRF_SPIM_FREQ_8M,
      .mode           = NRF_SPIM_MODE_0,
      .bit_order      = NRF_SPIM_BIT_ORDER_MSB_FIRST,
      .miso_pull      = NRF_GPIO_PIN_PULLUP,
    };
    
    uint8_t au8Data[16];
    
    nrfx_spim_xfer_desc_t sSpiRxTxData = 
    {
      .p_tx_buffer = au8Data,
      .tx_length   = 4,
      .p_rx_buffer = au8Data,
      .rx_length   = 4
    };
    
    nrfx_twim_evt_t sTestEvent;
    nrfx_spim_evt_t sTestEventSpi;
    
    K_SEM_DEFINE(sMain_Sem, 0, 1);
    
    static void Main_EvtHandler(const nrfx_twim_evt_t* psEvent, void* pContext)
    {
      memcpy(&sTestEvent, psEvent, sizeof(nrfx_twim_evt_t));
      k_sem_give(&sMain_Sem);
    }
    
    static void Main_TestEvtHandlerSpi(const nrfx_spim_evt_t* psEvent, void* pContext)
    {
      memcpy(&sTestEventSpi, psEvent, sizeof(nrfx_spim_evt_t));
      k_sem_give(&sMain_Sem);
    }
    
    static void spim_handler(const nrfx_spim_evt_t *p_event, void *p_context)
    {
    	printk("spim_handler running\n");
    }
    
    
    void main(void)
    {
    	printk("hello world twim ! %s\n", CONFIG_BOARD);
    
    #if 1 /* error case 1 */
      IRQ_CONNECT(DT_IRQN(DT_NODELABEL(i2c3)),
    		    DT_IRQ(DT_NODELABEL(i2c3), priority),
    		    nrfx_isr, nrfx_prs_box_3_irq_handler, 0);
    
      eErr = nrfx_spim_init(&sSpimInstance, &sDevCfgSpim, spim_handler, NULL);
      eErr = nrfx_spim_xfer(&sSpimInstance, &sSpiRxTxData, 0); /* xfer necessary to get crash */
      nrfx_spim_uninit(&sSpimInstance);
    
      eErr = nrfx_twim_init(&sTwimInstance, &sDevCfg, Main_EvtHandler, &sTwimInstance); /* crash */
      nrfx_twim_enable(&sTwimInstance);  
      nrfx_twim_uninit(&sTwimInstance);
      printk("Goes here");
    #else /* error case 2 */
    
      eErr = nrfx_spim_init(&sSpimInstance, &sDevCfgSpim, Main_TestEvtHandlerSpi, NULL);
      eErr = nrfx_spim_xfer(&sSpimInstance, &sSpiRxTxData, 0);
      k_sem_take(&sMain_Sem, K_MSEC(500)); /* crash */
      nrfx_spim_uninit(&sSpimInstance);
    
    #endif
    }
    

    With that I was able to go past nrfx_twim_init() without the program crashing.

Related