diff --git a/include/arch/arm/CortexM/scripts/linker.cmd b/include/arch/arm/CortexM/scripts/linker.cmd index a8e74720ebb..329afe4daf1 100644 --- a/include/arch/arm/CortexM/scripts/linker.cmd +++ b/include/arch/arm/CortexM/scripts/linker.cmd @@ -43,6 +43,10 @@ Linker script for the Cortex-M3 BSPs. #include +#define INIT_LEVEL(level) \ + __initconfig##level##_start = .; \ + *(.initconfig##level##.init) \ + /* physical address of RAM */ #ifdef CONFIG_XIP #define ROMABLE_REGION FLASH @@ -100,6 +104,14 @@ SECTIONS *(".text.*") } GROUP_LINK_IN(ROMABLE_REGION) + SECTION_PROLOGUE (devconfig, (OPTIONAL),) + { + __devconfig_start = .; + *(".devconfig.*") + KEEP(*(SORT_BY_NAME(".devconfig*"))) + __devconfig_end = .; + } GROUP_LINK_IN(ROMABLE_REGION) + SECTION_PROLOGUE(.ARM.exidx,,) { /* @@ -155,6 +167,21 @@ SECTIONS *(".data.*") } GROUP_LINK_IN(RAMABLE_REGION) + SECTION_PROLOGUE (initlevel, (OPTIONAL),) + { + __initconfig_start = .; + INIT_LEVEL(0) + INIT_LEVEL(1) + INIT_LEVEL(2) + INIT_LEVEL(3) + INIT_LEVEL(4) + INIT_LEVEL(5) + INIT_LEVEL(6) + INIT_LEVEL(7) + KEEP(*(SORT_BY_NAME(".initconfig*"))) + __initconfig_end = .; + } GROUP_LINK_IN(RAMABLE_REGION) + __data_ram_end = .; SECTION_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) diff --git a/include/arch/x86/linker-common-sections.h b/include/arch/x86/linker-common-sections.h index c0de33f3261..4ed8e4809f0 100644 --- a/include/arch/x86/linker-common-sections.h +++ b/include/arch/x86/linker-common-sections.h @@ -71,6 +71,10 @@ order when programming the MMU. #include +#define INIT_LEVEL(level) \ + __initconfig##level##_start = .; \ + *(.initconfig##level##.init) \ + /* SECTIONS definitions */ SECTIONS { @@ -107,6 +111,13 @@ SECTIONS KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE) } GROUP_LINK_IN(ROMABLE_REGION) + SECTION_PROLOGUE (devconfig, (OPTIONAL),) + { + __devconfig_start = .; + *(".devconfig.*") + KEEP(*(SORT_BY_NAME(".devconfig*"))) + __devconfig_end = .; + } GROUP_LINK_IN(ROMABLE_REGION) SECTION_PROLOGUE(_RODATA_SECTION_NAME, (OPTIONAL),) { @@ -136,6 +147,21 @@ SECTIONS . = ALIGN(4); } GROUP_LINK_IN(RAM) + SECTION_PROLOGUE (initlevel, (OPTIONAL),) + { + __initconfig_start = .; + INIT_LEVEL(0) + INIT_LEVEL(1) + INIT_LEVEL(2) + INIT_LEVEL(3) + INIT_LEVEL(4) + INIT_LEVEL(5) + INIT_LEVEL(6) + INIT_LEVEL(7) + KEEP(*(SORT_BY_NAME(".initconfig*"))) + __initconfig_end = .; + } GROUP_LINK_IN(RAM) + __data_ram_end = .; SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD OPTIONAL),) diff --git a/include/device.h b/include/device.h new file mode 100644 index 00000000000..c40bac38465 --- /dev/null +++ b/include/device.h @@ -0,0 +1,89 @@ + +/* Copyright (c) 2015 Intel Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DEVICE_H_ +#define _DEVICE_H_ + +/*! @def DECLARE_DEVICE_INIT_CONFIG + * + * @brief Define an config object + * + * @details This macro declares an config object to be placed in the + * image by the linker in the ROM region. + * + * @param cfg_name Name of the config object to be created. This name + * must be used in the *_init() macro(s) defined in init.h so the + * linker can associate the config object with the correct init + * object. + * + * @param drv_name The name this instance of the driver exposes to + * the system. + * @param init_fn Address to the init function of the driver. + * @param config The address to the structure containing the + * configuration information for this instance of the driver. + * + * @sa __define_initconfig() + */ +#define DECLARE_DEVICE_INIT_CONFIG(cfg_name, drv_name, init_fn, config) \ + static struct device_config config_##cfg_name __used \ + __attribute__((__section__(".devconfig.init"))) = { \ + .name = drv_name, .init = (init_fn), \ + .config_info = (config) \ + };\ + +struct device; + +/* Static device infomation (In ROM) Per driver instance */ +struct device_config { + /*! name of the device */ + char *name; + /*! init function for the driver */ + int (*init)(struct device *device); + /*! address of driver instance config information */ + void *config_info; +}; + +/* Runtime device structure (In memory) Per driver instance */ +struct device { + /*! Build time config information */ + struct device_config *config; + /*! pointer to structure containing the API functions for the + * device type. This pointer is filled in by the driver at + * init time. + */ + void *driver_api; + /*! Driver instance data. For driver use only*/ + void *driver_data; +}; + +void device_do_config_level(int level); +struct device* device_get_binding(char *name); + +#endif /* _DEVICE_H_ */ diff --git a/include/init.h b/include/init.h new file mode 100644 index 00000000000..04e9a8c925d --- /dev/null +++ b/include/init.h @@ -0,0 +1,68 @@ + +/* Copyright (c) 2015 Intel Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _INIT_H_ +#define _INIT_H_ + +#include +#define __used __attribute__((__used__)) + +/*! @def __define_initconfig + * + * @brief Define an init object + * + * @details This macro declares an init object to be placed a + * given init level section in the image. This macro not should be used + * directly. + * + * @param cfg_name Name of the config object created with + * DECLARE_DEVICE_INIT_CONFIG() macro that will be referenced by + * init object. + * + * @param id The init level id where the init object will be placed + * in the image. + * + * @sa DECLARE_DEVICE_INIT_CONFIG() + */ +#define __define_initconfig(cfg_name, id) \ + static struct device (__initconfig_##cfg_name##id) __used \ + __attribute__((__section__(".initconfig" #id ".init"))) = { \ + .config = &(config_##cfg_name)}; + +#define pure_init(cfg) __define_initconfig(cfg, 0) +#define nano_early_init(cfg) __define_initconfig(cfg, 1) +#define nano_late_init(cfg) __define_initconfig(cfg, 2) +#define micro_early_init(cfg) __define_initconfig(cfg, 3) +#define micro_late_init(cfg) __define_initconfig(cfg, 4) +#define pre_app_init(cfg) __define_initconfig(cfg, 5) +#define late_initconfig(cfg) __define_initconfig(cfg, 6) + + +#endif /* _INIT_H_ */ diff --git a/kernel/nanokernel/Makefile b/kernel/nanokernel/Makefile index 15361d924aa..034c1764e36 100644 --- a/kernel/nanokernel/Makefile +++ b/kernel/nanokernel/Makefile @@ -7,7 +7,7 @@ asflags-y := ${ccflags-y} obj-y = nano_fiber.o nano_lifo.o \ nano_fifo.o nano_stack.o nano_timer.o \ nano_context.o nano_init.o nano_sema.o \ - version.o ctors.o + version.o ctors.o device.o obj-$(CONFIG_STACK_CANARIES) += compiler_stack_protect.o obj-$(CONFIG_INT_LATENCY_BENCHMARK) += int_latency_bench.o diff --git a/kernel/nanokernel/device.c b/kernel/nanokernel/device.c new file mode 100644 index 00000000000..a3f1bed7107 --- /dev/null +++ b/kernel/nanokernel/device.c @@ -0,0 +1,75 @@ +#include +#include +#include + +extern struct device __initconfig_start[]; +extern struct device __initconfig0_start[]; +extern struct device __initconfig1_start[]; +extern struct device __initconfig2_start[]; +extern struct device __initconfig3_start[]; +extern struct device __initconfig4_start[]; +extern struct device __initconfig5_start[]; +extern struct device __initconfig6_start[]; +extern struct device __initconfig7_start[]; +extern struct device __initconfig_end[]; + +static struct device *config_levels[] = { + __initconfig0_start, + __initconfig1_start, + __initconfig2_start, + __initconfig3_start, + __initconfig4_start, + __initconfig5_start, + __initconfig6_start, + __initconfig7_start, + __initconfig_end, +}; + +/*! + * @brief Execute all the driver init functions at a given level + * + * @details Driver init objects are created with the + * __define_initconfig() macro and are placed in RAM by the linker + * script. The {nano|micro}kernel code will execute the init level at + * the appropriate time. + * + * @param level init level to run. + */ +void device_do_config_level(int level) +{ + struct device *info; + + for (info = config_levels[level]; info < config_levels[level+1]; info++) { + struct device_config *device = info->config; + device->init(info); + } +} + +/*! + * @brief Retrieve the device structure for a driver by name + * + * @details Driver config object are created via the + * DECLARE_DEVICE_INIT_CONFIG() macro and placed in ROM by the + * linker. If a driver needs to bind to another driver it will use + * this function to retrieve the device structure of the lower level + * driver by the name the driver exposes to the system. + * + * @param name driver name to search for. + */ +struct device* device_get_binding(char *name) +{ + struct device *info; + struct device *found = 0; + int level; + + for (level = 0; level < ARRAY_SIZE(config_levels) - 1; level++) { + for (info = config_levels[level]; + info < config_levels[level+1]; info++) { + struct device_config *device = info->config; + if (!strcmp(name, device->name)) { + return info; + } + } + } + return found; +}