Hardware studies specific
Overview
This wiki article an effort to fully understand Zephyr RTOS facilities to fully configure, at start time and dynamically throughout run time I2C peripherals supported by Zephyr and given microcontroller Hardware Abstraction Layer (HAL) code.
Contents
^ 2022-05-02 Monday
Search for Zephyr's I2C peripheral configuration code . . .
ted@localhost:~/projects/zephyr-based/hardware-Stage1-firmware-aws-iot-stand-alone/build$ grep -nr i2c_configure ./* ./mcuboot/zephyr/include/generated/syscall_dispatch.c:668:uintptr_t z_mrsh_i2c_configure(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, ./mcuboot/zephyr/include/generated/syscall_dispatch.c:1412: [K_SYSCALL_I2C_CONFIGURE] = z_mrsh_i2c_configure, ./mcuboot/zephyr/include/generated/syscalls/i2c.h:24:extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); ./mcuboot/zephyr/include/generated/syscalls/i2c.h:25:static inline int i2c_configure(const struct device * dev, uint32_t dev_config) ./mcuboot/zephyr/include/generated/syscalls/i2c.h:33: return z_impl_i2c_configure(dev, dev_config); ./mcuboot/zephyr/include/generated/syscalls/i2c_configure_mrsh.c:10:extern int z_vrfy_i2c_configure(const struct device * dev, uint32_t dev_config); ./mcuboot/zephyr/include/generated/syscalls/i2c_configure_mrsh.c:11:uintptr_t z_mrsh_i2c_configure(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, ./mcuboot/zephyr/include/generated/syscalls/i2c_configure_mrsh.c:19: int ret = z_vrfy_i2c_configure(*(const struct device **)&arg0, *(uint32_t*)&arg1) ./mcuboot/zephyr/misc/generated/syscalls.json:1159: "int i2c_configure", ./spm/zephyr/include/generated/syscall_dispatch.c:668:uintptr_t z_mrsh_i2c_configure(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, ./spm/zephyr/include/generated/syscall_dispatch.c:1412: [K_SYSCALL_I2C_CONFIGURE] = z_mrsh_i2c_configure, ./spm/zephyr/include/generated/syscalls/i2c.h:24:extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); ./spm/zephyr/include/generated/syscalls/i2c.h:25:static inline int i2c_configure(const struct device * dev, uint32_t dev_config) ./spm/zephyr/include/generated/syscalls/i2c.h:33: return z_impl_i2c_configure(dev, dev_config); ./spm/zephyr/include/generated/syscalls/i2c_configure_mrsh.c:10:extern int z_vrfy_i2c_configure(const struct device * dev, uint32_t dev_config); ./spm/zephyr/include/generated/syscalls/i2c_configure_mrsh.c:11:uintptr_t z_mrsh_i2c_configure(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, ./spm/zephyr/include/generated/syscalls/i2c_configure_mrsh.c:19: int ret = z_vrfy_i2c_configure(*(const struct device **)&arg0, *(uint32_t*)&arg1) ./spm/zephyr/misc/generated/syscalls.json:1159: "int i2c_configure", ./zephyr/include/generated/syscall_dispatch.c:668:uintptr_t z_mrsh_i2c_configure(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, ./zephyr/include/generated/syscall_dispatch.c:1412: [K_SYSCALL_I2C_CONFIGURE] = z_mrsh_i2c_configure, ./zephyr/include/generated/syscalls/i2c.h:24:extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); ./zephyr/include/generated/syscalls/i2c.h:25:static inline int i2c_configure(const struct device * dev, uint32_t dev_config) ./zephyr/include/generated/syscalls/i2c.h:33: return z_impl_i2c_configure(dev, dev_config); ./zephyr/include/generated/syscalls/i2c_configure_mrsh.c:10:extern int z_vrfy_i2c_configure(const struct device * dev, uint32_t dev_config); ./zephyr/include/generated/syscalls/i2c_configure_mrsh.c:11:uintptr_t z_mrsh_i2c_configure(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, ./zephyr/include/generated/syscalls/i2c_configure_mrsh.c:19: int ret = z_vrfy_i2c_configure(*(const struct device **)&arg0, *(uint32_t*)&arg1) ./zephyr/misc/generated/syscalls.json:1159: "int i2c_configure", ted@vibratsiya:~/projects/zephyr-based/hardware-Stage1-firmware-aws-iot-stand-alone/build$
- STEP - To identify first reference to routine i2c_configure() in Zephyr based project build artifacts.
An excerpt from file `ncs/project_root/build/zephyr/include/generated/syscalls/i2c.h:
24 extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); 25 static inline int i2c_configure(const struct device * dev, uint32_t dev_config) 26 { 27 #ifdef CONFIG_USERSPACE 28 if (z_syscall_trap()) { 29 return (int) arch_syscall_invoke2(*(uintptr_t *)&dev, *(uintptr_t *)&dev_config, K_SYSCALL_I2C_CONFIGURE); 30 } 31 #endif 32 compiler_barrier(); 33 return z_impl_i2c_configure(dev, dev_config); 34 }
Search results:
ted@vibratsiya:~/projects/zephyr-based/hardware-Stage1-firmware-aws-iot-stand-alone/build$ grep -nr z_impl_i2c_configure ./* ./mcuboot/zephyr/include/generated/syscalls/i2c.h:24:extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); ./mcuboot/zephyr/include/generated/syscalls/i2c.h:33: return z_impl_i2c_configure(dev, dev_config); ./spm/zephyr/include/generated/syscalls/i2c.h:24:extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); ./spm/zephyr/include/generated/syscalls/i2c.h:33: return z_impl_i2c_configure(dev, dev_config); ./zephyr/include/generated/syscalls/i2c.h:24:extern int z_impl_i2c_configure(const struct device * dev, uint32_t dev_config); ./zephyr/include/generated/syscalls/i2c.h:33: return z_impl_i2c_configure(dev, dev_config);
Hmm kind of dead ending here, no routine definitions found in either `zephyr` source tree nor `nrf` code projects. And `west build -t menuconfig` session shows CONFIG_USERSPACE=n.
- STEP - A search for CONFIG_PULL_UP symbol among Zephyr sources:
Subset of many results . . .
./boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common.dts:47: gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; ./boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common.dts:51: gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; ./boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common.dts:55: gpios = <&gpio0 6 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; ./boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common.dts:59: gpios = <&gpio0 7 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; ./boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common_0_14_0.dtsi:38: int-gpios = <&gpio0 6 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
^ Search For I2C Configuration Source Code
1 "nrf":"/home/ted/projects/zephyr-based/nrf":"/home/ted/projects/zephyr-based/nrf" 2 "openthread":"/home/ted/projects/zephyr-based/modules/lib/openthread":"/home/ted/projects/zephyr-based/modules/lib/openthread/zephyr" 3 "mcuboot":"/home/ted/projects/zephyr-based/bootloader/mcuboot":"${ZEPHYR_MCUBOOT_CMAKE_DIR}" 4 "trusted-firmware-m":"/home/ted/projects/zephyr-based/modules/tee/tfm":"${ZEPHYR_TRUSTED_FIRMWARE_M_CMAKE_DIR}" 5 "tfm-mcuboot":"/home/ted/projects/zephyr-based/modules/tee/tfm-mcuboot":"" 6 "cjson":"/home/ted/projects/zephyr-based/modules/lib/cjson":"${ZEPHYR_CJSON_CMAKE_DIR}" 7 "pelion-dm":"/home/ted/projects/zephyr-based/modules/lib/pelion-dm":"/home/ted/projects/zephyr-based/modules/lib/pelion-dm/zephyr/cmake" 8 "cddl-gen":"/home/ted/projects/zephyr-based/modules/lib/cddl-gen":"${ZEPHYR_CDDL_GEN_CMAKE_DIR}" 9 "memfault-firmware-sdk":"/home/ted/projects/zephyr-based/modules/lib/memfault-firmware-sdk":"/home/ted/projects/zephyr-based/modules/lib/memfaul t-firmware-sdk/ports/zephyr" 10 "cmsis":"/home/ted/projects/zephyr-based/modules/hal/cmsis":"/home/ted/projects/zephyr-based/modules/hal/cmsis" 11 "canopennode":"/home/ted/projects/zephyr-based/modules/lib/canopennode":"/home/ted/projects/zephyr-based/modules/lib/canopennode" 12 "civetweb":"/home/ted/projects/zephyr-based/modules/lib/civetweb":"/home/ted/projects/zephyr-based/modules/lib/civetweb" 13 "fatfs":"/home/ted/projects/zephyr-based/modules/fs/fatfs":"/home/ted/projects/zephyr-based/modules/fs/fatfs" 14 "hal_nordic":"/home/ted/projects/zephyr-based/modules/hal/nordic":"${ZEPHYR_HAL_NORDIC_CMAKE_DIR}" 15 "st":"/home/ted/projects/zephyr-based/modules/hal/st":"/home/ted/projects/zephyr-based/modules/hal/st" 16 "libmetal":"/home/ted/projects/zephyr-based/modules/hal/libmetal":"/home/ted/projects/zephyr-based/modules/hal/libmetal" 17 "lvgl":"/home/ted/projects/zephyr-based/modules/lib/gui/lvgl":"/home/ted/projects/zephyr-based/modules/lib/gui/lvgl" 18 "mbedtls":"/home/ted/projects/zephyr-based/modules/crypto/mbedtls":"${ZEPHYR_MBEDTLS_CMAKE_DIR}" 19 "mcumgr":"/home/ted/projects/zephyr-based/modules/lib/mcumgr":"/home/ted/projects/zephyr-based/modules/lib/mcumgr" 20 "open-amp":"/home/ted/projects/zephyr-based/modules/lib/open-amp":"/home/ted/projects/zephyr-based/modules/lib/open-amp" 21 "loramac-node":"/home/ted/projects/zephyr-based/modules/lib/loramac-node":"/home/ted/projects/zephyr-based/modules/lib/loramac-node/zephyr" 22 "segger":"/home/ted/projects/zephyr-based/modules/debug/segger":"${ZEPHYR_SEGGER_CMAKE_DIR}" 23 "tinycbor":"/home/ted/projects/zephyr-based/modules/lib/tinycbor":"/home/ted/projects/zephyr-based/modules/lib/tinycbor/zephyr" 24 "tinycrypt":"/home/ted/projects/zephyr-based/modules/crypto/tinycrypt":"/home/ted/projects/zephyr-based/modules/crypto/tinycrypt" 25 "littlefs":"/home/ted/projects/zephyr-based/modules/fs/littlefs":"/home/ted/projects/zephyr-based/modules/fs/littlefs" 26 "mipi-sys-t":"/home/ted/projects/zephyr-based/modules/debug/mipi-sys-t":"/home/ted/projects/zephyr-based/modules/debug/mipi-sys-t" 27 "nrf_hw_models":"/home/ted/projects/zephyr-based/modules/bsim_hw_models/nrf_hw_models":"/home/ted/projects/zephyr-based/modules/bsim_hw_models/n rf_hw_models" 28 "TraceRecorder":"/home/ted/projects/zephyr-based/modules/debug/TraceRecorder":"${ZEPHYR_TRACERECORDER_CMAKE_DIR}" 29 "nrfxlib":"/home/ted/projects/zephyr-based/nrfxlib":"${ZEPHYR_NRFXLIB_CMAKE_DIR}" 30 "connectedhomeip":"/home/ted/projects/zephyr-based/modules/lib/matter":"/home/ted/projects/zephyr-based/modules/lib/matter/config/nrfconnect/chi p-module" ~ ~ ~ ~ ~ ~ ~ "zephyr_modules.txt" 30L, 3486C
Out of these Zephyr modules built as part of our project the hal related ones appear to be:
- cmsis
- hal_nordic
- st
- libmetal
And possibly `nrfxlib`.
./zephyr/drivers/i2c/i2c_handlers.c
3
- STEP 1 -
$ grep -nr z_vrfy_i2c_configure ./*
./zephyr/drivers/i2c/i2c_handlers.c:11:static inline int z_vrfy_i2c_configure(const struct device *dev,
7 #include <drivers/i2c.h> 8 #include <string.h> 9 #include <syscall_handler.h> 10 11 static inline int z_vrfy_i2c_configure(const struct device *dev, 12 uint32_t dev_config) 13 { 14 Z_OOPS(Z_SYSCALL_DRIVER_I2C(dev, configure)); 15 return z_impl_i2c_configure((const struct device *)dev, dev_config); 16 } 17 #in
- STEP 2 -
./zephyr/include/drivers/i2c.h:310:static inline int z_impl_i2c_configure(const struct device *dev,
298 /** 299 * @brief Configure operation of a host controller. 300 * 301 * @param dev Pointer to the device structure for the driver instance. 302 * @param dev_config Bit-packed 32-bit value to the device runtime configuration 303 * for the I2C controller. 304 * 305 * @retval 0 If successful. 306 * @retval -EIO General input / output error, failed to configure device. 307 */ 308 __syscall int i2c_configure(const struct device *dev, uint32_t dev_config); 309 310 static inline int z_impl_i2c_configure(const struct device *dev, 311 uint32_t dev_config) 312 { 313 const struct i2c_driver_api *api = 314 (const struct i2c_driver_api *)dev->api; 315 316 return api->configure(dev, dev_config); 317 }
- STEP 3 -
./zephyr/include/drivers/i2c.h:137:__subsystem struct i2c_driver_api {
137 __subsystem struct i2c_driver_api { 138 i2c_api_configure_t configure; 139 i2c_api_full_io_t transfer; 140 i2c_api_slave_register_t slave_register; 141 i2c_api_slave_unregister_t slave_unregister; 142 i2c_api_recover_bus_t recover_bus; 143 };
. . . This code looks familiar and very similar to constructs we needed to implement for Kionix out-of-tree Zephyr driver, work cerca 2021 Q3.
Zephyr source i2c_nrfx_twim dot c
First reply to Devzone post 87549 points us to study some Zephyr sources in `~/projects/zephyr-based/zephyr/drivers/i2c`.