<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>MPSL assert during MCUmgr image erase</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/110460/mpsl-assert-during-mcumgr-image-erase</link><description>In my project I use MPSL for a combination of BLE, ESB and flash sync. The BLE/ESB timeslot handling was implemented following this example: https://github.com/too1/ncs-esb-ble-mpsl-demo During normal operation it is running perfectly fine (so far). However</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 16 May 2024 19:49:12 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/110460/mpsl-assert-during-mcumgr-image-erase" /><item><title>RE: MPSL assert during MCUmgr image erase</title><link>https://devzone.nordicsemi.com/thread/484779?ContentTypeID=1</link><pubDate>Thu, 16 May 2024 19:49:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:09d60244-dd6f-4f55-8c9a-835cda709476</guid><dc:creator>rsteijn</dc:creator><description>&lt;p&gt;I have changed it to schedule calls to mpsl_timeslot_session_open() and mpsl_timeslot_request() from the system workqueue (which is a non-preemptible thread) and it has solved the MPSL assert issue. I tested it by uploading and then erasing an image using mcumgr-web about 20 times, and no crashes happened. Without help of the system workqueue, the crash instantly happens.&lt;/p&gt;
&lt;p&gt;I will mark this as resolved, thanks!&lt;br /&gt;&lt;br /&gt;One more thing though (which may or may not be related to this), one time when doing the &amp;quot;erase&amp;quot; command on slot 1 from mcumgr-web, and mcumgr-web was trying to reconnect to the device, i got the following hardfault:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;[00:05:57.548,004] &amp;lt;inf&amp;gt; mcuboot_util: Image index: 0, Swap type: none
[00:06:07.358,276] &amp;lt;inf&amp;gt; mcuboot_util: Image index: 0, Swap type: none
[00:06:12.778,442] &amp;lt;err&amp;gt; bt_conn: not connected!
[00:06:12.778,808] &amp;lt;inf&amp;gt; bas: BAS Notifications disabled
[00:06:12.780,700] &amp;lt;inf&amp;gt; network: BLE Disconnect!
[00:06:12.780,731] &amp;lt;inf&amp;gt; thread_event_reg: BroadcastMessage = kBleConnectionEvent
[00:06:15.850,006] &amp;lt;err&amp;gt; os: ***** BUS FAULT *****
[00:06:15.850,036] &amp;lt;err&amp;gt; os:   Imprecise data bus error
[00:06:15.850,097] &amp;lt;err&amp;gt; os: r0/a1:  0x0114043e  r1/a2:  0x200081eb  r2/a3:  0x00000006
[00:06:15.850,128] &amp;lt;err&amp;gt; os: r3/a4:  0x0114043f r12/ip:  0x00000003 r14/lr:  0x00011c57
[00:06:15.850,158] &amp;lt;err&amp;gt; os:  xpsr:  0x21000000
[00:06:15.850,219] &amp;lt;err&amp;gt; os: s[ 0]:  0x00000000  s[ 1]:  0x00000000  s[ 2]:  0x20015af4  s[ 3]:  0x20007d28
[00:06:15.850,280] &amp;lt;err&amp;gt; os: s[ 4]:  0x00000848  s[ 5]:  0x000000ff  s[ 6]:  0x00000000  s[ 7]:  0x0001a91f
[00:06:15.850,341] &amp;lt;err&amp;gt; os: s[ 8]:  0x01005ae8  s[ 9]:  0x20001d01  s[10]:  0x20007d28  s[11]:  0x001b0001
[00:06:15.850,402] &amp;lt;err&amp;gt; os: s[12]:  0x001b0848  s[13]:  0x00010848  s[14]:  0x00000001  s[15]:  0x200017fc
[00:06:15.850,402] &amp;lt;err&amp;gt; os: fpscr:  0x20001d9c
[00:06:15.850,463] &amp;lt;err&amp;gt; os: Faulting instruction address (r15/pc): 0x00018a80
[00:06:15.850,494] &amp;lt;err&amp;gt; os: &amp;gt;&amp;gt;&amp;gt; ZEPHYR FATAL ERROR 26: Unknown error on CPU 0
[00:06:16.288,940] &amp;lt;err&amp;gt; os: Halting system&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Where doing addr2line on 0x00011c57 returned: &lt;br /&gt;&lt;br /&gt;0x00011c57&lt;br /&gt;libsoftdevice_controller_s112_debug_hardfp__obfuscated.elf:?&lt;br /&gt;&lt;br /&gt;To me it seemed like a Bluetooth issue, and then especially related to the host device, since it had trouble connecting to the board in the first place, and also the following in the logs seems suspicious:&lt;br /&gt;&lt;br /&gt;bt_conn: not connected!&lt;br /&gt;&lt;br /&gt;Switched to a laptop with a proper functioning Bluetooth chip, and i did not see this error again.&lt;br /&gt;&lt;br /&gt;Just wanted to mention it just in case, if it ever happens to a user it would be nice to handle it properly&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: MPSL assert during MCUmgr image erase</title><link>https://devzone.nordicsemi.com/thread/480135?ContentTypeID=1</link><pubDate>Tue, 23 Apr 2024 08:34:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:92fad422-d725-4963-b121-86bfa8d782aa</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;I see. Then I can confirm that the assert is because you of an action other than NONE in the handling of a&amp;nbsp;MPSL_TIMESLOT_SIGNAL_CANCELLED event. Defering the call to&amp;nbsp;mpsl_timeslot_request() with the help of the system workqueue as you suggest should resolve this.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: MPSL assert during MCUmgr image erase</title><link>https://devzone.nordicsemi.com/thread/480025?ContentTypeID=1</link><pubDate>Mon, 22 Apr 2024 13:54:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7f21cad2-0cc2-4fac-9e8e-09e95771de45</guid><dc:creator>rsteijn</dc:creator><description>&lt;p&gt;Thanks for your reply!&lt;br /&gt;&lt;br /&gt;This was using NCS version 2.6.0, but i got the same using 2.5.1.&lt;br /&gt;&lt;br /&gt;Here are the relevant parts of my timeslot handler, where I do call mpsl_timeslot_request() upon receiving the MPSL_TIMESLOT_SIGNAL_CANCELLED event;&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;extern &amp;quot;C&amp;quot; void RADIO_IRQHandler(void);

