Skip to content

Commit fab378f

Browse files
committed
[nrf noup] drivers: misc: nordic_vpr_launcher: Improve code relocation
Instead of copying whole partition dedicated for VPR decode end address from the beginning of the binary code. Only code and certain portion of data is copied (excluding noinit section). It reduces the boot time and fixes issue where noinit section is overwritten after reset. Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 8c9c43f commit fab378f

File tree

1 file changed

+48
-5
lines changed

1 file changed

+48
-5
lines changed

drivers/misc/nordic_vpr_launcher/nordic_vpr_launcher.c

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,62 @@ struct nordic_vpr_launcher_config {
3030
#endif
3131
};
3232

33+
/** @brief Decode rom size from the VPR code.
34+
*
35+
* Use VPR code, which at the beginning encodes address of __relocation_region_end,
36+
* to calculate code that needs to be copied. Expecting following 2 instructions:
37+
* auipc gp,val
38+
* addi gp,gp val
39+
*
40+
* @param src_addr Source address.
41+
* @param dst_addr Destination address.
42+
* @param[out] size ROM size.
43+
*
44+
* @retval 0 on successful size decoding.
45+
* @retval -EINVAL if size decoding failed.
46+
*/
47+
static int decode_size(uintptr_t src_addr, uintptr_t dst_addr, size_t *size)
48+
{
49+
uint32_t *instr = (uint32_t *)src_addr;
50+
uint32_t i0 = instr[0];
51+
uint32_t i1 = instr[1];
52+
uint32_t instr0 = i0 & BIT_MASK(7);
53+
uint32_t rd0 = (i0 >> 7) & BIT_MASK(5);
54+
uint32_t imm0 = i0 >> 12;
55+
int imm1 = (int)i1 >> 20;
56+
57+
if ((instr0 != 0x17) && (rd0 != 3)) {
58+
return -EINVAL;
59+
}
60+
61+
uintptr_t relocation_addr_end = dst_addr + (imm0 << 12);
62+
63+
relocation_addr_end += imm1;
64+
*size = (size_t)(relocation_addr_end - dst_addr)+ 0;
65+
66+
return 0;
67+
}
68+
3369
static int nordic_vpr_launcher_init(const struct device *dev)
3470
{
3571
const struct nordic_vpr_launcher_config *config = dev->config;
36-
3772
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(source_memory)
73+
size_t size;
74+
int err;
75+
76+
err = decode_size(config->src_addr, config->exec_addr, &size);
77+
if (err < 0) {
78+
size = config->size;
79+
}
80+
3881
if (config->size > 0U) {
3982
LOG_DBG("Loading VPR (%p) from %p to %p (%zu bytes)", config->vpr,
40-
(void *)config->src_addr, (void *)config->exec_addr, config->size);
41-
memcpy((void *)config->exec_addr, (void *)config->src_addr, config->size);
83+
(void *)config->src_addr, (void *)config->exec_addr, size);
84+
memcpy((void *)config->exec_addr, (void *)config->src_addr, size);
4285
#if defined(CONFIG_DCACHE)
4386
LOG_DBG("Writing back cache with loaded VPR (from %p %zu bytes)",
44-
(void *)config->exec_addr, config->size);
45-
sys_cache_data_flush_range((void *)config->exec_addr, config->size);
87+
(void *)config->exec_addr, size);
88+
sys_cache_data_flush_range((void *)config->exec_addr, size);
4689
#endif
4790
}
4891
#endif

0 commit comments

Comments
 (0)