<?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>nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/95743/nrf51822-getting-instruction-address-from-the-fault-handlers</link><description>Hello, guys! 
 We are using nRF51822 SoC with nRF5 SDK v12.3.0 and s130 SoftDevice. For the devices in the wild, we would like to implement the following health monitoring strategy: 
 
 Detect when the fault events happen (e.g. HardFaults, App Error Faults</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 17 Jan 2023 16:51:19 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/95743/nrf51822-getting-instruction-address-from-the-fault-handlers" /><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405323?ContentTypeID=1</link><pubDate>Tue, 17 Jan 2023 16:51:19 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:da5252be-9ebc-4275-a99d-9c550e77d030</guid><dc:creator>bojan</dc:creator><description>&lt;p&gt;Hey, &lt;a href="https://devzone.nordicsemi.com/members/sigurdon"&gt;Sigurd&lt;/a&gt; !&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve applied the approach you suggested. From my custom implementation of the &lt;span style="background-color:#ccffcc;"&gt;&lt;em&gt;&lt;strong&gt;HardFault_process()&lt;/strong&gt;&lt;/em&gt; &lt;/span&gt;function, I was able to extract the PC value.&lt;/p&gt;
&lt;p&gt;I after that used the&amp;nbsp; &lt;span style="background-color:#ccffff;"&gt;&lt;strong&gt;&lt;i&gt;addr2line&lt;/i&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-weight:400;"&gt; tool of the arm compiler to find out more about which function/module is located on that PC address:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;arm-none-eabi-addr2line.exe -e &amp;lt;your_path&amp;gt;/nrf51822_xxac.out -a PC&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;However, given the fact that we don&amp;#39;t use SES IDE but compile through the Makefile, I needed to revert the workaround in &lt;span style="background-color:#ccffcc;"&gt;&lt;em&gt;&lt;strong&gt;hardfault_handler_gcc.c&lt;/strong&gt;&lt;/em&gt; &lt;/span&gt;file described in &lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/23232/hardfault_handler-for-segger-embedded-studio" rel="noopener noreferrer" target="_blank"&gt;this thread&lt;/a&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1673974177701v1.png" alt=" " /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;Is this reverting OK?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;Anyway, thank you very much for your great support, &lt;a href="https://devzone.nordicsemi.com/members/turboj"&gt;Turbo J&lt;/a&gt; , &lt;a href="https://devzone.nordicsemi.com/members/sigurdon"&gt;Sigurd&lt;/a&gt; !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;Cheers,&lt;br /&gt;Bojan.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405312?ContentTypeID=1</link><pubDate>Tue, 17 Jan 2023 15:32:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5b07789b-6cd8-4b03-92a8-b7e162ef82ce</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I recommend having a look at the&amp;nbsp;&lt;span&gt;HardFault handling library in the SDK.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a id="" href="https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.3.0/lib_hardfault.html"&gt;https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.3.0/lib_hardfault.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Add these to your projects:&lt;/p&gt;
&lt;p&gt;$(SDK_ROOT)/components/libraries/hardfault/hardfault_implementation.c&lt;br /&gt;$(SDK_ROOT)/components/libraries/hardfault/nrf51/handler/hardfault_handler_gcc.c (or *_keil/iar, depending on your toolchain)&lt;/p&gt;
&lt;p&gt;And set HARDFAULT_HANDLER_ENABLED to 1 in sdk_config.h (and &lt;span&gt;DEBUG_NRF in your preprocessor definitions&amp;nbsp;to&amp;nbsp;get even more info in the handler&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It will show you the PC value that triggered the fault(if the HW was able determine the location of the fault).&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405284?ContentTypeID=1</link><pubDate>Tue, 17 Jan 2023 14:21:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d90265bc-03e9-47de-9e3c-a8bc9622e264</guid><dc:creator>bojan</dc:creator><description>&lt;p&gt;Thanks, &lt;a href="https://devzone.nordicsemi.com/members/sigurdon"&gt;Sigurd&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;What about the instruction address (&lt;span style="background-color:rgba(204, 255, 204, 1);"&gt;&lt;em&gt;&lt;strong&gt;ia&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;) that caused the HardFault? Can we get that from the &lt;span style="background-color:rgba(255, 153, 204, 1);"&gt;&lt;em&gt;&lt;strong&gt;HardFault_Handler()&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; under some circumstances?&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Bojan.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405263?ContentTypeID=1</link><pubDate>Tue, 17 Jan 2023 13:21:20 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e861107a-26ef-42d3-8463-1ffa177e73a0</guid><dc:creator>Sigurd</dc:creator><description>[quote user="bojan"]Where can I find something more about the meaning of fault identifier (id) and info fields?[/quote]
&lt;p&gt;Take a look at how the app_error_save_and_stop() parses the id and info field&lt;/p&gt;
&lt;p&gt;Snippet:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info)
{
    /* static error variables - in order to prevent removal by optimizers */
    static volatile struct
    {
        uint32_t        fault_id;
        uint32_t        pc;
        uint32_t        error_info;
        assert_info_t * p_assert_info;
        error_info_t  * p_error_info;
        ret_code_t      err_code;
        uint32_t        line_num;
        const uint8_t * p_file_name;
    } m_error_data = {0};

    // The following variable helps Keil keep the call stack visible, in addition, it can be set to
    // 0 in the debugger to continue executing code after the error check.
    volatile bool loop = true;
    UNUSED_VARIABLE(loop);

    m_error_data.fault_id   = id;
    m_error_data.pc         = pc;
    m_error_data.error_info = info;

    switch (id)
    {
        case NRF_FAULT_ID_SDK_ASSERT:
            m_error_data.p_assert_info = (assert_info_t *)info;
            m_error_data.line_num      = m_error_data.p_assert_info-&amp;gt;line_num;
            m_error_data.p_file_name   = m_error_data.p_assert_info-&amp;gt;p_file_name;
            break;

        case NRF_FAULT_ID_SDK_ERROR:
            m_error_data.p_error_info = (error_info_t *)info;
            m_error_data.err_code     = m_error_data.p_error_info-&amp;gt;err_code;
            m_error_data.line_num     = m_error_data.p_error_info-&amp;gt;line_num;
            m_error_data.p_file_name  = m_error_data.p_error_info-&amp;gt;p_file_name;
            break;
    }

    UNUSED_VARIABLE(m_error_data);

    // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger.
    __disable_irq();
    while (loop);

    __enable_irq();
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405129?ContentTypeID=1</link><pubDate>Mon, 16 Jan 2023 20:56:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:13da5d84-f052-48fd-8bb0-72ff8678222d</guid><dc:creator>bojan</dc:creator><description>&lt;p&gt;Thanks!&lt;/p&gt;
&lt;p&gt;Where can I find something more about the meaning of fault identifier (id) and info fields?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405128?ContentTypeID=1</link><pubDate>Mon, 16 Jan 2023 20:35:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6a5b3857-79ec-4a54-bcd8-03e7b812f4e8</guid><dc:creator>Turbo J</dc:creator><description>&lt;p&gt;The app_error_fault_handler() is a normal function, but the calling (on the SDK side) contains tons of compiler magic and IFDEFs. It is possible to deactivate the info functionality in order to save flash memory.&lt;/p&gt;
&lt;p&gt;Not sure if the &amp;quot;pc&amp;quot; argument actually ever worked, I always used the stuff in &amp;quot;info&amp;quot; for app errors.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405127?ContentTypeID=1</link><pubDate>Mon, 16 Jan 2023 20:23:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d68f67ca-ac22-49d7-b2db-fe788ace09b0</guid><dc:creator>bojan</dc:creator><description>&lt;p&gt;Thanks for the fast feedback, &lt;a href="https://devzone.nordicsemi.com/members/turboj"&gt;Turbo J&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;We have declared both functions as &amp;quot;naked&amp;quot; with:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void HardFault_Handler(void) __attribute__(( naked ));
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) __attribute__(( naked ));&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;So, for the devices in the wild, the best will be just to count the number of fault events (HardFault, App Error Fault)?&lt;/p&gt;
&lt;p&gt;It will be much more useful for us if we could get some more details about the Faulty event so that we can fix the bug causing it.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51822: Getting instruction address from the fault handlers</title><link>https://devzone.nordicsemi.com/thread/405126?ContentTypeID=1</link><pubDate>Mon, 16 Jan 2023 20:10:05 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f8b555d4-5a53-4526-8df0-276e57402963</guid><dc:creator>Turbo J</dc:creator><description>&lt;p&gt;You forgot to declare the Hardfault_Handler() to be &amp;quot;naked&amp;quot; (yes, that is an attribute in gcc). Otherwise it generates the normal pre stacking of any function type - like pushing LR for example.&lt;/p&gt;
&lt;p&gt;Note that the softdevice already handles hard faults and &lt;em&gt;will&lt;/em&gt; mess up the stack - at least it tries to read from it (which can cause a lockup reset).&lt;/p&gt;
&lt;p&gt;Its better to use the vector catch in the debugger. For devices in the wild its better to just NVIC_SystemReset() in the Fault handler&amp;nbsp; - you have to be lucky to get a function call working properly.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>