<?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>Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/124281/replacing-mbr-with-custom-bootloader</link><description>Hi, 
 I&amp;#39;m developing a custom MBR/bootloader for NRF52811 which is used as a second/radio MCU on the board. The MCU will need to run applications with and without the softdevice, based on current usecase (ble and non-BLE protocols). The official uart</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 17 Sep 2025 15:16:37 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/124281/replacing-mbr-with-custom-bootloader" /><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/549076?ContentTypeID=1</link><pubDate>Wed, 17 Sep 2025 15:16:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f164f908-dc95-4733-ac42-112c91f1de1b</guid><dc:creator>tesc</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="kajus"]That seems to be everything the MBR does when not requested otherwise. Implementing similar behavior seems to work for me with BLE uart example (modified as loopback) and S112.[/quote]
&lt;p&gt;That sounds correct, yes.&lt;/p&gt;
&lt;p&gt;To elaborate on the redirection of interrupts and SVCalls, similar redirects are done also from SoftDevice to application, for the interrupts not used by the SoftDevice. In theory, if you redirect anything to the SoftDevice which the SoftDevice doesn&amp;#39;t use, then the SoftDevice will redirect that back to the app, and you end up looping infinitely.&lt;/p&gt;
&lt;p&gt;Hence if VTOR is set to the application start, you need to redirect interrupts for certain peripherals to the SoftDevice, but only when the SoftDevice is enabled. Also, you must only redirect interrupts for the peripherals actually used by the SoftDevice. Failing to map this correctly could lead to either the SoftDevice not getting interrupts, or interrupts getting endlessly redirected back and forth between app and SoftDevice.&lt;/p&gt;
[quote user="kajus"]However I still don&amp;#39;t understand, why the VTOR change I used initially doesn&amp;#39;t work, what my MBR implementation does now is redirecting all IRQs to addresses at 0x1000 (softdevice vector table). The 0x20000000 doesn&amp;#39;t seem to be changing during app/softdevice runtime, so the behavior shall be identical...[/quote]
&lt;p&gt;The first couple of words in RAM are used for vector table coordination between MBR and SoftDevice. Hence the need to set 0x20000000 to 0x1000.&lt;/p&gt;
&lt;p&gt;Regards,&lt;br /&gt;Terje&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/549021?ContentTypeID=1</link><pubDate>Wed, 17 Sep 2025 11:53:04 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:99df5c79-16e4-46d3-bda8-8c7bac2f0cec</guid><dc:creator>kajus</dc:creator><description>&lt;p&gt;Ok, I guess I&amp;#39;ve managed to make it work with help of some MBR binary disassembly,&amp;nbsp;the error mentioned in the previous post was caused in bug in my code around SVCall processing.&lt;br /&gt;&lt;br /&gt;So, the official MBR seems to be doing:&lt;/p&gt;
&lt;p&gt;- After boot, the MBR does some magic at UICR-&amp;gt;NRFFW pointed address (with fallback to some hardcoded address), it seems it has something to do with the MBR configuration storage that to my understanding contains data for DFU (e.g. which section is to be written with DFU data,...), so I can ignore this as I don&amp;#39;t intend to use the official bootloader&lt;br /&gt;- Once reading configuration is done, bootloader jumps to application/softdevice at 0x1000 + 0x4 (if not set to different address in the configuration above), before jumping 0x20000000 is written with the vector table address (0x1000)&lt;br /&gt;- All interrupts except Reset and SVCall are redirected to vector table the 0x20000000 points to.&lt;br /&gt;- The SVCall interrupt check the argument in svcall instruction, if it&amp;#39;s equal to 0x18, it&amp;#39;s a bootloader call, else it&amp;#39;s passed to softdevice/app in the same way as the other interrupts.&lt;br /&gt;&lt;br /&gt;That seems to be everything the MBR does when not requested otherwise. Implementing similar behavior seems to work for me with BLE uart example (modified as loopback) and S112.&lt;br /&gt;&lt;br /&gt;However I still don&amp;#39;t understand, why the VTOR change I used initially doesn&amp;#39;t work, what my MBR implementation does now is redirecting all IRQs to addresses at 0x1000 (softdevice vector table). The 0x20000000 doesn&amp;#39;t seem to be changing during app/softdevice runtime, so the behavior shall be identical...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548862?ContentTypeID=1</link><pubDate>Tue, 16 Sep 2025 11:30:47 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:25b9bf7d-fcd5-48d6-8b7f-2b332ce2f414</guid><dc:creator>kajus</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve added vector forwarding to vector table at 0x20000000. The application seems to be launched correctly though the softdevice, but it always fails starting the softdevice (the&amp;nbsp;sd_softdevice_enable call returns&amp;nbsp;0x20005fd4 which doesn&amp;#39;t make much sense to me, as it&amp;#39;s some address in ram, not the actual error code). I&amp;#39;m using S112 7.2.0&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548692?ContentTypeID=1</link><pubDate>Mon, 15 Sep 2025 07:37:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4eca537d-3c5c-4c8b-a9dc-78b95d9bb3e0</guid><dc:creator>kajus</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;thank you very much for the answer, but I still don&amp;#39;t understand few points:&lt;br /&gt;&lt;br /&gt;- when I run reset vector at 2), the MBR won&amp;#39;t be executed again until reset, right? I assume the reset&amp;nbsp; vector shall not return - therefore I&amp;#39;ll never by able to run 3) to&amp;nbsp; 6)&lt;br /&gt;- at 4), how do I get the application start address? It depends on softdevice version...&lt;br /&gt;- 6) so I have to modify the application to do the heavylifting instead of MBR? I thought this was to be done by the MBR, not the application&lt;br /&gt;- is there a way to detect the binary at 0x1000 is a softdevice?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548513?ContentTypeID=1</link><pubDate>Thu, 11 Sep 2025 14:05:01 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0d689c9f-16a0-456f-9811-acaaf4af5de0</guid><dc:creator>tesc</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Upon further inquiry, we see that more is indeed needed. Here&amp;#39;s what is required:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set 0x20000000 to the application start address&lt;/li&gt;
&lt;li&gt;Run the reset vector of the SoftDevice (at address 0x1004)&lt;/li&gt;
&lt;li&gt;Set 0x20000000 to 0x1000 (which is the start address of the SoftDevice)&lt;/li&gt;
&lt;li&gt;Do a sd_softdevice_vector_table_base_set() with the application start address&lt;/li&gt;
&lt;li&gt;Set VTOR to the start address of the application&lt;/li&gt;
&lt;li&gt;From the application, whenever the SoftDevice is enabled, forward any RADIO, RTC, POWER_CLOCK, RNG and SWI5 IRQs to the SoftDevice&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some of those steps may be unnecessary and might be omitted to save space, but a first step should be to do all of the above in order to have a known working starting point.&lt;/p&gt;
&lt;p&gt;Regards,&lt;br /&gt;Terje&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548442?ContentTypeID=1</link><pubDate>Thu, 11 Sep 2025 07:50:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:25ba93c4-1b1f-4783-86df-284f4793dd99</guid><dc:creator>kajus</dc:creator><description>&lt;p&gt;I&amp;#39;ve created a minimalistic MBR that only changes VTOR to softdevice, sets stack pointer and jumps to the reset vector, but it doesn&amp;#39;t seem to do the trick (code below). The reset vector from the S112 seems to be at 0x18a59 (just at the end of the softdevice flash area), stack pointer set to 0x20000cd0, so this is probably valid.&lt;br /&gt;&lt;br /&gt;Flashing softdevice + app works (the device is advertising on BLE), rewriting flash below 0x1000 with my MBR implementation results hanging on address 0x189b8.&lt;/p&gt;
&lt;p&gt;As the softdevice is a binary blob, it&amp;#39;s quite hard to debug this... Any ideas what I&amp;#39;m missing?&lt;/p&gt;
&lt;div style="background-color:#1f1f1f;color:#cccccc;font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;font-size:14px;font-weight:normal;line-height:19px;white-space:pre;"&gt;
&lt;div&gt;&lt;span style="color:#c586c0;"&gt;#define&lt;/span&gt;&lt;span style="color:#569cd6;"&gt; &lt;/span&gt;&lt;span style="color:#569cd6;"&gt;APP_VECTOR_TABLE_ADDR&lt;/span&gt;&lt;span style="color:#569cd6;"&gt; &lt;/span&gt;&lt;span style="color:#b5cea8;"&gt;0x1000UL&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="color:#569cd6;"&gt;static&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#569cd6;"&gt;void&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#dcdcaa;"&gt;jump_to_app&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;*&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;vector &lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;=&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; (&lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;*&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;)&lt;/span&gt;&lt;span style="color:#569cd6;"&gt;APP_VECTOR_TABLE_ADDR&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; new_sp &lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;=&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;vector&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;[&lt;/span&gt;&lt;span style="color:#b5cea8;"&gt;0&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;];&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; new_pc &lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;=&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;vector&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;[&lt;/span&gt;&lt;span style="color:#b5cea8;"&gt;1&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;];&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#569cd6;"&gt;SCB&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#9cdcfe;"&gt;VTOR&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;=&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; &lt;/span&gt;&lt;span style="color:#569cd6;"&gt;APP_VECTOR_TABLE_ADDR&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#dcdcaa;"&gt;__DSB&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#dcdcaa;"&gt;__ISB&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color:#dcdcaa;"&gt;__set_MSP&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;(new_sp);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color:#cccccc;"&gt;&amp;nbsp; &amp;nbsp; ((&lt;/span&gt;&lt;span style="color:#569cd6;"&gt;void&lt;/span&gt;&lt;span style="color:#cccccc;"&gt; (&lt;/span&gt;&lt;span style="color:#d4d4d4;"&gt;*&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;)(&lt;/span&gt;&lt;span style="color:#569cd6;"&gt;void&lt;/span&gt;&lt;span style="color:#cccccc;"&gt;))new_pc)();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548380?ContentTypeID=1</link><pubDate>Wed, 10 Sep 2025 13:55:03 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0641cefa-2c4a-444a-b090-c332c17ca682</guid><dc:creator>tesc</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I see that if you use e.g. the S140 v7.3.0, not much Flash is left on the nRF52811 for other purposes. (S140 takes up 156 kiB, leaving 24 kiB for MBR, bootloader and application.)&lt;/p&gt;
[quote user=""]Is it enough to change VTOR to 0x1000, jump to reset handler in vector table at that address and stop worrying (assuming the softdevice, if present, handles forwarding all interrupts to app)?[/quote]
&lt;p&gt;That should basically be it, yes. Then make sure not to do any MBR calls from the application.&lt;/p&gt;
&lt;p&gt;Please note that our bootloader in nRF5 SDK do rely somewhat on MBR functionality, so if you use that bootloader for inspiration, then you should be aware of the usage of MBR functionality there.&lt;/p&gt;
&lt;p&gt;Please also note that the SoftDevice must start at 0x1000, which may have some implications for your custom MBR/bootloader implementation. (The SoftDevice is built for being executed from that fixed location.)&lt;/p&gt;
&lt;p&gt;Regards,&lt;br /&gt;Terje&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548318?ContentTypeID=1</link><pubDate>Wed, 10 Sep 2025 07:43:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:79c4e561-9692-4aba-a4b9-6afc13d60618</guid><dc:creator>kajus</dc:creator><description>&lt;p&gt;It might have an important role for upgrading bootloader and softdevice, but I don&amp;#39;t really care in this case - the bootloader won&amp;#39;t be present, or to be precise, the fw/softdevice upgrade logic would be placed in the MBR itself.&lt;br /&gt;&lt;br /&gt;I don&amp;#39;t need updates over bluetooth, I don&amp;#39;t mind corrupting softdevice/app if the upgrade is aborted in the middle - I can always reset MCU by reset pin and write the fw binary again - the NRF is a secondary MCU on a larger board and the main MCU is there to make sure the correct firmware is flashed and working correctly.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Replacing MBR with custom bootloader</title><link>https://devzone.nordicsemi.com/thread/548316?ContentTypeID=1</link><pubDate>Wed, 10 Sep 2025 07:38:03 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:12814f07-5791-4918-83c2-c9b85ea90db2</guid><dc:creator>Turbo J</dc:creator><description>&lt;p&gt;The MBR has an important role to play when replacing/upgrading the bootloader and the softdevice - its the code piece which does the actual swapping of flash pages. Not easy to replace/rewrite.&lt;/p&gt;
&lt;p&gt;if you run out of flash space, consider external flash or a bigger chip variant.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>