adding Softdevice BLE (S140) with GPIO attached coprocessor to project without softdevice. hardfault calling existing code after Softdevice active

I am extending one of Qorvo's UWB platforms.. adding Softdevice BLE functions..  (which work ok) (this is on sdk 17_1_0)


the coprocessor uses a GPIO connected signaling mechanism,  using interrupts..

calling the existing code after BLE is active causes a hardfault.. 

this is running freetos,  we are in a freetos task. 

I've debugged (using ozone) it to  attempting to setup the interrupt handler for the GPIO pins. 

the existing code calls the nrfx libs 

       return qgpio_pin_irq_configure(&qm33_irq, QGPIO_IRQ_DISABLED);  //according to the doc, a gpio interrupt disable shouldn't impact softdevice.. 

```

enum qerr qgpio_pin_irq_configure(const struct qgpio *qgpio_pin, uint32_t flags)
{
nrfx_err_t r;
enum qerr err;
struct qgpio_cb_data *cb_data;
nrfx_gpiote_in_config_t trigger_config;
uint32_t abs_pin = NRF_GPIO_PIN_MAP(qgpio_pin->port, qgpio_pin->pin_number);  // this sets abs_pin = 25 

/* Init GPIOTE at least once. */
if (!nrfx_gpiote_is_init()) {   // this causes the hardfault.   
   r = nrfx_gpiote_init();
   if (r)
   return QERR_EBUSY;
}

if (flags & QGPIO_IRQ_DISABLED) {
   nrfx_gpiote_in_event_disable(abs_pin);
   nrfx_gpiote_in_uninit(abs_pin);
   return QERR_SUCCESS;
}
```
hardfault window
```
The target stopped in HardFault exception state.

Reason: A fault with configurable priority has been escalated to a HardFault exception at 0x00000000.
```

I don't see any mechanism to cause hardfault on a GPIO pin  with SD active. 
if SD is not active this code works as written 

what am I missing

if I run this code BEFORE setup of softdevice, it works, but softdevice init fails. 

Parents
  • Hi Sam, 

    You mentioned earlier "if I comment out the 198 anomaly test it hardfaults in the nrfx_spim, irq_handler," 
    Could you explain what has been changed ? 
    My understanding now is that you have it working both BLE and SPIM3 ? 


    Is there any option to use other SPIM instead of SPIM3 ? So that we can avoid errata 198. Please find this note in the SDK's release note (Known issue): 
    - The workaround for Anomaly 198 for nRF52840 SPIM3 peripheral
    that has been implemented in nrfx_spim cannot be used with a SoftDevice.
    Flag NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED must be set to zero.
    The workaround based on a dedicated RAM block for SPIM3 must be used instead.

    If SPIM3 is a must, then you will have to use the solution to use dedicated RAM block for SPIM3. 

    One my coworkers have made an example a few years back. I attached the project (SDK v17.1.0) and the instruction here: 
    =========
    ble_app_beacon_spim.zip

    Look at the flash placement file:

    To see how this reserves one RAM block for the SPI, and then in main.c how it allocates the spim buffer to be within this block. 

    Then you should use this buffer for your SPI when you initialize it. The softdevice will not touch the allocated ram block.

    Give it a go, and let me know how it works in your application. Please note that you can see where this RAM block ends up (this is dynamic). If the application grows too big, then it will go into ram block 8, and things may start to get messy with the callstack and so on. You should see this after compiling:

  • ok, I am now at the spot where I think I have to implement this..  the buffer and link time placement is easy..

    usage is not so much

    they are using

     

    #if NRFX_SPIM_ENABLED
    		nrf_spim_enable(spi->type.spim.p_reg);
    
    		const nrfx_spim_xfer_desc_t xfer_desc = { xfer->tx_buf, xfer->tx_size, xfer->rx_buf,
    							  xfer->rx_size };
    		result = nrfx_spim_xfer(&spi->type.spim, &xfer_desc, xfer->flags);
    #else
    


    I don't find any doc on this.(nrfx_spim_xfer) . my assumption is this could be write then read, (depending on flags)
    so I set the spim_buffer I created as write from, and copy the write data there, set the read buffer same place, and copy the read data from there to the address specified by caller

Reply
  • ok, I am now at the spot where I think I have to implement this..  the buffer and link time placement is easy..

    usage is not so much

    they are using

     

    #if NRFX_SPIM_ENABLED
    		nrf_spim_enable(spi->type.spim.p_reg);
    
    		const nrfx_spim_xfer_desc_t xfer_desc = { xfer->tx_buf, xfer->tx_size, xfer->rx_buf,
    							  xfer->rx_size };
    		result = nrfx_spim_xfer(&spi->type.spim, &xfer_desc, xfer->flags);
    #else
    


    I don't find any doc on this.(nrfx_spim_xfer) . my assumption is this could be write then read, (depending on flags)
    so I set the spim_buffer I created as write from, and copy the write data there, set the read buffer same place, and copy the read data from there to the address specified by caller

Children
  • Hi Sam, 
    I haven't looked deep into the function but you can find the documentation in nrfx_spim.h file in \modules\nrfx\drivers\include in our SDK. The source code is in src\nrfx_spim.c . 

    My understanding is that the function will do both reading and writing at the same time as SPI can do full duplex. 

  • Thanks. I ran into another problem I thought might be SPIM3. And tried to implement the sw workaround. 
    Defining the buffer and pinning it to some place in the binary was easy, but there was no sample on exploiting the pinned buffer. Do you hook transfer and put send in the top half of the 8k buffer  and receive in the bottom half?

    the problem I thought might be SPIM3 turned out to be an app bug writing over the end of its heap buffer and corrupting other control blocks. 

  • Hi Sam, 
    Since it's not directly related to the original question, please create a new ticket. Please give more detail about the buffer you are using. Are you talking about EasyDMA buffer ? 

  • I am talking about the post you made in January 12, above,,which introduced the SPIM3 workaround (no way to reference a post here)


    the code example (you provided)  defines the buffer and places it via the ld file, but doesn't REFERENCE the buffer in the actual SPIM operations..  you comment in the referenced post 

    >Then you should use this buffer for your SPI when you initialize it.
    but the example doesn't

  • Hi Sam, 
    Oh sorry, it's been a few months :) 
    I had a quick look at the code. You are right that the code doesn't use SPIM. It simply show how to define a dedicated RAM area for SPIM operation. 
    But you can see this assigning at line 288 in main.c: 
    __attribute__((section(".spim_buffer"))) static uint32_t m_spim_buffer[0x2000];


    This buffer is what you should use when you call nrfx_spim_xfer(). The xfer_desc argument in that function contain the pointers to the tx and rx buffer. 

Related