Trying to use UART2 witn custom nrf9151 board non secure

Hi all,

I'm trying to use uart2 on my custom nrf9151 board, but I'm stuck. As I understand, I use i2c1 so I can't use uart1 and i2c1in parallel, so here is why I wnt to use uart2. 

Here is my configufration: I use P0.23 and P0.24 in my dtsi file

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

	uart2_sleep: uart2_sleep {
		group1 {
			psels = <NRF_PSEL(UART_TX, 0, 23)>,
				<NRF_PSEL(UART_RX, 0, 24)>;
			low-power-enable;
		};
	};

And in overlay file

&uart2 {
    status = "okay";
    current-speed = <115200>;
    pinctrl-0 = <&uart2_default>;
    pinctrl-1 = <&uart2_sleep>;
    pinctrl-names = "default", "sleep";
};

and I've added CONFIG_UART_ASYNC_API=y in my prj.conf. So after all thaht setup I've write uart_async.c file (inspired by devacedemy here)

#define UART_NODE DT_NODELABEL(uart2)
#define RX_BUF_SIZE 64
#define RX_TIMEOUT 100

static const struct device *uart_dev;
static uint8_t rx_buf[RX_BUF_SIZE];

struct tx_msg {
	uint8_t data[64];
	size_t len;
};


static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) {
	switch (evt->type) {

	case UART_TX_DONE:
		LOG_DBG("TX done (%d bytes)", evt->data.tx.len);
		break;

	case UART_TX_ABORTED:
		LOG_ERR("TX aborted");
		break;

	case UART_RX_RDY:
		if (evt->data.rx.len > 0) {
			LOG_INF("RX");
			LOG_HEXDUMP_INF(&evt->data.rx.buf[evt->data.rx.offset],
			                evt->data.rx.len,
			                "RX Data");

			for (size_t i = evt->data.rx.offset; i < evt->data.rx.offset + evt->data.rx.len; i++) {
				if (rx_buf[i] == '\n') {
					LOG_INF("End of message detected");
				}
			}
		}
		break;

	case UART_RX_DISABLED:
		LOG_WRN("RX disabled, re-enabling");
		uart_rx_enable(dev, rx_buf, sizeof(rx_buf), RX_TIMEOUT);
		break;

	case UART_RX_BUF_REQUEST:
		// RX buffer management not used in this basic example
		break;

	case UART_RX_BUF_RELEASED:
		// RX buffer management not used in this basic example
		break;

	case UART_RX_STOPPED:
		LOG_ERR("RX stopped due to error %d", evt->data.rx_stop.reason);
		break;

	default:
		break;
	}
}

int uart_init(void) {
	uart_dev = DEVICE_DT_GET(UART_NODE);
	if (!device_is_ready(uart_dev)) {
		LOG_ERR("UART device not ready");
		return -ENODEV;
	}

	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 ret = uart_configure(uart_dev, &uart_cfg);

	if (ret == -ENOSYS) {
		return -ENOSYS;
	}


	ret = uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), RX_TIMEOUT);
	if (ret) {
		LOG_ERR("Failed to enable UART RX (%d)", ret);
		return ret;
	}

	LOG_INF("UART initialized");
	return 0;
}

int uart_send_data(const uint8_t *data, size_t len) {
	int ret = uart_tx(uart_dev, data, len, SYS_FOREVER_MS);
	if (ret) {
		LOG_ERR("UART TX failed (%d)", ret);
		return ret;
	}
	return 0;
}

and my main

	uart_init();


	static uint8_t tx_buf[] = {
		"nRF Connect SDK Fundamentals Course\r\n"
	};

	uart_send_data(tx_buf, sizeof(tx_buf));
	....

Everything build but when my board boot, I receive my tx data but after thaht my board seem to be freeze nothing happen. If I boot my board without cp21 connected to P0.23/24 my board boot and run normaly, but if I try to send data through my cp21 i receive nothing...

Is there other configuration I missed in non secure to use uart2? It's seem RX pin to somthing, if I unplung it from mycp2102 my board boot normally

