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

Parents Reply
  • Ah, I figured out why it failed for me. After enabling log I saw the following:

    E: SFDP magic 00000000 invalid

    Which comes from the spi_nor driver and means that I'm not able to communicate with external flash

    That is why it failed in boot_read_image_headers(), since it tried to acces the image in the external flash. The reason it failed was because but I hadn't programmed the 52840 properly, the 52840 works as a board controller and will connect the external flash to the 9160.

    After programming the nrf9160dk_nrf52840 with connect_ext_flash_to_9160 I no longer had this issue. Now I will look into your issue.

    Best regards,

    Simon

Children
  • 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

  • This reply was deleted.
  • 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