mps3-an547:let ap build with pic,and use bootloader boot it

Implement PIC loading in armv8-m qemu,
for example: load address-independent AP ELF in the bootloader,
and the text segment in AP ELF is XIP,
no need to apply for memory and modify it.

Two config:

bootloader abbreviation bl:
  use romfs to load ap elf, use the boot command to parse and jump to ap

application abbreviation ap:
  run os test

We need to compile ap first, then compile bl.

compile step:
  ./tools/configure.sh mps3-an547:ap
  make -j20
  mkdir -p pic
  cp boot pic/.
  genromfs -a 128 -f ../romfs.img -d pic
  make distclean -j20
  ./tools/configure.sh mps3-an547:bl
  make -j20

run qemu:
  qemu-system-arm -M mps3-an547 -m 2G -nographic -kernel nuttx.bin \
    -gdb tcp::1127 -device loader,file=../romfs.img,addr=0x60000000

  nsh> boot /etc/boot
  ap> ostest

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2024-07-01 17:33:23 +08:00 committed by GUIDINGLI
parent 3e9c2e00ea
commit 15fa55f234
7 changed files with 260 additions and 15 deletions

View file

@ -41,6 +41,24 @@ Configuring and Running
$ nsh> /pic/ostest
```
4. **Pic bootloader boot to ap, and run ostest:**
```bash
$ ./tools/configure.sh mps3-an547:ap
$ make -j20
$ mkdir -p pic
$ arm-none-eabi-strip --remove-section=.rel.text --remove-section=.comment --strip-unneeded nuttx -o pic/boot
$ genromfs -a -f 128 ../romfs.img -d pic
$ make distclean -j20
$ ./tools/configure.sh mps3-an547:bl
$ make -j20
$ qemu-system-arm -M mps3-an547 -m 2G -nographic \
-kernel nuttx.bin -gdb tcp::1127 \
-device loader,file=../romfs.img,addr=0x60000000
$ bl> boot /pic/boot
$ ap> ostest
```
Debugging with QEMU
===================

View file

@ -42,6 +42,8 @@ config ARCH_CHIP_MPS3_AN547
select ARCH_CORTEXM55
select ARCH_HAVE_FPU
select ARM_HAVE_MVE
select ARCH_HAVE_TEXT_HEAP
select ARCH_HAVE_DATA_HEAP
endchoice

View file

@ -43,6 +43,8 @@
* Pre-processor Definitions
****************************************************************************/
#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
/* Configuration ************************************************************/
/* Terminology.
@ -76,21 +78,12 @@
*/
/****************************************************************************
* Public Data
* Private Data
****************************************************************************/
/* _sbss is the start of the BSS region (see the linker script) _ebss is the
* end of the BSS regions (see the linker script). The idle task stack starts
* at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE
* thread is the thread that the system boots on and, eventually, becomes the
* idle, do nothing task that runs only when there is nothing else to run.
* The heap continues from there until the configured end of memory.
* g_idle_topstack is the beginning of this heap region (not necessarily
* aligned).
*/
const uintptr_t g_idle_topstack = (uintptr_t)_ebss +
CONFIG_IDLETHREAD_STACKSIZE;
#if defined(CONFIG_ARCH_USE_TEXT_HEAP) || defined(CONFIG_ARCH_USE_DATA_HEAP)
static uintptr_t g_alloc_count;
#endif
/****************************************************************************
* Public Functions
@ -169,8 +162,13 @@ void up_allocate_heap(void **heap_start, size_t *heap_size)
/* Allow user-mode access to the user heap memory */
mpu_user_intsram(ubase, usize);
#else
#elif defined(CONFIG_BUILD_PIC)
/* Use different heap useful to debug */
*heap_start = (void *)MPS_SRAM1_START;
*heap_size = MPS_SRAM1_SIZE;
#else
/* Return the heap settings */
*heap_start = (void *)g_idle_topstack;
@ -271,3 +269,111 @@ void arm_addregion(void)
#endif /* CONFIG_MM_REGIONS > 2 */
}
#endif /* CONFIG_MM_REGIONS > 1 */
/****************************************************************************
* Name: up_textheap_memalign
*
* Description:
* Allocate memory for text with the specified alignment and sectname.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
# if defined(CONFIG_ARCH_USE_SEPARATED_SECTION)
void *up_textheap_memalign(const char *sectname,
size_t align, size_t size)
# else
void *up_textheap_memalign(size_t align, size_t size)
# endif
{
uintptr_t base = (uintptr_t)MPS_SRAM2_START + g_alloc_count;
uintptr_t ret = ALIGN_UP(base, align);
g_alloc_count += ret - base + size;
return (void *)ret;
}
#endif
/****************************************************************************
* Name: up_textheap_free
*
* Description:
* Free memory allocated for text sections.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
void up_textheap_free(void *p)
{
}
#endif
/****************************************************************************
* Name: up_textheap_heapmember
*
* Description:
* Test if memory is from text heap.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
bool up_textheap_heapmember(void *p)
{
return (uintptr_t)p >= MPS_SRAM2_START &&
(uintptr_t)p < MPS_SRAM2_START + MPS_SRAM2_SIZE;
}
#endif
/****************************************************************************
* Name: up_dataheap_memalign
*
* Description:
* Allocate memory for data with the specified alignment and sectname.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
# if defined(CONFIG_ARCH_USE_SEPARATED_SECTION)
void *up_dataheap_memalign(const char *sectname,
size_t align, size_t size)
# else
void *up_dataheap_memalign(size_t align, size_t size)
# endif
{
uintptr_t base = (uintptr_t)MPS_SRAM2_START + g_alloc_count;
uintptr_t ret = ALIGN_UP(base, align);
g_alloc_count += ret - base + size;
return (void *)ret;
}
#endif
/****************************************************************************
* Name: up_dataheap_free
*
* Description:
* Free memory allocated for data sections.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
void up_dataheap_free(void *p)
{
}
#endif
/****************************************************************************
* Name: up_dataheap_heapmember
*
* Description:
* Test if memory is from data heap.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
bool up_dataheap_heapmember(void *p)
{
return (uintptr_t)p >= MPS_SRAM2_START &&
(uintptr_t)p < MPS_SRAM2_START + MPS_SRAM2_SIZE;
}
#endif

View file

@ -36,6 +36,28 @@
#include "mps_userspace.h"
#include "mpu.h"
/****************************************************************************
* Public Functions
****************************************************************************/
#define HEAP_BASE ((uintptr_t)_ebss + CONFIG_IDLETHREAD_STACKSIZE)
/****************************************************************************
* Public Data
****************************************************************************/
/* g_idle_topstack: _sbss is the start of the BSS region as defined by the
* linker script. _ebss lies at the end of the BSS region. The idle task
* stack starts at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE.
* The IDLE thread is the thread that the system boots on and, eventually,
* becomes the IDLE, do nothing task that runs only when there is nothing
* else to run. The heap continues from there until the end of memory.
* g_idle_topstack is a read-only variable the provides this computed
* address.
*/
const uintptr_t g_idle_topstack = HEAP_BASE;
/****************************************************************************
* Private Functions
****************************************************************************/
@ -94,8 +116,10 @@ static inline void mps_tcmenable(void)
void __start(void)
{
#ifndef CONFIG_BUILD_PIC
const uint32_t *src;
uint32_t *dest;
#endif
/* If enabled reset the MPU */
@ -105,6 +129,10 @@ void __start(void)
#endif
arm_fpuconfig();
/* If used the PIC, then the PIC will have already been configured */
#ifndef CONFIG_BUILD_PIC
/* Set bss to zero */
for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; )
@ -120,6 +148,7 @@ void __start(void)
{
*dest++ = *src++;
}
#endif
/* Perform early serial initialization */

View file

@ -91,6 +91,8 @@ CONFIG_ARCH_CHIP_MPS3_AN547=y
CONFIG_ARCH_CHIP_MPS=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_USE_DATA_HEAP=y
CONFIG_ARCH_USE_SEPARATED_SECTION=y
CONFIG_ARMV8M_SYSTICK=y
CONFIG_BOARDCTL_APP_SYMTAB=y
CONFIG_BOARDCTL_BOOT_IMAGE=y

View file

@ -18,6 +18,8 @@
*
****************************************************************************/
#include "nuttx/config.h"
MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 512K
@ -33,7 +35,9 @@ SECTIONS
{
.text : {
_stext = ABSOLUTE(.);
#ifndef CONFIG_BUILD_PIC /* We need change vectors use pic */
*(.vectors)
#endif
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
@ -41,7 +45,6 @@ SECTIONS
*(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.got)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
_etext = ABSOLUTE(.);
@ -93,6 +96,11 @@ SECTIONS
_edata = ABSOLUTE(.);
} > sram1 AT > flash
.got :
{
*(.got*)
} > sram1
.bss : ALIGN(4) {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View file

@ -28,9 +28,13 @@
#include <sys/mount.h>
#include <syslog.h>
#include <nuttx/lib/modlib.h>
#include <nuttx/fs/fs.h>
#include <nuttx/drivers/ramdisk.h>
#include "nvic.h"
#include "arm_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -97,6 +101,82 @@ static int mps3_bringup(void)
* Public Functions
****************************************************************************/
#ifdef CONFIG_BOARDCTL_BOOT_IMAGE
int board_boot_image(FAR const char *path, uint32_t hdr_size)
{
struct mod_loadinfo_s loadinfo;
struct module_s mod;
uintptr_t bss;
uintptr_t got;
uintptr_t msp;
int ret;
/* Initialize the ELF library to load the program binary. */
syslog(LOG_INFO, "modlib_init...\n");
ret = modlib_initialize(path, &loadinfo);
if (ret < 0)
{
syslog(LOG_ERR, "Failed to modlib_init: %d\n", ret);
return ret;
}
/* Load the program binary */
syslog(LOG_INFO, "modlib_load...\n");
ret = modlib_load(&loadinfo);
if (ret < 0)
{
syslog(LOG_ERR, "Failed to modlib_load: %d\n", ret);
goto errout_with_init;
}
syslog(LOG_INFO, "modlib_bind...\n");
memset(&mod, 0, sizeof(struct module_s));
ret = modlib_bind(&mod, &loadinfo, NULL, 0);
if (ret < 0)
{
syslog(LOG_ERR, "Failed to modlib_bind: %d\n", ret);
goto errout_with_load;
}
bss = modlib_findsection(&loadinfo, ".bss");
got = loadinfo.shdr[loadinfo.gotindex].sh_addr;
msp = loadinfo.shdr[bss].sh_addr + loadinfo.shdr[bss].sh_size +
CONFIG_IDLETHREAD_STACKSIZE;
syslog(LOG_INFO, "add-symbol-file ap.elf -s .text 0x%x -s .data"
" 0x%x\n", loadinfo.textalloc, loadinfo.datastart);
up_irq_disable();
/* Disable systick */
putreg32(0, NVIC_SYSTICK_CTRL);
putreg32(NVIC_SYSTICK_RELOAD_MASK, NVIC_SYSTICK_RELOAD);
putreg32(0, NVIC_SYSTICK_CURRENT);
/* Set got address to r9 */
__asm__ __volatile__("mov r9, %0"::"r"(got));
/* set msp to the top of idle stack */
__asm__ __volatile__("msr msp, %0" : : "r" (msp));
((void (*)(void))loadinfo.ehdr.e_entry + loadinfo.textalloc)();
errout_with_load:
modlib_unload(&loadinfo);
errout_with_init:
modlib_uninitialize(&loadinfo);
return ret;
}
#endif
/****************************************************************************
* Name: board_late_initialize
*