PRINTK over SWD

How can I properly set up the SWD interface for printk on a custom PCB? I have to build my project example and see the message printed on the VS Code console. My custom hardware does not have a UART connection broken out and I am programming my custom hardware over SWD with a nrf53DK board. I tried other solutions but none of them worked. This is my setup:

dts file:

/ {
	model = "Atreides";
	compatible = "lA,atreides";

	chosen {
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
		zephyr,code-partition = &slot0_ns_partition;
		zephyr,console = &uart2;
		zephyr,shell-uart = &uart2;
		zephyr,bt-uart = &uart2;
		zephyr,bt-mon-uart = &uart2;
		zephyr,bt-c2h-uart = &uart2;
		zephyr,bt-hci-rpmsg-ipc = &ipc0;
	};

	zephyr,user {
		EN_GATE-gpios = <&gpio0 0 0>;
		OC_ADJ-gpios = <&gpio0 1 0>;
		NFAULT-gpios = <&gpio0 2 0>;
		M_OC-gpios = <&gpio0 4 0>;
		NOCTW-gpios = <&gpio0 3 0>;
		Stepper3_EN-gpios = <&gpio0 6 0>;
		Stepper4_STEP-gpios = <&gpio0 8 0>;
		Stepper3_STEP-gpios = <&gpio0 7 0>;
		Stepper4_EN-gpios = <&gpio0 9 0>;
		Stepper4_DIR-gpios = <&gpio0 10 0>;
		Fan_Enable-gpios = <&gpio0 11 0>;
		Stepper1_DIR-gpios = <&gpio0 26 0>;
		Stepper1_STEP-gpios = <&gpio0 27 0>;
		Stepper1_EN-gpios = <&gpio0 30 0>;
		Stepper2_DIR-gpios = <&gpio0 31 0>;
		Stepper3_DIR-gpios = <&gpio1 3 0>;
		Stepper2_STEP-gpios = <&gpio1 11 0>;
		Stepper2_EN-gpios = <&gpio1 13 0>;
		INH_A-gpios = <&gpio1 1 0>;
		INH_B-gpios = <&gpio1 0 0>;
		INH_C-gpios = <&gpio1 15 0>;
		INL_A-gpios = <&gpio0 12 0>;
		INL_B-gpios = <&gpio0 29 0>;
		INL_C-gpios = <&gpio1 10 0>;
		SX1280_M1-gpios = <&gpio1 6 0>;
		SX1280_M2-gpios = <&gpio1 4 0>;
		SX1280_M0-gpios = <&gpio0 23 0>;
	};

};

&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x0 0x10000>;
		};
		slot0_partition: partition@10000 {
			label = "image-0";
			reg = <0x10000 0x40000>;
		};
		slot0_ns_partition: partition@50000 {
			label = "image-0-nonsecure";
			reg = <0x50000 0x30000>;
		};
		slot1_partition: partition@80000 {
			label = "image-1";
			reg = <0x80000 0x40000>;
		};
		slot1_ns_partition: partition@c0000 {
			label = "image-1-nonsecure";
			reg = <0xc0000 0x30000>;
		};
		scratch_partition: partition@f0000 {
			label = "image-scratch";
			reg = <0xf0000 0xa000>;
		};
		storage_partition: partition@fa000 {
			label = "storage";
			reg = <0xfa000 0x6000>;
		};
	};
};



/* Default shared SRAM planning when building for nRF5340.
* This file is included by both nRF5340 CPUAPP (Application MCU)
* and nRF5340 CPUNET (Network MCU).
* - 64 kB SRAM allocated as Shared memory (sram0_shared)
* - Region defined after the image SRAM of Application MCU
*/

/ {
    chosen {
        /* shared memory reserved for the inter-processor communication */
        zephyr,ipc_shm = &sram0_shared;
    };

    reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;

        sram0_shared: memory@20070000 {
            /* SRAM allocated to shared memory */
            reg = <0x20070000 0x10000>;
        };
    };
};

