<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/104410/uart-pins-remapping-at-run-time</link><description>Hello, 
 I have multiple UART devices connected to various pins on my nRF5340, but due to hardware limitations, I can only use two UARTs concurrently alongside interfaces like SPI and I2C. To address this constraint, I need the ability to dynamically</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 23 Oct 2024 10:03:09 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/104410/uart-pins-remapping-at-run-time" /><item><title>RE: UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/thread/507543?ContentTypeID=1</link><pubDate>Wed, 23 Oct 2024 10:03:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e31ceb1f-ba2a-428a-b81f-0c5731aae079</guid><dc:creator>hugo_98</dc:creator><description>&lt;p&gt;Hi,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I encountered the same use case for my application where everything must be reconfigure at runtime and we try not to lose the functionnalities offered by Zephyr Services built on top of the driver api. I found a solution based on the use of Device Runtime Power Management and the pin switching is done via pincontroller API.&lt;/p&gt;
&lt;p&gt;My configuration : ncs 2.7.0&lt;/p&gt;
&lt;p&gt;This solution works only for UART driver, with the &amp;lt;zephyr/drivers/serial/uart_nrfx_uarte.c&amp;gt; at the end, as far as I know.&lt;/p&gt;
&lt;p&gt;What we need to do, in a nutshell :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;disable/deinitialise the uart driver ie. uarte peripheral and interruptions basically&lt;/li&gt;
&lt;li&gt;retreive the pinctrl config of interest&lt;/li&gt;
&lt;li&gt;apply the new pinctrl config&lt;/li&gt;
&lt;li&gt;enable/reinitialise the uart driver&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From the application perspective, there is no way to deinitialise the uart driver directly. But looking at the&amp;nbsp;&lt;span&gt;&amp;lt;zephyr/&lt;/span&gt;&lt;span&gt;drivers/serial/uart_nrfx_uarte.c&amp;gt; PM action callback implementation, I found something really interesting :&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1729676151134v2.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;You can configure the driver not to handle the automatic pin initialisation when switching power state using Kconfig option&amp;nbsp;&lt;/span&gt;CONFIG_UART_n_GPIO_MANAGEMENT (n is the uart instance id)&lt;span&gt;. Given that, we are able to deinitialise/reinitialise the uart driver properly using&amp;nbsp;Device Runtime Power Management.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;prj.conf (fragment):&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_PM=y
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y

CONFIG_UART_0_GPIO_MANAGEMENT=n # UARTE0 pins must be controlled independantly because the peripheral is used for multiple devices.

CONFIG_PINCTRL_DYNAMIC=y&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Now let&amp;#39;s configure the pins !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I use the empty pinctrl-N slots to add my other pin configurations in the devicetree.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="json"&gt;&amp;amp;uart0 {
    status = &amp;quot;okay&amp;quot;;

    pinctrl-0 = &amp;lt;&amp;amp;uart0_default&amp;gt;;
    pinctrl-1 = &amp;lt;&amp;amp;uart0_sleep&amp;gt;;
    pinctrl-2 = &amp;lt;&amp;amp;uart0_gsm&amp;gt;;
    pinctrl-3 = &amp;lt;&amp;amp;uart0_gnss&amp;gt;;
    pinctrl-names = &amp;quot;default&amp;quot;,&amp;quot;sleep&amp;quot;,&amp;quot;gsm&amp;quot;,&amp;quot;gnss&amp;quot;;
};&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;Although &amp;quot;default&amp;quot; state refers PINCTRL_STATE_DEFAULT and&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;quot;sleep&amp;quot; state refers PINCTRL_STATE_SLEEP as expected,&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;quot;gsm&amp;quot; and &amp;quot;gnss&amp;quot; states are custom states whose corresponding macro names&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;PINCTRL_STATE_GSM and PINCTRL_STATE_GNSS will be generated at build time.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;These names are unknown from the uart driver&amp;#39;s perspective :&amp;nbsp;at this point we hit serious compilations problem in case we try to build the project.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;The first option I thought about was modifying the uart_nrfx_uarte.c source code, adding my new pinctrl states definitions on the top of the file like we can see in other drivers. Easy but not sexy.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;So I looked for another option more &amp;quot;project specific&amp;quot;, end I ended up providing these macro definitions to the compiler via my project&amp;#39;s CMakeLists.txt, using Zephyr&amp;#39;s cmake extention&amp;nbsp;&lt;/span&gt;&lt;/span&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;zephyr_compile_definitions().&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(custom_dts_binding)