mpsl_timeslot_request_t esb_timeslot_request{
    .request_type = MPSL_TIMESLOT_REQ_TYPE_EARLIEST,
    .params{
        .earliest{
            .hfclk = MPSL_TIMESLOT_HFCLK_CFG_NO_GUARANTEE,
            .priority = MPSL_TIMESLOT_PRIORITY_NORMAL,
            .length_us = kTimeslotLengthUs,
            .timeout_us = kTimeslotReqTimeoutUs,
        },
    },
};

mpsl_timeslot_signal_return_param_t* MyClass::TimeslotEventHandler(uint8_t session_id, uint32_t signal) {
  static bool timeslot_extenstion_failed = false;

  auto&amp;amp; inst = MyClass::GetInstance();
  inst.timeslot_action_.callback_action = MPSL_TIMESLOT_SIGNAL_ACTION_NONE;

  switch (signal) {
    case MPSL_TIMESLOT_SIGNAL_START: {
      timeslot_extenstion_failed = false;

      NVIC_ClearPendingIRQ(RADIO_IRQn);
      NRF_RADIO-&amp;gt;POWER = RADIO_POWER_POWER_Disabled &amp;lt;&amp;lt; RADIO_POWER_POWER_Pos;
      NRF_RADIO-&amp;gt;POWER = RADIO_POWER_POWER_Enabled &amp;lt;&amp;lt; RADIO_POWER_POWER_Pos;
      NVIC_ClearPendingIRQ(RADIO_IRQn);

      nrf_timer_bit_width_set(NRF_TIMER0, NRF_TIMER_BIT_WIDTH_32);
      nrf_timer_cc_set(NRF_TIMER0, NRF_TIMER_CC_CHANNEL0, kTimerExpiryUsEarly);
      nrf_timer_cc_set(NRF_TIMER0, NRF_TIMER_CC_CHANNEL1, kTimerExpiryUsReq);

      nrf_timer_int_enable(NRF_TIMER0, NRF_TIMER_INT_COMPARE0_MASK);
      nrf_timer_int_enable(NRF_TIMER0, NRF_TIMER_INT_COMPARE1_MASK);

      inst.SetTimeslotActive(true);
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_TIMER0: {
      if (nrf_timer_event_check(NRF_TIMER0, NRF_TIMER_EVENT_COMPARE0)) {
        nrf_timer_int_disable(NRF_TIMER0, NRF_TIMER_INT_COMPARE0_MASK);
        nrf_timer_event_clear(NRF_TIMER0, NRF_TIMER_EVENT_COMPARE0);

        inst.timeslot_action_.callback_action = MPSL_TIMESLOT_SIGNAL_ACTION_EXTEND;
        inst.timeslot_action_.params.extend.length_us = kTimeslotLengthUs;
      } else if (nrf_timer_event_check(NRF_TIMER0, NRF_TIMER_EVENT_COMPARE1)) {
        nrf_timer_int_disable(NRF_TIMER0, NRF_TIMER_INT_COMPARE1_MASK);
        nrf_timer_event_clear(NRF_TIMER0, NRF_TIMER_EVENT_COMPARE1);

        if (timeslot_extenstion_failed) {
          inst.timeslot_action_.callback_action = MPSL_TIMESLOT_SIGNAL_ACTION_REQUEST;
          inst.timeslot_action_.params.request.p_next = &amp;amp;esb_timeslot_request;
        }
      }
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_EXTEND_SUCCEEDED: {
      // next trigger time is current + timer expiry early
      uint32_t current_cc = nrf_timer_cc_get(NRF_TIMER0, NRF_TIMER_CC_CHANNEL0);
      nrf_timer_bit_width_set(NRF_TIMER0, NRF_TIMER_BIT_WIDTH_32);
      nrf_timer_cc_set(NRF_TIMER0, NRF_TIMER_CC_CHANNEL0, (current_cc + kTimeslotLengthUs));
      nrf_timer_int_enable(NRF_TIMER0, NRF_TIMER_INT_COMPARE0_MASK);

      current_cc = nrf_timer_cc_get(NRF_TIMER0, NRF_TIMER_CC_CHANNEL1);
      nrf_timer_bit_width_set(NRF_TIMER0, NRF_TIMER_BIT_WIDTH_32);
      nrf_timer_cc_set(NRF_TIMER0, NRF_TIMER_CC_CHANNEL1, (current_cc + kTimeslotLengthUs));
      nrf_timer_int_enable(NRF_TIMER0, NRF_TIMER_INT_COMPARE1_MASK);
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_EXTEND_FAILED: {
      timeslot_extenstion_failed = true;
      inst.SetTimeslotActive(false);
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_RADIO: {
      // radio signal received, manually call RADIO IRQ / disable IRQ
      if (inst.timeslot_active_) {
        RADIO_IRQHandler();
      } else {
        NVIC_ClearPendingIRQ(RADIO_IRQn);
        NVIC_DisableIRQ(RADIO_IRQn);
      }
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_CANCELLED:  // [[fallthrough]];
    case MPSL_TIMESLOT_SIGNAL_BLOCKED: {
      inst.SetTimeslotActive(false);
      mpsl_timeslot_request(session_id, &amp;amp;esb_timeslot_request);
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_OVERSTAYED:  // [[fallthrough]];
    case MPSL_TIMESLOT_SIGNAL_INVALID_RETURN: {
      inst.timeslot_action_.callback_action = MPSL_TIMESLOT_SIGNAL_ACTION_END;
      inst.SetTimeslotActive(false);
      break;
    }
    case MPSL_TIMESLOT_SIGNAL_SESSION_IDLE:  // [[fallthrough]];
    case MPSL_TIMESLOT_SIGNAL_SESSION_CLOSED: {
      inst.SetTimeslotActive(false);
      break;
    }
    default: {
      return nullptr;
    }
  }

  return &amp;amp;inst.timeslot_action_;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With relevant class definition (just parts of it for this demonstration) in the header (note: using c++17)&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;class MyClass {
 public:
  MyClass(const MyClass&amp;amp;) = delete;
  MyClass&amp;amp; operator=(const MyClass&amp;amp;) = delete;
  MyClass(MyClass&amp;amp;&amp;amp;) = delete;
  MyClass&amp;amp; operator=(MyClass&amp;amp;&amp;amp;) = delete;

  static inline MyClass&amp;amp; GetInstance() {
    static MyClass instance;
    return instance;
  }

 private:
  MyClass() = default;
  ~MyClass() = default;

  void SetTimeslotActive(bool active);

  static mpsl_timeslot_signal_return_param_t* TimeslotEventHandler(uint8_t session_id, uint32_t signal);

  bool timeslot_active_{false};
  mpsl_timeslot_signal_return_param_t timeslot_action_{};
};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The biggest difference with the example here: &lt;a href="https://github.com/too1/ncs-esb-ble-mpsl-demo/blob/master/common/timeslot_handler.c#L183"&gt;https://github.com/too1/ncs-esb-ble-mpsl-demo/blob/master/common/timeslot_handler.c#L183&lt;/a&gt; Is that the request is done from a non-preemptible thead, while I just called mpsl_timeslot_request() directly from the timeslot handler. Could this be the reason for the assert as well?&lt;br /&gt;&lt;br /&gt;I wasn&amp;#39;t really sure whether this was necessary, since i would have to create a new thread and message queue for it, which takes up extra stack space. In case it really is required, could i also use the system workqueue to schedule the request? It has a cooperative priority&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: MPSL assert during MCUmgr image erase</title><link>https://devzone.nordicsemi.com/thread/479996?ContentTypeID=1</link><pubDate>Mon, 22 Apr 2024 12:49:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:59035eae-0e0a-4c97-b6b6-6b930ecb4424</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Which SDK version were you using when you got this assert (the line numbers for the same assert may differ between versions)?&lt;/p&gt;
&lt;p&gt;That said, this assert is likely in the handling of the&amp;nbsp;MPSL_TIMESLOT_SIGNAL_CANCELLED event. This statement from the &lt;a href="https://docs.nordicsemi.com/bundle/ncs-latest/page/nrfxlib/mpsl/doc/api.html"&gt;MPSL API documentation&lt;/a&gt; is likely relevant: &amp;quot;&lt;em&gt;For signals executed in low priority returning any action other than MPSL_TIMESLOT_SIGNAL_ACTION_NONE will result in an assert.&lt;/em&gt;&amp;quot;&amp;nbsp;The proper way of requesting an event when processing a low priority signal is to invoke &lt;code&gt;mpsl_timeslot_request()&lt;/code&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>