&gpio0 {
	status = "okay";
};

&gpio1 {
	status = "okay";
};

&i2c1 {
	WPS_front: WPS_front@77{
        compatible = "i2c-device";
        reg = < 0x77 >;
        label = "WPS_front";
    };
	VisionController: VisionController@50{
        compatible = "i2c-device";
        reg = < 0x50 >;
        label = "VisionController";
    };
	clock-frequency = <I2C_BITRATE_STANDARD>;
	status = "okay";
	pinctrl-0 = <&i2c1_default>;
	pinctrl-names = "default";
};

&i2c0 {
	//BMI270
    bmi_270: bmi_270@69{
        compatible = "i2c-device";
        reg = < 0x69 >; 
        label = "BMI270-IMU"; 
    };

    //Multiplexer with IMUs
    BUS_0_MUX_1: BUS_0_MUX_1@70{
        compatible = "i2c-device";
        reg = < 0x70 >;  
        label = "BUS_0_MUX_1";
    };

    WPS_rear: WPS_rear@77{
        compatible = "i2c-device";
        reg = < 0x77 >;
        label = "WPS_rear";
    };

	status = "okay";
	pinctrl-0 = <&i2c0_default>;
	pinctrl-names = "default";
};

&uart2 {
	GPS {
        compatible = "uart-device";
    };
	status = "okay";
	pinctrl-0 = <&uart2_default>;
	pinctrl-names = "default";
	current-speed = <115200>;
};

&uart3 {
	SX1280 {
        compatible = "uart-device";
    };
	status = "okay";
	current-speed = <115200>;
	pinctrl-0 = <&uart3_default>;
	pinctrl-names = "default";
};

&spi4 {
	status = "okay";
	pinctrl-0 = <&spi4_default>;
	pinctrl-names = "default";
	cs-gpios = <&gpio1 5 0>;
};

&rtc0 {
	status = "disabled";
};

&qspi {
	status = "okay";
	pinctrl-0 = <&qspi_default>;
	pinctrl-names = "default";
};

&adc {
	status = "disabled";
};

&gpiote1 {
	status = "okay";
};

deconfig:

# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_SOC_SERIES_NRF53X=y
CONFIG_SOC_NRF5340_CPUAPP_QKAA=y
CONFIG_BOARD_ATREIDES=y

# Enable MPU
CONFIG_ARM_MPU=y

# Enable hardware stack protection
CONFIG_HW_STACK_PROTECTION=y

# Enable TrustZone-M
CONFIG_ARM_TRUSTZONE_M=y

# This Board implies building Non-Secure firmware
CONFIG_TRUSTED_EXECUTION_NONSECURE=y

# enable GPIO
CONFIG_GPIO=y

# enable PINCTRL
CONFIG_PINCTRL=y

# Enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_UART_CONSOLE=n
CONFIG_CONSOLE=y

# Enable RTT
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

CONFIG_LOG=y

prj.conf:

CONFIG_I2C=y
CONFIG_BT=y
CONFIG_BT_DEVICE_NAME="BT-DEV"

CONFIG_PWM=y

CONFIG_UART_ASYNC_API=y

CONFIG_BT_PERIPHERAL=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=y

# STEP 12 - Update Data Length and MTU
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_L2CAP_TX_MTU=247

# Increase stack size for the main thread and System Workqueue
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=2048

CONFIG_UART_INTERRUPT_DRIVEN=y

CONFIG_NRF53_SYNC_RTC=n

CONFIG_LOG_PRINTK=y
CONFIG_PRINTK=y

main.c

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(AtreidesLogs,LOG_LEVEL_DBG);

int main(void)
{
    printk("Init Test");
	LOG_DBG("A log message in debug level");

    while(1){
        printk("Init Test");
        k_sleep(K_MSEC(1000));
    }
}

RTT Output:

SEGGER J-Link V7.88j - Real time terminal output
SEGGER J-Link (unknown) V1.0, SN=1050051574
Process: JLinkExe

