From ba9df2aa09deeae5d851c59469d782b1a7a0efe4 Mon Sep 17 00:00:00 2001 From: Jack Rosenthal Date: Fri, 8 Jan 2021 15:07:05 -0700 Subject: zephyr: switch to platform/ec printf format implementation Prior to this change, the cprints and cprintf shim implementations used Zephyr's printk to do the output formatting. Our EC code has some custom printf specifiers not supported by Zephyr's printk. We've already attempted to send some of our custom specifiers upstream, but upstream does not want them: https://github.com/zephyrproject-rtos/zephyr/pull/28882 The logical thing to do would be to bring in the vfnprintf function from our EC to the Zephyr build, and use that to do the output formatting instead. That's what this CL does. The binary cost of brining in this second printf implementation appears to be minimal (952 bytes on volteer). BUG=b:177065615 BRANCH=none TEST=on posix-ec and volteer, run gettime and observe output no longer contains %.6lld, but instead the correct system time Signed-off-by: Jack Rosenthal Change-Id: I53cd4edf129223c12a2c5e7d0519623a8d07a328 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2618575 --- common/printf.c | 12 ++++++++++- zephyr/CMakeLists.txt | 1 + zephyr/shim/src/console.c | 11 ++++++++-- zephyr/shim/src/util.c | 44 ++++++++++++++++++++++++++++++++++++++++ zephyr/test/hooks/CMakeLists.txt | 2 ++ zephyr/test/i2c/CMakeLists.txt | 3 ++- 6 files changed, 69 insertions(+), 4 deletions(-) diff --git a/common/printf.c b/common/printf.c index f876a1da19..039a83a92f 100644 --- a/common/printf.c +++ b/common/printf.c @@ -275,7 +275,9 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, continue; /* %pT - print a timestamp. */ if (ptrspec == 'T' && - !IS_ENABLED(NO_UINT64_SUPPORT)) { + !IS_ENABLED(NO_UINT64_SUPPORT) && + (!IS_ENABLED(CONFIG_ZEPHYR) || + IS_ENABLED(CONFIG_PLATFORM_EC_TIMER))) { flags |= PF_64BIT; if (ptrval == PRINTF_TIMESTAMP_NOW) v = get_time().val; @@ -461,6 +463,12 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, return EC_SUCCESS; } +/* + * These symbols are already defined by the Zephyr OS kernel, and we + * don't want to use the EC implementation. + */ +#ifndef CONFIG_ZEPHYR + /* Context for snprintf() */ struct snprintf_context { char *str; @@ -516,3 +524,5 @@ int vsnprintf(char *str, int size, const char *format, va_list args) return (rv == EC_SUCCESS) ? (ctx.str - str) : -rv; } + +#endif /* !CONFIG_ZEPHYR */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 68f7382cc6..28620657d4 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -40,6 +40,7 @@ add_subdirectory_ifdef(CONFIG_PLATFORM_EC "shim") # supported by all boards and emulators (including unit tests) using the shim # layer. zephyr_sources_ifdef(CONFIG_PLATFORM_EC "${PLATFORM_EC}/common/base32.c" + "${PLATFORM_EC}/common/printf.c" "${PLATFORM_EC}/common/queue.c" "${PLATFORM_EC}/common/shared_mem.c") diff --git a/zephyr/shim/src/console.c b/zephyr/shim/src/console.c index f59bda2f63..f07b56cf2f 100644 --- a/zephyr/shim/src/console.c +++ b/zephyr/shim/src/console.c @@ -10,12 +10,19 @@ #include #include "console.h" +#include "printf.h" int cputs(enum console_channel channel, const char *str) { return cprintf(channel, "%s", str); } +static int printk_putchar(void *context, int c) +{ + printk("%c", c); + return 0; +} + static void console_vprintf(enum console_channel channel, const char *format, va_list args) { @@ -27,7 +34,7 @@ static void console_vprintf(enum console_channel channel, const char *format, * use shell_ print functions instead of printk function as they could * be on different uarts (they are not for Chrome OS Apps though). */ - vprintk(format, args); + vfnprintf(printk_putchar, NULL, format, args); } __attribute__((__format__(__printf__, 2, 3))) int @@ -46,7 +53,7 @@ cprints(enum console_channel channel, const char *format, ...) { va_list args; - cprintf(channel, "[%lld ", k_uptime_get()); + cprintf(channel, "[%pT ", PRINTF_TIMESTAMP_NOW); va_start(args, format); console_vprintf(channel, format, args); va_end(args); diff --git a/zephyr/shim/src/util.c b/zephyr/shim/src/util.c index 3181fccb95..5a7131b23a 100644 --- a/zephyr/shim/src/util.c +++ b/zephyr/shim/src/util.c @@ -161,3 +161,47 @@ int parse_offset_size(int argc, char **argv, int shift, int *offset, int *size) return EC_SUCCESS; } + +int uint64divmod(uint64_t *n, int d) +{ + uint64_t q = 0, mask; + int r = 0; + + /* Divide-by-zero returns zero */ + if (!d) { + *n = 0; + return 0; + } + + /* Common powers of 2 = simple shifts */ + if (d == 2) { + r = *n & 1; + *n >>= 1; + return r; + } else if (d == 16) { + r = *n & 0xf; + *n >>= 4; + return r; + } + + /* If v fits in 32-bit, we're done. */ + if (*n <= 0xffffffff) { + uint32_t v32 = *n; + r = v32 % d; + *n = v32 / d; + return r; + } + + /* Otherwise do integer division the slow way. */ + for (mask = (1ULL << 63); mask; mask >>= 1) { + r <<= 1; + if (*n & mask) + r |= 1; + if (r >= d) { + r -= d; + q |= mask; + } + } + *n = q; + return r; +} diff --git a/zephyr/test/hooks/CMakeLists.txt b/zephyr/test/hooks/CMakeLists.txt index e44ebfe674..2236963762 100644 --- a/zephyr/test/hooks/CMakeLists.txt +++ b/zephyr/test/hooks/CMakeLists.txt @@ -23,5 +23,7 @@ zephyr_include_directories( # Include test file, test under test and console dependency target_sources(app PRIVATE hooks.c) +target_sources(app PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../../common/printf.c") target_sources(app PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../shim/src/hooks.c") target_sources(app PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../shim/src/console.c") +target_sources(app PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../shim/src/util.c") diff --git a/zephyr/test/i2c/CMakeLists.txt b/zephyr/test/i2c/CMakeLists.txt index 94c5deb8cc..4edbfb9006 100644 --- a/zephyr/test/i2c/CMakeLists.txt +++ b/zephyr/test/i2c/CMakeLists.txt @@ -25,4 +25,5 @@ target_sources(app PRIVATE "${PLATFORM_EC}/zephyr/shim/src/console.c" "${PLATFORM_EC}/zephyr/shim/src/i2c.c" "${PLATFORM_EC}/zephyr/shim/src/util.c" - "${PLATFORM_EC}/common/i2c_controller.c") + "${PLATFORM_EC}/common/i2c_controller.c" + "${PLATFORM_EC}/common/printf.c") -- cgit v1.2.1