scripts: gen_kobject_list: Generate enums and case statements

Adding a new kernel object type or driver subsystem requires changes
in various different places.  This patch makes it easier to create
those devices by generating as much as possible in compile time.

No behavior change.

Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
This commit is contained in:
Leandro Pereira 2018-04-05 13:59:33 -07:00 committed by Anas Nashif
parent c200367b68
commit 39dc7d03f7
8 changed files with 106 additions and 74 deletions

View file

@ -376,6 +376,8 @@ add_custom_command(
)
add_custom_target(driver_validation_h_target DEPENDS ${DRV_VALIDATION})
include($ENV{ZEPHYR_BASE}/cmake/kobj.cmake)
gen_kobj(KOBJ_INCLUDE_PATH)
# Generate offsets.c.obj from offsets.c
# Generate offsets.h from offsets.c.obj
@ -390,6 +392,7 @@ add_dependencies( offsets
syscall_list_h_target
syscall_macros_h_target
driver_validation_h_target
kobj_types_h_target
)
add_custom_command(

27
cmake/kobj.cmake Normal file
View file

@ -0,0 +1,27 @@
function(gen_kobj gen_dir_out)
if (PROJECT_BINARY_DIR)
set(gen_dir ${PROJECT_BINARY_DIR}/include/generated)
else ()
set(gen_dir ${CMAKE_BINARY_DIR}/include/generated)
endif ()
set(KOBJ_TYPES ${gen_dir}/kobj-types-enum.h)
set(KOBJ_OTYPE ${gen_dir}/otype-to-str.h)
file(MAKE_DIRECTORY ${gen_dir})
add_custom_command(
OUTPUT ${KOBJ_TYPES} ${KOBJ_OTYPE}
COMMAND
${PYTHON_EXECUTABLE}
$ENV{ZEPHYR_BASE}/scripts/gen_kobject_list.py
--kobj-types-output ${KOBJ_TYPES}
--kobj-otype-output ${KOBJ_OTYPE}
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_custom_target(kobj_types_h_target DEPENDS ${KOBJ_TYPES} ${KOBJ_OTYPE})
set(${gen_dir_out} ${gen_dir} PARENT_SCOPE)
endfunction ()

View file

@ -211,13 +211,6 @@ Creating New Core Kernel Objects
* In ``scripts/gen_kobject_list.py``, add the name of the struct to the
:py:data:`kobjects` list.
* The name of the enumerated type is derived from the name of the struct.
Take the name of the struct, remove the first two characters, convert to
uppercase, and prepend ``K_OBJ_`` to it. Add the enum to
:cpp:enum:`k_objects` in include/kernel.h. For example, ``struct k_foo``
should be enumerated as ``K_OBJ_FOO``.
* Add a string representation for the enum to the
:c:func:`otype_to_str()` function in kernel/userspace.c
Instances of the new struct should now be tracked.
@ -229,13 +222,6 @@ what API struct they are set to.
* In ``scripts/gen_kobject_list.py``, add the name of the API struct for the
new subsystem to the :py:data:`subsystems` list.
* Take the name of the API struct, remove the trailing "_driver_api" from its
name, convert to uppercase, and prepend ``K_OBJ_DRIVER_`` to it. This is
the name of the enumerated type, which should be added to
:cpp:enum:`k_objects` in include/kernel.h. For example, ``foo_driver_api``
should be enumerated as ``K_OBJ_DRIVER_FOO``.
* Add a string representation for the enum to the
:c:func:`otype_to_str()` function in ``kernel/userspace.c``
Driver instances of the new subsystem should now be tracked.

View file

@ -293,7 +293,11 @@ Several macros exist to validate arguments:
fails. The latter should only be used for the most obvious of tests.
* :c:macro:`_SYSCALL_DRIVER_OP()` checks at runtime if a driver
instance is capable of performing a particular operation.
instance is capable of performing a particular operation. While this
macro can be used by itself, it's mostly a building block for macros
that are automatically generated for every driver subsytem. For
instance, to validate the GPIO driver, one could use the
:c:macro:`_SYSCALL_DRIVER_GPIO()` macro.
If any check fails, a kernel oops will be triggered which will kill the
calling thread. This is done instead of returning some error condition to

View file

@ -28,61 +28,10 @@ const char *otype_to_str(enum k_objects otype)
*/
#ifdef CONFIG_PRINTK
switch (otype) {
/* Core kernel objects */
case K_OBJ_ALERT:
return "k_alert";
case K_OBJ_MSGQ:
return "k_msgq";
case K_OBJ_MUTEX:
return "k_mutex";
case K_OBJ_PIPE:
return "k_pipe";
case K_OBJ_SEM:
return "k_sem";
case K_OBJ_STACK:
return "k_stack";
case K_OBJ_THREAD:
return "k_thread";
case K_OBJ_TIMER:
return "k_timer";
case K_OBJ__THREAD_STACK_ELEMENT:
return "k_thread_stack_t";
/* Driver subsystems */
case K_OBJ_DRIVER_ADC:
return "adc driver";
case K_OBJ_DRIVER_AIO_CMP:
return "aio comparator driver";
case K_OBJ_DRIVER_COUNTER:
return "counter driver";
case K_OBJ_DRIVER_CRYPTO:
return "crypto driver";
case K_OBJ_DRIVER_DMA:
return "dma driver";
case K_OBJ_DRIVER_FLASH:
return "flash driver";
case K_OBJ_DRIVER_GPIO:
return "gpio driver";
case K_OBJ_DRIVER_I2C:
return "i2c driver";
case K_OBJ_DRIVER_I2S:
return "i2s driver";
case K_OBJ_DRIVER_IPM:
return "ipm driver";
case K_OBJ_DRIVER_PINMUX:
return "pinmux driver";
case K_OBJ_DRIVER_PWM:
return "pwm driver";
case K_OBJ_DRIVER_ENTROPY:
return "entropy driver";
case K_OBJ_DRIVER_RTC:
return "realtime clock driver";
case K_OBJ_DRIVER_SENSOR:
return "sensor driver";
case K_OBJ_DRIVER_SPI:
return "spi driver";
case K_OBJ_DRIVER_UART:
return "uart driver";
/* otype-to-str.h is generated automatically during build by
* gen_kobject_list.py
*/
#include <otype-to-str.h>
default:
return "?";
}

View file

@ -141,6 +141,51 @@ def write_validation_output(fp):
fp.write("#endif /* __DRIVER_VALIDATION_GEN_H__ */\n")
def write_kobj_types_output(fp):
fp.write("/* Core kernel objects */\n")
for kobj in kobjects:
if kobj == "device":
continue
if kobj.startswith("k_"):
kobj = kobj[2:]
elif kobj.startswith("_k_"):
kobj = kobj[2:]
fp.write("K_OBJ_%s,\n" % kobj.upper())
fp.write("/* Driver subsystems */\n")
for subsystem in subsystems:
subsystem = subsystem.replace("_driver_api", "").upper()
fp.write("K_OBJ_DRIVER_%s,\n" % subsystem)
def write_kobj_otype_output(fp):
fp.write("/* Core kernel objects */\n")
for kobj in kobjects:
if kobj == "device":
continue
if kobj.startswith("k_"):
kobj = kobj[2:]
elif kobj.startswith("_k_"):
kobj = kobj[2:]
fp.write('case K_OBJ_%s: return "%s";\n' % (
kobj.upper(),
kobj
))
fp.write("/* Driver subsystems */\n")
for subsystem in subsystems:
subsystem = subsystem.replace("_driver_api", "")
fp.write('case K_OBJ_DRIVER_%s: return "%s driver";\n' % (
subsystem.upper(),
subsystem
))
def parse_args():
global args
@ -156,6 +201,12 @@ def parse_args():
parser.add_argument(
"-V", "--validation-output", required=False,
help="Output driver validation macros")
parser.add_argument(
"-K", "--kobj-types-output", required=False,
help="Output k_object enum values")
parser.add_argument(
"-S", "--kobj-otype-output", required=False,
help="Output case statements for otype_to_str()")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print extra debugging information")
args = parser.parse_args()
@ -187,6 +238,13 @@ def main():
with open(args.validation_output, "w") as fp:
write_validation_output(fp)
if args.kobj_types_output:
with open(args.kobj_types_output, "w") as fp:
write_kobj_types_output(fp)
if args.kobj_otype_output:
with open(args.kobj_otype_output, "w") as fp:
write_kobj_otype_output(fp)
if __name__ == "__main__":
main()

View file

@ -1,3 +1,3 @@
include($ENV{ZEPHYR_BASE}/tests/unit/unittest.cmake)
project(none)
include($ENV{ZEPHYR_BASE}/tests/unit/unittest.cmake)

View file

@ -18,17 +18,22 @@ if(NOT SOURCES)
set(SOURCES main.c)
endif()
add_executable(testbinary ${SOURCES})
include($ENV{ZEPHYR_BASE}/cmake/kobj.cmake)
add_dependencies(testbinary kobj_types_h_target)
gen_kobj(KOBJ_GEN_DIR)
list(APPEND INCLUDE
tests/ztest/include
tests/include
include
.
)
add_executable(testbinary ${SOURCES})
)
target_compile_options(testbinary PRIVATE
-Wall
-I ${KOBJ_GEN_DIR}
${EXTRA_CPPFLAGS_AS_LIST}
${EXTRA_CFLAGS_AS_LIST}
$<$<COMPILE_LANGUAGE:CXX>:${EXTRA_CXXFLAGS_AS_LIST}>