Parents
  • Hi,

    I recommend the Nordic Developer Academy as an excellent place to start learning the nRF Connect SDK.

    For how to change pins for your board, you need pinctrl.

    Here is what our AI says about pinctrl:

    The pinctrl (pin control) is a feature used in Nordic Semiconductor's nRF Connect SDK to manage the pin configurations of various peripherals on the device. It allows you to assign different pins to the peripherals based on states. The two standard states are default and sleep.
    In the pinctrl node, pin configurations are organized in groups within each sub-node. Each group specifies a list of pin function selections in the psels property. For example, a group could specify the pin configurations for UART_TX and UART_RTS. A group can also specify shared pin properties common to all specified pins.
    Here's an example of how pin configurations are being applied in the TWIM driver:
    &pinctrl {
     i2c0_default_alt: i2c0_default_alt {
     group1 {
     psels = <NRF_PSEL(TWIM_SDA, 1, 13)>,
     <NRF_PSEL(TWIM_SCL, 1, 15)>;
     };
     };
     i2c0_sleep_alt: i2c0_sleep_alt {
     group1 {
     psels = <NRF_PSEL(TWIM_SDA, 1, 13)>,
     <NRF_PSEL(TWIM_SCL, 1, 15)>;
     low-power-enable;
     };
     };
    };
    In this example, the i2c0_default_alt and i2c0_sleep_alt nodes define the pin configurations for the I2C peripheral in its default and sleep states, respectively. The psels property in each group specifies the function (SDA or SCL) and pin number for each pin.
    For more information, you can refer to the Nordic Semiconductor's DevZone forum and Nordic Semiconductor's Academy Course.
  • Hello, I’m sorry but a forgot to add my pinctrl file. Everything builds and works I am just not able to use printk over SWD


    pinctrl.dtsi

    
    

    &pinctrl {
    i2c0_default: i2c0_default {
    group1 {
    psels = <NRF_PSEL(TWIM_SCL, 1, 12)>, <NRF_PSEL(TWIM_SDA, 1, 14)>;
    };
    };

    i2c1_default: i2c1_default {
    group1 {
    psels = <NRF_PSEL(TWIM_SDA, 0, 5)>, <NRF_PSEL(TWIM_SCL, 1, 2)>;
    };
    };

    spi4_default: spi4_default {
    group1 {
    psels = <NRF_PSEL(SPIM_MISO, 1, 9)>,
    <NRF_PSEL(SPIM_MOSI, 1, 8)>,
    <NRF_PSEL(SPIM_SCK, 1, 7)>;
    };
    };

    uart2_default: uart2_default {
    group1 {
    psels = <NRF_PSEL(UART_RX, 0, 24)>, <NRF_PSEL(UART_TX, 0, 25)>;
    };
    };

    uart3_default: uart3_default {
    group1 {
    psels = <NRF_PSEL(UART_RX, 0, 21)>, <NRF_PSEL(UART_TX, 0, 19)>;
    };
    };

    qspi_default: qspi_default {
    group1 {
    psels = <NRF_PSEL(QSPI_CSN, 0, 18)>,
    <NRF_PSEL(QSPI_IO0, 0, 13)>,
    <NRF_PSEL(QSPI_IO1, 0, 14)>,
    <NRF_PSEL(QSPI_IO2, 0, 15)>,
    <NRF_PSEL(QSPI_IO3, 0, 16)>,
    <NRF_PSEL(QSPI_SCK, 0, 17)>;
    };
    };
    };

  • Can you specify what you mean by "printk over SWD"?

  • Okay so I would like to debug and print statements to the console using printk. I have a custom board featuring nRF5340 and a programming interface that I connect to the DK in order to program it, using SWDIO, SWDCLK and RESET. I would like to print via SWDIO using RTT. I tried to follow this solution:

     Setting up console over SWD interface 

    However my configuration just does not work 

Reply Children
Related