Q: Both APPNAME
and PROGNAME
are used to describe the entry point into an application. What is the difference?
A: Let's answer this question by dissecting one case: apps/examples/hello
apps/examples/hello/Kconfig
First, notice in the apps/examples/hello Kconfig
file that the PROGNAME
is only selected for the kernel build (CONFIG_BUILD_KERNEL
). It is not defined or used in other build modes.
config EXAMPLES_HELLO_PROGNAME string "Program name" default "hello" depends on BUILD_KERNEL ---help--- This is the name of the program that will be use when the NSH ELF program is installed.
Kernel Build Mode
What is different about the kernel build mode? In the kernel build, the RTOS is built as a separately linked kernel that lives in its own kernel address space. There are no tasks in the sense used in the flat build. There are still kernel threads but tasks are now referred to as processes: A process is simply a task that lives in its own protected address space.
In the the kernel build, you cannot reference any task/process by an address in memory. Remember that each process lives in its own separate address spaces that is not accessible from any other process. So you cannot do task_create()
or task_spawn()
or any of those APIs that include the absolute address of an task entry point. That virtual entry point address has meaning only within the context of the process and is useless in the kernel build.
The APPNAME
variable provides information for the task entry point address. None of this can be used in the kernel build.
Instead, for the kernel build, the process code must be loaded into memory and mapped into its own address space before it can be executed. The process code is referred to as a program and is typically saved in a file system. If you are familiar with Linux, then then you are familiar with processes and separately linked programs in files.
apps/examples/hello_main.c
Look in the task/process entry point in apps/examples/hello/hello_main.c
:
#ifdef CONFIG_BUILD_KERNEL int main(int argc, FAR char *argv[]) #else int hello_main(int argc, char *argv[]) #endif { printf("Hello, World!!\n"); return 0; }
The APPNAME
is hello_main()
. But for the kernel build, the standard entry point name main()
is used. Every program in the NuttX build has the entry point main()
in the kernel build (You could not do that in the flat build because the symbol main()
would be multiply defined. But since each program is separately built there is no issue in the kernel build).
When the NuttX program is linked, it is linked with special object called crt0.o
. You can see the ARMv7-A crt0 file at nuttx/arch/arm/src/armv7-a/crt0.c
.
apps/examples/hello/Makefile
Finally, there are a few interesting things in the hello
Makefile at apps/examples/hello/Makefile
:
First, it defines the MAINSRC
variable to hold the file that includes the main()
function:
MAINSRC = hello_main.c
There is nothing special about MAINSRC
in the flat or protected builds, but MAINSRC
is special in the kernel build as we will see below.
It also defines the program name, PROGNAME
. PROGNAME
is simply a file name in some file system.
CONFIG_EXAMPLES_HELLO_PROGNAME ?= hello$(EXEEXT) PROGNAME = $(CONFIG_EXAMPLES_HELLO_PROGNAME)
At this point, the original question has been answered: The difference be APPNAME
and PROGNAME
is that APPNAME
is the name a task entry address in the a flat or protected build; PROGNAME
is the name of a program file in the kernel build. But let's continue on anywayl
And, finally, it includes Appliction.mk
that does the rest of the job:
include $(APPDIR)/Application.mk
apps/Application.mk
The final link of each link of each program is performed by the install target in Application.mk:
ifeq ($(CONFIG_BUILD_KERNEL),y) $(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) @echo "LD: $(PROGNAME)" $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) install: $(BIN_DIR)$(DELIM)$(PROGNAME) else install: endif
Notice that the final linked programs are stored in INSTALL_DIR
which will be apps/bin
.
Preparing the File System
The overall build sequency for the kernel build is a little more involved than just typing make. You have to also do some steps in order to create the file system containing the separately linked programs. The following instructions come from nuttx/boards/arm/sama5/sama5d4-ek/README.txt
.
6a. General build directions (boot from SD card): $ tools/configure.sh sama5d4-ek:kernel : Establish this configuration $ export PATH=??? : Set up the PATH variable $ make : Build the kerne with a dummy ROMFS image : This should create the nuttx ELF $ make export : Create the kernel export package : You should have a file like : nuttx-export-*.zip $ cd apps/ : Go to the apps/ directory $ tools/mkimport.sh -x <zip-file> : Use the full path to nuttx-export-*.zip $ make import : This will build the file system. You will then need to copy the files from apps/bin to an SD card to create the the bootable SD card. 6b. General build directions (boot from ROMFS image): $ tools/configure.sh sama5d4-ek:kernel : Establish this configuration $ export PATH=??? : Set up the PATH variable $ touch boards/arm/sama5/sama5d4-ek/include/boot_romfsimg.h $ make : Build the kernel with a dummy ROMFS image : This should create the nuttx ELF $ make export : Create the kernel export package : You should have a file like : nuttx-export-*.zip $ cd apps/ : Go to the apps/ directory $ tools/mkimport.sh -x <zip-file> : Use the full path to nuttx-export-*.zip $ make import : This will build the file system $ tools/mkromfsimg.sh : Create the real ROMFS image $ mv boot_romfsimg.h ../nuttx/boards/arm/sama5/sama5d4-ek/include/boot_romfsimg.h $ cd nuttx/ : Rebuild the system with the correct $ make clean_context all : ROMFS file system
NOTE the use of the these two special tools:
apps/tools/mkimport.sh
This does the complement of make export in the NuttX directory. make export bundles up all of the OS components for use with some external build. mkimport.sh
takes this bundle, installs it in the apps/
directory and performs the build of the separately linked programs.
apps/tools/mkimport.sh
This will (optionally) put the separately linked programs into a ROMFS file system that can be included in system FLASH.