diff --git a/CODEOWNERS b/CODEOWNERS index 57b86f853167..72eb74ebaeff 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -154,6 +154,7 @@ /drivers/clock_control/*esp32* @extremegtx /drivers/clock_control/*npcx* @MulinChao /drivers/counter/ @nordic-krch +/drivers/console/ipm_console.c @finikorg /drivers/console/semihost_console.c @luozhongyao /drivers/counter/counter_cmos.c @andrewboie /drivers/counter/maxim_ds3231.c @pabigot diff --git a/boards/xtensa/up_squared_adsp/tools/mbterm.py b/boards/xtensa/up_squared_adsp/tools/mbterm.py new file mode 100755 index 000000000000..e37181ff6f07 --- /dev/null +++ b/boards/xtensa/up_squared_adsp/tools/mbterm.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +from time import sleep +from mmap import mmap, ACCESS_COPY +from ctypes import c_uint8 + +from lib.device import Device +import lib.registers as regs + +MBOX = 0x91281000 +LENGTH = 0x1000 + +with open("/dev/mem", "rb") as f: + mem_map = mmap(f.fileno(), LENGTH, access=ACCESS_COPY, offset=MBOX) + mem = (c_uint8 * LENGTH).from_buffer(mem_map) + +def mailbox_poll_mem(dev): + while True: + if dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_BUSY: + + # Use only id for passing character + line_len = dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_MSG + + # Mask out internal bits + line_len &= 0x10FFFF + + if line_len: + print(bytes(mem[:line_len]).decode()) + + # Clear interrupt + dev.dsp_hipct.value |= regs.ADSP_IPC_HIPCT_BUSY + else: + sleep(0.005) + +# Character passed in mailbox ID field +def mailbox_poll_char(dev): + while True: + if dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_BUSY: + + # Use only id for passing character + character = dev.dsp_hipct.value & regs.ADSP_IPC_HIPCT_MSG + + # Get readable character + character &= 0x10FFFF + + print('{}'.format(chr(character)), end='') + + # Clear interrupt + dev.dsp_hipct.value |= regs.ADSP_IPC_HIPCT_BUSY + else: + sleep(0.005) + + +if __name__ == "__main__": + # Clear Done if needed + #dev.dsp_hipct.value |= regs.ADSP_IPC_HIPCT_BUSY + + # Use Device library for controlling registers + device = Device() + device.open_device() + + mailbox_poll_mem(device) diff --git a/boards/xtensa/up_squared_adsp/up_squared_adsp.dts b/boards/xtensa/up_squared_adsp/up_squared_adsp.dts index 0ec6488fd65c..b328d67d7157 100644 --- a/boards/xtensa/up_squared_adsp/up_squared_adsp.dts +++ b/boards/xtensa/up_squared_adsp/up_squared_adsp.dts @@ -14,5 +14,6 @@ chosen { zephyr,sram = &sram0; + zephyr,console = &ipm_console; }; }; diff --git a/drivers/console/CMakeLists.txt b/drivers/console/CMakeLists.txt index 46b6eb53fdb8..a7097f660779 100644 --- a/drivers/console/CMakeLists.txt +++ b/drivers/console/CMakeLists.txt @@ -5,6 +5,7 @@ zephyr_sources_ifdef(CONFIG_RAM_CONSOLE ram_console.c) zephyr_sources_ifdef(CONFIG_RTT_CONSOLE rtt_console.c) zephyr_sources_ifdef(CONFIG_IPM_CONSOLE_RECEIVER ipm_console_receiver.c) zephyr_sources_ifdef(CONFIG_IPM_CONSOLE_SENDER ipm_console_sender.c) +zephyr_sources_ifdef(CONFIG_IPM_CONSOLE ipm_console.c) zephyr_sources_ifdef(CONFIG_UART_MCUMGR uart_mcumgr.c) zephyr_sources_ifdef(CONFIG_UART_PIPE uart_pipe.c) zephyr_sources_ifdef(CONFIG_XTENSA_SIM_CONSOLE xtensa_sim_console.c) diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig index 7abb8efeac82..31d58d7fc652 100644 --- a/drivers/console/Kconfig +++ b/drivers/console/Kconfig @@ -168,6 +168,32 @@ config IPM_CONSOLE_STACK_SIZE thread to print out incoming messages from the remote CPU. Specify the stack size for these threads here. +config IPM_CONSOLE + bool "Inter-processor Mailbox console" + depends on IPM + select CONSOLE_HAS_DRIVER + help + Enable console over Inter-processor Mailbox. + +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_IPM_CONSOLE := zephyr,console + +config IPM_CONSOLE_ON_DEV_NAME + string "IPM device name used by console" + default "$(dt_chosen_label,$(DT_CHOSEN_Z_IPM_CONSOLE))" if HAS_DTS + default "IPM_0" + depends on IPM_CONSOLE + help + IPM device name used by IPM console driver. + +config IPM_CONSOLE_LINE_BUF_LEN + int "IPM console line buffer length" + default 128 + depends on IPM_CONSOLE + help + IPM console line buffer length specify amount of the buffer + where characters are stored before sending the whole line. + config UART_PIPE bool "Enable pipe UART driver" select UART_INTERRUPT_DRIVEN diff --git a/drivers/console/ipm_console.c b/drivers/console/ipm_console.c new file mode 100644 index 000000000000..852daff61927 --- /dev/null +++ b/drivers/console/ipm_console.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(ipm_console, CONFIG_IPM_LOG_LEVEL); + +struct device *ipm_dev; + +static int console_out(int c) +{ + static char buf[CONFIG_IPM_CONSOLE_LINE_BUF_LEN]; + static size_t len; + int ret; + + if (c != '\n' && len < sizeof(buf)) { + buf[len++] = c; + return c; + } + + ret = ipm_send(ipm_dev, 1, len, buf, len); + if (ret) { + LOG_ERR("Error sending character %c over IPM, ret %d", c, ret); + } + + memset(buf, 0, sizeof(buf)); + len = 0; + + /* After buffer is full start a new one */ + if (c != '\n') { + buf[len++] = c; + } + + return c; +} + +#if defined(CONFIG_STDOUT_CONSOLE) +extern void __stdout_hook_install(int (*hook)(int)); +#else +#define __stdout_hook_install(x) \ + do { /* nothing */ \ + } while ((0)) +#endif + +#if defined(CONFIG_PRINTK) +extern void __printk_hook_install(int (*fn)(int)); +#else +#define __printk_hook_install(x) \ + do { /* nothing */ \ + } while ((0)) +#endif + +/* Install printk/stdout hooks */ +static void ipm_console_hook_install(void) +{ + __stdout_hook_install(console_out); + __printk_hook_install(console_out); +} + +static int ipm_console_init(struct device *dev) +{ + ARG_UNUSED(dev); + + LOG_DBG("IPM console initialization"); + + ipm_dev = device_get_binding(CONFIG_IPM_CONSOLE_ON_DEV_NAME); + if (!ipm_dev) { + LOG_ERR("Cannot get %s", CONFIG_IPM_CONSOLE_ON_DEV_NAME); + return -ENODEV; + } + + if (ipm_max_id_val_get(ipm_dev) < CONFIG_IPM_CONSOLE_LINE_BUF_LEN) { + LOG_ERR("IPM driver does not support buffer length %d", + CONFIG_IPM_CONSOLE_LINE_BUF_LEN); + return -ENOTSUP; + } + + ipm_console_hook_install(); + + return 0; +} + +/* Need to be initialized after IPM */ +SYS_INIT(ipm_console_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/dts/bindings/ipm/zephyr,ipm-console.yaml b/dts/bindings/ipm/zephyr,ipm-console.yaml new file mode 100644 index 000000000000..8159b089f58e --- /dev/null +++ b/dts/bindings/ipm/zephyr,ipm-console.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2020 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: IPM console + +compatible: "zephyr,ipm-console" + +include: uart-device.yaml + +properties: + label: + required: true diff --git a/dts/xtensa/intel/intel_apl_adsp.dtsi b/dts/xtensa/intel/intel_apl_adsp.dtsi index fc5d8b93a1b2..615791003a40 100644 --- a/dts/xtensa/intel/intel_apl_adsp.dtsi +++ b/dts/xtensa/intel/intel_apl_adsp.dtsi @@ -99,5 +99,10 @@ interrupt-parent = <&cavs0>; label = "IPM_0"; }; + + ipm_console: ipm_console { + compatible = "zephyr,ipm-console"; + label="IPM_0"; + }; }; }; diff --git a/scripts/sanity_chk/sanitylib.py b/scripts/sanity_chk/sanitylib.py index 34f2e933cf37..2814cd79a9b8 100644 --- a/scripts/sanity_chk/sanitylib.py +++ b/scripts/sanity_chk/sanitylib.py @@ -575,7 +575,7 @@ def handle(self): master, slave = pty.openpty() try: - ser_pty_process = subprocess.Popen(serial_pty, stdout=master, stdin=master, stderr=master) + ser_pty_process = subprocess.Popen(re.split(',| ', serial_pty), stdout=master, stdin=master, stderr=master) except subprocess.CalledProcessError as error: logger.error("Failed to run subprocess {}, error {}".format(serial_pty, error.output)) return diff --git a/soc/xtensa/intel_apl_adsp/Kconfig.defconfig b/soc/xtensa/intel_apl_adsp/Kconfig.defconfig index 7736d86009bd..f439ab68b64a 100644 --- a/soc/xtensa/intel_apl_adsp/Kconfig.defconfig +++ b/soc/xtensa/intel_apl_adsp/Kconfig.defconfig @@ -43,8 +43,9 @@ config TEST_LOGGING_DEFAULTS if LOG +# When console is enabled printk should go through it config LOG_PRINTK - default y + default y if !CONSOLE config LOG_BACKEND_RB default y @@ -57,7 +58,6 @@ config LOG_BACKEND_RB_MEM_SIZE endif # LOG - if SMP config MP_NUM_CPUS @@ -80,4 +80,13 @@ config SCHED_IPI_SUPPORTED endif +config IPM_INTEL_ADSP + default y + depends on IPM + +config IPM_CONSOLE + default y + depends on CONSOLE + depends on IPM + endif diff --git a/soc/xtensa/intel_apl_adsp/adsp.c b/soc/xtensa/intel_apl_adsp/adsp.c index cdc58b810608..9109fa347f91 100644 --- a/soc/xtensa/intel_apl_adsp/adsp.c +++ b/soc/xtensa/intel_apl_adsp/adsp.c @@ -123,4 +123,5 @@ static int adsp_init(struct device *dev) return 0; } -SYS_INIT(adsp_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +/* Init after IPM initialization and before logging (uses memory windows) */ +SYS_INIT(adsp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);