embassy
embassy copied to clipboard
embassy-boot-nrf with softdevice
I need an example to have bootloader with using softdevice together due to update both application and softdevice. I checked the example, but it does not work for me. One thing that I should mention is that I need defmt for debug both bootloader and applications. Thanks.
What is it that does not work with the example? For what it's worth, I've got a more advanced example here https://github.com/lulf/watchful/tree/main/firmware, maybe you can copy from that.
Thank you for your quick response. I checked your example, but you did not use any debug message. Because I think it has problem with using probe-rs runner debug in both bootloader and application example. I see weird behavior for debug messages. First I program softdevice, then program bootloader and after that the main program but it does not work as desired.
Did you get this working eventually, can we close the issue?
Did you get this working eventually, can we close the issue?
Yes, Thank you
Hi @AliMoal , may I ask you some infos on how you solved? I have a strange issue too. I have sofdevice, app and bootloader at the end of flash. Bootloader is custom, just rewrites actual one ( no double image ). When I jumo to app ( using load function og embassy boot in sd flavour ) app starts but crash when i turn on sd and send some commands from uart. When i just flash sd and app it works like a charm. If you can give me some hints on how you solved would be great!
Thank you @arkanoider My case was different from yours, but if you explain more, I can help. Could you describe how to understand app starts? Do you have UART connection from board? Did you implement any debug method?
Thanks @AliMoal !
I try to summarize my system: I have an nrf52 chip connected with a bigger MCU via UART, bigger MCU can send and receive messages to and from BT via nrf chip ( a sort of passthrough let me say ) basically my small app just do this. Bootloader inside nrf chip can update this passthrough app in case.
As premise, i confirm that application is working correctly with no bootloader flashed, with boot onbooard basically I have a reset after i send a command with BT on.
Could you describe how to understand app starts? I see welcome message and I can also send BT activation command and it works because I can see advertise starting.
I have a UART message sent out at start
Do you have UART connection from board?
Yes. Real system has the two microcontrollers speakin via UART , i am using a sw terminal to simulate from PC during tests.
Did you implement any debug method?
If you mean Rust impl...no...i am using just defmt for printing info.
I can drop my memory.x files here: Bootloader side:
MEMORY
{
/* NOTE 1 K = 1 KiBi = 1024 bytes */
/* These values correspond to the NRF52805 with SoftDevices S112 7.2.0 */
FLASH (rx) : ORIGIN = 0x2A000, LENGTH = 24K
RAM : ORIGIN = 0x20000008, LENGTH = 24K - 8
mbr_params_page (r) : ORIGIN = 0x0002E000, LENGTH = 4K
bootloader_settings_page (r) : ORIGIN = 0x0002F000, LENGTH = 4K
uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
}
SECTIONS {
.uicr_bootloader_start_address : {
KEEP(*(.uicr_bootloader_start_address))
. = ALIGN(4);
} > uicr_bootloader_start_address
};
App side
MEMORY
{
/* NOTE 1 K = 1 KiBi = 1024 bytes */
/* These values correspond to the NRF52805 with SoftDevices S112 7.2.0 */
FLASH (rx) : ORIGIN = 0x19000, LENGTH = 64K
RAM : ORIGIN = 0x20000000 + 9440, LENGTH = 24K - 9440
}
So basically bootloader is placed at 0x2A000 and app starts after SD at 0x19000. Jump to app is done via this copy and paste function from embassy boot:
/// Boots the application assuming softdevice is present.
///
/// # Safety
///
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
pub unsafe fn jump_to_app() -> ! {
use nrf_softdevice_mbr as mbr;
// Address of softdevice which we'll forward interrupts to
let addr = 0x1000;
let mut cmd = mbr::sd_mbr_command_t {
command: mbr::NRF_MBR_COMMANDS_SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET,
params: mbr::sd_mbr_command_t__bindgen_ty_1 {
irq_forward_address_set: mbr::sd_mbr_command_irq_forward_address_set_t {
address: addr,
},
},
};
let ret = mbr::sd_mbr_command(&mut cmd);
info!("ret val {}", ret);
let msp = *(addr as *const u32);
let rv = *((addr + 4) as *const u32);
trace!("msp = {=u32:x}, rv = {=u32:x}", msp, rv);
// These instructions perform the following operations:
//
// * Modify control register to use MSP as stack pointer (clear spsel bit)
// * Synchronize instruction barrier
// * Initialize stack pointer (0x1000)
// * Set link register to not return (0xFF)
// * Jump to softdevice reset vector
core::arch::asm!(
"mrs {tmp}, CONTROL",
"bics {tmp}, {spsel}",
"msr CONTROL, {tmp}",
"isb",
"msr MSP, {msp}",
"mov lr, {new_lr}",
"bx {rv}",
// `out(reg) _` is not permitted in a `noreturn` asm! call,
// so instead use `in(reg) 0` and don't restore it afterwards.
tmp = in(reg) 0,
spsel = in(reg) 2,
new_lr = in(reg) 0xFFFFFFFFu32,
msp = in(reg) msp,
rv = in(reg) rv,
options(noreturn),
);
}
Solved! Thanks anyway...