# This is a convenience hack : we need it to inform the uart driver that these states exists, without
# having to modify the uart driver itself.
zephyr_compile_definitions(PINCTRL_STATE_GSM=2 PINCTRL_STATE_GNSS=3)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})&lt;/pre&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;Now gcc shouldn&amp;#39;t complain anymore (at least about unknown pinctlr states).&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;In the application code, the dynamic switch is handled like this:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**
 * @brief Initialize runtime power management for uart0
 *
 * @return int
 */
static int switch_init__PM_METHOD(void)
{
	int err;
	err = pm_device_runtime_enable(p_uarte0_dev);
	if (err != 0)
	{
		printf(&amp;quot;The PM device runtime is not ready.\n&amp;quot;);
		return err;
	}

	err = pm_device_runtime_get(p_uarte0_dev);
	if (err != 0)
	{
		printf(&amp;quot;The PM device still suspended.\n&amp;quot;);
		return err;
	}
	return 0;
}

/**
 * @brief Switch uart0 pins dynamically to gsm pins
 *
 * @return int
 */
static int switch_uarte0_to_gsm__PM_METHOD(void)
{
	int ret;

	// The device (UARTE0) must be configured with CONFIG_UART_0_GPIO_MANAGEMENT disabled,
	// otherwise, this call ant further pm_device_runtime_get() will set pinctrl depending on SLEEP and DEFAULT states.
	ret = pm_device_runtime_put(p_uarte0_dev);
	if (ret &amp;lt; 0)
	{
		return ret;
	}

	// Now we fetch the pin config of interest.
	const struct pinctrl_dev_config *p_config = PINCTRL_DT_DEV_CONFIG_GET(UARTE_NODE);
	ret = pinctrl_apply_state(p_config, PINCTRL_STATE_GSM);
	if (ret &amp;lt; 0)
	{
		return ret;
	}

	// And we can resume our device through PM, which won&amp;#39;t
	// touch pinctrl.
	ret = pm_device_runtime_get(p_uarte0_dev);
	if (ret &amp;lt; 0)
	{
		return ret;
	}

	printf(&amp;quot;Switched UARTE0 to GSM\n&amp;quot;);
	return 0;
}&lt;/pre&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;All the best,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;Hugo&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/thread/502825?ContentTypeID=1</link><pubDate>Tue, 17 Sep 2024 21:50:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:934b747a-cdbd-47d2-9cd1-39d1a26c6fef</guid><dc:creator>JakeJ</dc:creator><description>&lt;p&gt;I know this is an old thread but it might be easiest to just change the&amp;nbsp;&amp;nbsp;PSEL.TXD, and&amp;nbsp;&amp;nbsp;PSEL.RXD registers for the specific UART in the HW versus the other suggested methods. You can have your thread change this and wait a certain amount of time for any current TX transactions to finish (assuming you don&amp;#39;t need very tightly timed switch over). Or see this about using pin control groups and dynamically selecting at runtime&amp;nbsp;&lt;a href="https://docs.zephyrproject.org/latest/hardware/pinctrl/index.html"&gt;Pin Control &amp;mdash; Zephyr Project Documentation&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/thread/453372?ContentTypeID=1</link><pubDate>Tue, 31 Oct 2023 18:32:33 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:deb8090c-ac70-4dc3-bed1-1cfc5a2122cc</guid><dc:creator>&amp;#216;ivind</dc:creator><description>&lt;p&gt;Hi again, we prefer that users create a new ticket for issues which do not fall under the topic of the original ticket.&lt;/p&gt;
&lt;p&gt;That being said, I believe the data for the event would be stored in:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;p_event.data.rx.p_data&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The structure for nrfx_uarte_event_t is:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/** @brief Structure for the UARTE transfer completion event. */
typedef struct
{
    uint8_t * p_data; ///&amp;lt; Pointer to memory used for transfer.
    size_t    bytes;  ///&amp;lt; Number of bytes transfered.
} nrfx_uarte_xfer_evt_t;

/** @brief Structure for UARTE error event. */
typedef struct
{
    nrfx_uarte_xfer_evt_t rx;         ///&amp;lt; Transfer details, including number of bytes received.
    uint32_t              error_mask; ///&amp;lt; Mask of error flags that generated the event.
} nrfx_uarte_error_evt_t;

/** @brief Structure for UARTE event. */
typedef struct
{
    nrfx_uarte_evt_type_t type; ///&amp;lt; Event type.
    union
    {
        nrfx_uarte_xfer_evt_t  rx;    ///&amp;lt; Data provided for RX completion events.
        nrfx_uarte_xfer_evt_t  tx;    ///&amp;lt; Data provided for TX completion events.
        nrfx_uarte_error_evt_t error; ///&amp;lt; Data provided for error event.
    } data;                           ///&amp;lt; Union to store event data.
} nrfx_uarte_event_t;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Please make a new ticket if you need further support on how to handle the event data.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/thread/453258?ContentTypeID=1</link><pubDate>Tue, 31 Oct 2023 12:16:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6949a196-345b-47e8-bdf4-4157794fdbaa</guid><dc:creator>vinodsdw</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;While using the nrfx driver, what zephyr mechanism I can use to collect the data received inside the below handler ?&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Function for handling UARTE driver events.&lt;br /&gt; *&lt;br /&gt; * @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available&lt;br /&gt; * only within the context of the event handler.&lt;br /&gt; * @param[in] p_context Context passed to the interrupt handler, set on initialization. In this example&lt;br /&gt; * p_context is used to pass the address of the UARTE instance that calls this handler.&lt;br /&gt; */&lt;br /&gt;static void uarte_handler(nrfx_uarte_event_t const * p_event, void * p_context)&lt;br /&gt;{&lt;br /&gt; nrfx_uarte_t * p_inst = p_context;&lt;br /&gt; if (p_event-&amp;gt;type == NRFX_UARTE_EVT_TX_DONE)&lt;br /&gt; {&lt;br /&gt; NRFX_LOG_INFO(&amp;quot;--&amp;gt; UARTE event: TX done&amp;quot;);&lt;br /&gt; NRFX_LOG_INFO(&amp;quot;Content of TX buffer: %s&amp;quot;, m_tx_buffer);&lt;br /&gt; NRFX_LOG_INFO(&amp;quot;Content of RX buffer: %s&amp;quot;, m_rx_buffer);&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt; NRFX_LOG_INFO(&amp;quot;UARTE event: %d&amp;quot;, p_event-&amp;gt;type);&lt;br /&gt; }&lt;br /&gt; nrfx_uarte_uninit(p_inst);&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;Can I push the data to zephyr os fifo?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/thread/448994?ContentTypeID=1</link><pubDate>Thu, 05 Oct 2023 11:49:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:54e5e410-448e-4de3-881e-7608ed20ad2b</guid><dc:creator>vinodsdw</dc:creator><description>&lt;p&gt;Thanks, I will try it and will update you.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: UART PINS REMAPPING AT RUN TIME</title><link>https://devzone.nordicsemi.com/thread/448992?ContentTypeID=1</link><pubDate>Thu, 05 Oct 2023 11:46:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dc694536-fe70-4086-8de1-f268ec095e67</guid><dc:creator>&amp;#216;ivind</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;For this you should disable uart2 in the devicetree and use our nrfx driver api directly. The Zephyr driver uses this api, but has some limitations, as you correctly point out.&lt;/p&gt;
&lt;p&gt;You can find a sample for using uart through this api at &amp;lt;SDK&amp;gt;/modules/hal/nordic/nrfx/samples/src/nrfx_uarte/tx_rx_non_blocking&lt;/p&gt;
&lt;p&gt;You will need to uninit the peripheral, then reinit it to change the pins. You also need to make a nrfx_uarte_config_t for each desired setup and use these when you reinit.&lt;/p&gt;
&lt;p&gt;Here are the header files with the api for uart and uarte(with DMA), I have highlighted the init and uninit functions for you:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nrfconnect/sdk-hal_nordic/blob/main/nrfx/drivers/include/nrfx_uart.h#L173-L199"&gt;https://github.com/nrfconnect/sdk-hal_nordic/blob/main/nrfx/drivers/include/nrfx_uart.h#L173-L199&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nrfconnect/sdk-hal_nordic/blob/main/nrfx/drivers/include/nrfx_uarte.h#L182-L208"&gt;https://github.com/nrfconnect/sdk-hal_nordic/blob/main/nrfx/drivers/include/nrfx_uarte.h#L182-L208&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can try using this to make a simple application that switches between two setups, and I will assist you if you run into any issues.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>