Compilation of nRF9151 project with TF-M log routed to UART0 results in error "undefined reference to stdio_init"

I'm developing a project, where I use nRF9151 as a GPS sensor, and nRF52833 as a BLE gateway. I want to send data from 9151 to 52833 over one of UARTs. The problems I'm facing now are either runtime or compile time, depending on the set of configurations. I was able to reproduce this issue on the nRF9151DK.

This demo consists of 3 files.
main.c:

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/uart.h>

#include <nrf_modem_gnss.h>
#include <modem/nrf_modem_lib.h>

#include <modem/lte_lc.h>


LOG_MODULE_REGISTER(main_app, LOG_LEVEL_DBG);

int main(void)
{
LOG_DBG("Starting main app thread on hw %s", CONFIG_BOARD);
return 0;
}


const struct device * uart_1 = DEVICE_DT_GET(DT_NODELABEL(uart1));


void uart1_thread(void* p1, void* p2, void* p3)
{
LOG_DBG("Starting UART1 thread");

if (!device_is_ready(uart_1))
{
LOG_ERR("UART1 init failed");
}

const struct uart_config uart_cfg = {
.baudrate = 115200,
.parity = UART_CFG_PARITY_NONE,
.stop_bits = UART_CFG_STOP_BITS_1,
.data_bits = UART_CFG_DATA_BITS_8,
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE
};

int err = uart_configure(uart_1, &uart_cfg);
if (err != 0) {
LOG_ERR("UART1 init failed %d", err);
}

uint8_t tx_buff[32] = {0};
snprintf(tx_buff, 20, "%s\n", "hello world\n");

while(1)
{
k_msleep(1000);
uart_tx(uart_1, tx_buff, 20, SYS_FOREVER_MS);
LOG_DBG("UART 1 msg sent");
}
}

K_THREAD_DEFINE(uart1_thr_id, 1024, uart1_thread, NULL, NULL, NULL, 6, 0, 10);

static int modem_configure(void)
{
int err;

LOG_INF("Initializing modem library");

err = nrf_modem_lib_init();
if (err) {
LOG_ERR("Failed to initialize the modem library, error: %d", err);
return err;
}

return 0;
}


void gps_thread(void* p1, void* p2, void* p3)
{
LOG_DBG("Starting GPS thread");

modem_configure();

LOG_DBG("func mode set");
// if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) {
if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_NORMAL) != 0) {
LOG_ERR("Failed to activate GNSS functional mode");
return;
}

while(1)
{
k_msleep(5000);
LOG_DBG("GPS cycle");
}
}

K_THREAD_DEFINE(gps_thr_id, 1024, gps_thread, NULL, NULL, NULL, 6, 0, 10);


prj.conf (it's taken from another project, so it's not a minimal subset of configs)


CONFIG_GPIO=y

CONFIG_SHELL=y
CONFIG_KERNEL_SHELL=y

CONFIG_SERIAL=y

CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_VT100_COMMANDS=y
CONFIG_SHELL_VT100_COLORS=y
CONFIG_SHELL_STACK_SIZE=4096
CONFIG_SHELL_CMD_BUFF_SIZE=128

CONFIG_SHELL_WILDCARD=n
CONFIG_SHELL_HELP_ON_WRONG_ARGUMENT_COUNT=n
CONFIG_SHELL_STATS=n
CONFIG_SHELL_CMDS=n
CONFIG_SHELL_HISTORY=y

CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_DEBUG_THREAD_INFO=y

# Enable CPP support
CONFIG_CPP=y

CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3

CONFIG_REBOOT=y

CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

CONFIG_NRF_MODEM_LIB=y
CONFIG_NRF_MODEM_LIB_LOG_FW_VERSION_UUID=y

CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_NETWORK_MODE_LTE_M_GPS=y

CONFIG_NRF_MODEM_LIB_FAULT_STRERROR=n

CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1536

# CONFIG_AT_HOST_LIBRARY=y
CONFIG_NRF_MODEM_LIB_SHMEM_RX_SIZE=8192
CONFIG_NRF_MODEM_LIB_SHMEM_TX_SIZE=8192