Parents
  • Hello,

    I noticed in your code that the RX timeout is only set to 100 us which is too short and may lead to unreliable reception. Please try to set it to  50 milliseconds and see if that fixes the problem. 

    #define RX_TIMEOUT (50 * USEC_PER_MSEC)

    Best regards,

    Vidar

  • Hi Vidar,

    I have a related problem using UART2

    I kept UART0 as the default for the console on the first serial port

    Then configured UART2 out of the arduino header to experiment with the UART peripheral as described this devAcademy course, using a second serial port

    https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-4-serial-communication-uart/

    The RX interface on UART2 is working as expected, meaning I can toggle the LEDS by sending 1/2/3 characters on UART2/second serial port.

    However I cannot get the uart_tx data to write data on the second serial port

    All works well with the uart peripheral configured to UART0

    To configure UART2, I added this overlay file

    nrf9151dk_nrf9151_ns.overlay

    content

    &pinctrl {
       uart2_default: uart2_default {
          group1 {
             psels = <NRF_PSEL(UART_TX, 0, 23)>;
          };
          group2 {
             psels = <NRF_PSEL(UART_RX, 0, 24)>;
             bias-pull-up;
          };
       };

       uart2_sleep: uart2_sleep {
          group1 {
             psels = <NRF_PSEL(UART_TX, 0, 23)>, <NRF_PSEL(UART_RX, 0, 24)>;
             low-power-enable;
          };
       };
    };

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

  • Hi,

    Both pins appear to be available on the DK. As a test, have you tried swapping the TX and RX pins (the TX/RX assignment in nrf9151dk_nrf9151_ns.overlay as well as the physical connections)? Would be interesting to know if RX still works after this. 

    Also, what is the uart connected to, is it another board, or a usb serial bridge?

  • Hi Vidar,

    Thank you for confirming my overlay configuration and the pin availability

    Regarding the serial bridge, that was indeed my problem. I was using an old Schmart board.

    I just switched to an FTDI cable, wired the RX/TX/GND on the arduino heade.

    UART2 is working fine now, both TX and RX.

  • Good to hear you found the problem. Thanks for the update.

  • Hi Vidar,

    Follow up question if I may keep using this ticket --can open a new one otherwise...

    The reason I switched to UART2 was to extend support to SHELL commands using the default console on uart0 (as defined in the nRF9151DK board device tree)

    To that end, I enable the SHELL support adding this single line the prj.conf file

    CONFIG_SHELL=y

    Once I do that, the call to add the uart callback return an error -88

    <err> main: uart_callback_set (-88)

    The call to enable the call is the same

    Is this a known problem on the nRF9151?

    Is there a workaround?

    How to support SHELL command on the uart0/console while keeping the uart2 peripheral working

    Thank you

       ret = uart_callback_set(uart, uart_cb, NULL);
       if (ret)
       {
          LOG_ERR("uart_callback_set (%d)", ret);
          return 4;
       }

Reply
  • Hi Vidar,

    Follow up question if I may keep using this ticket --can open a new one otherwise...

    The reason I switched to UART2 was to extend support to SHELL commands using the default console on uart0 (as defined in the nRF9151DK board device tree)

    To that end, I enable the SHELL support adding this single line the prj.conf file

    CONFIG_SHELL=y

    Once I do that, the call to add the uart callback return an error -88

    <err> main: uart_callback_set (-88)

    The call to enable the call is the same

    Is this a known problem on the nRF9151?

    Is there a workaround?

    How to support SHELL command on the uart0/console while keeping the uart2 peripheral working

    Thank you

       ret = uart_callback_set(uart, uart_cb, NULL);
       if (ret)
       {
          LOG_ERR("uart_callback_set (%d)", ret);
          return 4;
       }

Children
  • Hi,

    -88 (-ENOSYS) indicates that the UART async driver API is not enabled, at least not for this UARTE instance. Please try adding CONFIG_UART_2_ASYNC=y to your prj.conf and watch the build output for any errors/warnings, and if not, see if you still get this runtime warning.

    Note that you can also check your current configuration from the generated .config in your build output.

  • Hi Vidar,

    I had this config already enabled

    CONFIG_UART_ASYNC_API=y

    and now added 

    CONFIG_UART_2_ASYNC=y

    However the latter seems to be forced disabled in the build as I cannot find it in the generated .config file as you indicated.

    Please remember my demo app works fine on UART2, with no error when setting the callback

    ret = uart_callback_set(uart, uart_cb, NULL);

    as long as I keep the CONFIG_SHELL off.

    My test goal is keep the UART2 interface working while also adding support for SHELL commands on the UART0/console

    Thank you

  • Hi,

    I've not investigated why enabling CONFIG_SHELL is affects this configuration. However, you should be seeing a Kconfig warning in the build log saying why CONFIG_UART_2_ASYNC does not end up being selected (I'm assuming it is not set in the .config since it's not working). Try to also add the line below and see if that fixes it.

    CONFIG_UART_2_INTERRUPT_DRIVEN=n
    CONFIG_UART_2_ASYNC=y
  • Hi Vidar,

    thanks for the additional feedback

    I have been able to resolve the problem by using enabling the Interrupt-driven API

    Here is how my prj.conf file looks now

    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_UART_USE_RUNTIME_CONFIGURE=y

    With that I had to trade uart_set_callback() --which seems to be only supported for ASYNC API???

    for uart_irq_callback_user_data_set() –using the callback from the echo_bot zephyr sample

    All is good now: I can have both RX/TX traffic on UART2 while supporting Shell commands on the uart0/console.

    Thanks again for your support

    Jamal

    PS

    I still don't understand why the SHELL component disables the uart Async API??? But this is not blocking anymore

  • I was able to enable CONFIG_UART_2_ASYNC with CONFIG_SHLL=y if I also disabled CONFIG_UART_2_INTERRUPT_DRIVEN. Did you try the same? 

    Jamal_nRF said:
    With that I had to trade uart_set_callback() --which seems to be only supported for ASYNC API???

    Yes, you're right. Please refer to the "UART async driver API" documentation which describes the difference between these.

Related