For an embedded system, there's actually little or almost no reason to use loadable Kernel modules. On the other hand, it may turn insecure, if the system is a protected one, using encrypted data & key while live. Then a custom loadable module can dump the memory to grab the secret data/key from runtime environment.
Other than all these, probably, you wish to see something while booting your own custom Kernel. For example, you want - that well known hello_world program should print something on console while kernel is booting.
A simple google search for "hello_world kernel space program" will point you a lot of examples to preparation, write, linking, compiling, loading, checking and unloading that hello_world program as a module for Kernel.
Also, I'd wrote two post - here & here, tried to show how to write a physical hardware driver for Kernel space, but the program is also a loadable module and need or will load after the kernel is live with filesystem.
But as I've said earlier, while engaged with an embedded system, there are comparatively requirements of these work, rather you want to have your all driver, and driver program inside the Kernel binary (uImage / zImage) and let Kernel do those stuff at booting.
Well, its just not difficult, and quite easy. What I've done by myself is,
Kept the hello_world.c program inside ./kernel/driver folder, and edit the ./kernel/driver/Makefile to add
obj-y += hello_world.o
at the end of the Makefile.
Then compile the full kernel and generated zImage transferred to sd-card. While booting, just after USB HID core driver, I am able to see my custom message from hello_world printk(). As,
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.1.15 (linux@linux-VirtualBox) (gcc version 5.3.1 20160413 (Ubuntu/Linaro 5.3.1-14ubuntu2) ) #1 SMP PREEMPT Wed Aug 17 18:09:14 CEST 2016
[ 0.000000] CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7d
[ 15.744840] fec 2188000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[ 17.368140] random: nonblocking pool is initialized
[ 43.937392] Hello World!
And if loading module function is absolutely not in any requirement, just remove it from Kernel build .config.
It also possible just by unselect from #make menuconfig