CONFIG_UART_ASYNC_API=y
CONFIG_UART_0_ASYNC=n
#CONFIG_UART_1_ASYNC=y
#CONFIG_UART_1_INTERRUPT_DRIVEN=n
CONFIG_UART_USE_RUNTIME_CONFIGURE=y

CONFIG_TFM_SECURE_UART0=y
#CONFIG_TFM_LOG_LEVEL_SILENCE=y

nrf9151dk_nrf9151.overlay

&pinctrl {
uart0_default: uart0_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 18)>,
<NRF_PSEL(UART_RX, 0, 17)>;
};
};

uart0_sleep: uart0_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 18)>,
<NRF_PSEL(UART_RX, 0, 17)>;
low-power-enable;
};
};

uart1_default: uart1_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 22)>,
<NRF_PSEL(UART_RX, 0, 21)>;
};
};
uart1_sleep: uart1_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 22)>,
<NRF_PSEL(UART_RX, 0, 21)>;
low-power-enable;
};
};

};

&uart0 {
compatible = "nordic,nrf-uarte";
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart0_default>;
pinctrl-1 = <&uart0_sleep>;
pinctrl-names = "default", "sleep";
};

&uart1 {
compatible = "nordic,nrf-uarte";
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart1_default>;
pinctrl-1 = <&uart1_sleep>;
pinctrl-names = "default", "sleep";
};

I use nRF Connect SDK 3.0.2.

I'm trying to follow this manual: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/security/tfm/tfm_logging.html.
When I use config CONFIG_TFM_SECURE_UART0 , compilation fails with the following error:
nrf-sdk/v3.0.2/modules/tee/tf-m/trusted-firmware-m/platform/ext/target/nordic_nrf/common/core/tfm_hal_platform_common.c:36: undefined reference to `stdio_init'

When at the same time I use config
CONFIG_TFM_LOG_LEVEL_SILENCE=y, compilation works, but when I flash the DK - the board stays silent on both UARTs.

I've also attempted changing TF-M logging properties inside the Kconfig, but it was always resulting either in various compilation errors or a silent board.

Primary question of this post: what config would allow me to compile and link file `uart_stdout.c` (the definition of stdio_init is there)? I have an impression that I'm missing a simple configuration flag.
More global (and more important to me) question: is there a comprehensive guide on how to reliably use UART1 in nRF9151 for inter-MCU communication on a system with TF-M (which is required to run modem firmware)? All my attempts so far ended either in: compilation error, silent board or runtime errors, throwing a secure fault on the first call to the `uart_tx` method of Zephyr UART API
  • roman.turkin said:
    The problem described in this thread is the one that I have been able to reproduce on the devkit.
    The problem I experience on the devkit is slightly different.

    Not sure if I understand. It is the same problem, but slightly different due to what you run on it? Could you try running the same sw on both and see if there is a difference?

    Regards,

    Elfving

  • Alright, I've executed identical code on the DK and ended up in the same issue.
    I'm able to reproduce it in the runtime, and it's not identical to the issue described in the topic.
    I'll create another ticket, and I will use my next reply as an answer (I found solution to the compile time errors)

  • I did not find the solution to the underlying TF-M related problem, but have managed to find the solution of the compilation time problem.

    Recipe: do not rely on the command "clean build configuration"/"pristine build". Only explicit removal of the build directory and recreation of the build configuration helps to achieve a reliable behavior of the build system. After I started removing the build folder upon every major change in either defconfig or prj.conf, these sporadic compilation issues were gone. 

  • Hi  
    I found the rootcause of my underlying issue. It has been a missing return in a function that is supposed to return something.

  • Okay. I agree that it is good to keep the cases on topic, and I understand that having one for each topic makes it easier for both parties.

    roman.turkin said:
    Recipe: do not rely on the command "clean build configuration"/"pristine build". Only explicit removal of the build directory and recreation of the build configuration helps to achieve a reliable behavior of the build system. After I started removing the build folder upon every major change in either defconfig or prj.conf, these sporadic compilation issues were gone. 

    I knew this was a problem in the past, but I am surprised to learn that this is a still an issue. I am glad you noticed, and notifed the forum with your solution.

    Regards,

    Elfving

Related