Why does application that builds using nRF Connect SDK v2.0.0 fail to build under SDK v2.1.0

Under Ubuntu 20.04 the udp sample application that we have modified that builds with no problem under nRF Connect SDK v2.0.0 fails to build when when its directory is copied to SDK v2.1.0. 

There appear to be two problem areas.

This uart code builds and runs under v2.0.0 but fails under v2.1.0

	baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)));

	if (baseuart == NULL) {
		printk("Could not find  %s!\n\r", DT_LABEL(DT_NODELABEL(uart2)));
		return;
	}

Errors as follows:

In file included from /media/sam/ncs21/zephyr/include/zephyr/arch/arm/aarch32/arch.h:20,
                 from /media/sam/ncs21/zephyr/include/zephyr/arch/cpu.h:19,
                 from /media/sam/ncs21/zephyr/include/zephyr/kernel_includes.h:33,
                 from /media/sam/ncs21/zephyr/include/zephyr/kernel.h:17,
                 from /media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/src/main.c:8:
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/src/main.c: In function 'main':
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/build/zephyr/include/generated/devicetree_unfixed.h:9216:38: error: 'DT_N_S_soc_S_peripheral_40000000_S_uart_a000_P_label' undeclared (first use in this function); did you mean 'DT_N_S_soc_S_peripheral_40000000_S_uart_a000_P_reg'?
 9216 | #define DT_N_NODELABEL_uart2         DT_N_S_soc_S_peripheral_40000000_S_uart_a000
      |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:3068:24: note: in definition of macro 'DT_CAT'
 3068 | #define DT_CAT(a1, a2) a1 ## a2
      |                        ^~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:715:27: note: in expansion of macro 'DT_PROP'
  715 | #define DT_LABEL(node_id) DT_PROP(node_id, label)
      |                           ^~~~~~~
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/src/main.c:918:31: note: in expansion of macro 'DT_LABEL'
  918 |  baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)));
      |                               ^~~~~~~~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:3068:24: note: in expansion of macro 'DT_N_NODELABEL_uart2'
 3068 | #define DT_CAT(a1, a2) a1 ## a2
      |                        ^~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:177:29: note: in expansion of macro 'DT_CAT'
  177 | #define DT_NODELABEL(label) DT_CAT(DT_N_NODELABEL_, label)
      |                             ^~~~~~
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/src/main.c:918:40: note: in expansion of macro 'DT_NODELABEL'
  918 |  baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)));
      |                                        ^~~~~~~~~~~~
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/build/zephyr/include/generated/devicetree_unfixed.h:9216:38: note: each undeclared identifier is reported only once for each function it appears in
 9216 | #define DT_N_NODELABEL_uart2         DT_N_S_soc_S_peripheral_40000000_S_uart_a000
      |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:3068:24: note: in definition of macro 'DT_CAT'
 3068 | #define DT_CAT(a1, a2) a1 ## a2
      |                        ^~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:715:27: note: in expansion of macro 'DT_PROP'
  715 | #define DT_LABEL(node_id) DT_PROP(node_id, label)
      |                           ^~~~~~~
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/src/main.c:918:31: note: in expansion of macro 'DT_LABEL'
  918 |  baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)));
      |                               ^~~~~~~~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:3068:24: note: in expansion of macro 'DT_N_NODELABEL_uart2'
 3068 | #define DT_CAT(a1, a2) a1 ## a2
      |                        ^~
/media/sam/ncs21/zephyr/include/zephyr/devicetree.h:177:29: note: in expansion of macro 'DT_CAT'
  177 | #define DT_NODELABEL(label) DT_CAT(DT_N_NODELABEL_, label)
      |                             ^~~~~~
/media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/src/main.c:918:40: note: in expansion of macro 'DT_NODELABEL'
  918 |  baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)));
      |                                        ^~~~~~~~~~~~
ninja: build stopped: subcommand failed.
FATAL ERROR: command exited with status 1: /usr/bin/cmake --build /media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/build

I think the uart aliases may have changed so that this initialisation needs coding differently but am unclear how to resolve.

There is also an overlay file with the following:

&uart2 {
	status = "okay";
    current-speed = <115200>;
	pinctrl-0 = <&uart2_default>;
	pinctrl-1 = <&uart2_sleep>;
    // rx-pin = <14>;
	// tx-pin = <15>;
};

This doesn't seem to be the only problem moving from v2.0.0 to v2.1.0

If the modem initialisation code is modified so that it compiles (but won't run), there are additional errors:

[113/292] Building C object zephyr/CMakeFiles/zephyr.dir/media/sam/ncs21/nrf/subsys/nonsecure/soc_secure.c.obj
/media/sam/ncs21/nrf/subsys/nonsecure/soc_secure.c: In function 'soc_secure_mem_read':
/media/sam/ncs21/nrf/subsys/nonsecure/soc_secure.c:19:2: warning: 'spm_request_read' is deprecated [-Wdeprecated-declarations]
   19 |  return spm_request_read(dst, (uint32_t)src, len);
      |  ^~~~~~
In file included from /media/sam/ncs21/nrf/subsys/nonsecure/soc_secure.c:10:
/media/sam/ncs21/nrf/include/secure_services.h:88:18: note: declared here
   88 | __deprecated int spm_request_read(void *destination, uint32_t addr, size_t len);
      |                  ^~~~~~~~~~~~~~~~
[146/292] Building C object zephyr/CMakeFiles/zephyr.dir/subsys/net/lib/sockets/sockets_tls.c.obj
/media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c: In function 'dtls_rx':
/media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:804:11: warning: implicit declaration of function 'mbedtls_ssl_set_client_transport_id'; did you mean 'mbedtls_ssl_conf_transport'? [-Wimplicit-function-declaration]
  804 |     err = mbedtls_ssl_set_client_transport_id(
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |           mbedtls_ssl_conf_transport
/media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c: In function 'tls_mbedtls_init':
/media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:1236:3: warning: implicit declaration of function 'mbedtls_ssl_conf_handshake_timeout'; did you mean 'mbedtls_ssl_conf_read_timeout'? [-Wimplicit-function-declaration]
 1236 |   mbedtls_ssl_conf_handshake_timeout(&context->config,
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |   mbedtls_ssl_conf_read_timeout
/media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:1249:4: warning: implicit declaration of function 'mbedtls_ssl_conf_dtls_cookies'; did you mean 'mbedtls_ssl_conf_sig_hashes'? [-Wimplicit-function-declaration]
 1249 |    mbedtls_ssl_conf_dtls_cookies(&context->config,
      |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |    mbedtls_ssl_conf_sig_hashes
[210/292] Building C object zephyr/drivers/entropy/CMakeFiles/drivers__entropy.dir/media/sam/ncs21/nrf/drivers/entropy/entropy_cc3xx.c.obj
/media/sam/ncs21/nrf/drivers/entropy/entropy_cc3xx.c: In function 'entropy_cc3xx_rng_get_entropy':
/media/sam/ncs21/nrf/drivers/entropy/entropy_cc3xx.c:65:3: warning: 'spm_request_random_number' is deprecated [-Wdeprecated-declarations]
   65 |   ret = spm_request_random_number(buffer + offset,
      |   ^~~
In file included from /media/sam/ncs21/nrf/drivers/entropy/entropy_cc3xx.c:18:
/media/sam/ncs21/nrf/include/secure_services.h:75:18: note: declared here
   75 | __deprecated int spm_request_random_number(uint8_t *output, size_t len, size_t *olen);
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~
[281/292] Linking C executable zephyr/zephyr_pre0.elf
FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map /media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/build/zephyr/zephyr_pre0.map 

Again these errors don't appear when building under v2.0.0

This looks like it could be some kind of new configuration option that needs asserting that affects conditional compilation of the functions not found (as they do exist), but have not been able to find anything new in the documentation, even though different version of sdk-mbedtls have been provided as appears in the two west.yaml files:

 v3.0.0-ncs2 in nrf connect v2.0.0 and  v3.1.0-ncs1 in nrf connect v2.1.0 

The applications are being built from VSC after SDK installation via toolchain manager.

Any assistance would be very much appreciated. Cheers Ron.

Parents
  • Hi,

    The label property has been removed in v2.1.0 (see this commit), so you cannot use DT_LABEL in this case. It is recommended to use node labels to get devices instead of using the label property, and to use DEVICE_DT_GET instead of device_get_binding. In your case, this would look something like the following:

    baseuart = DEVICE_DT_GET(DT_NODELABEL(uart2));
    
    if (!device_is_ready(baseuart)) {
        /* device exists, but it failed to initialize */
    }

    For more information about these changes, please see the Zephyr release notes: Zephyr release notes 3.2 - Devicetree.

    Best regards,

    Marte

  • Thanks Marte, that's very helpful, partially answering the question.

    Although I had some idea that there were no longer labels, having done a code comparison, for some reason the actual calls were proving elusive.

    The remaining, in some respects more pressing issue is the second set of related errors, with several related functions unable to be found, e.g. mbedtls_ssl_set_client_transport_id, or that were previously being built not now being built.  I've tried temporarily including some of the defines that should result in these functions building but although that removes some of the error messages, it creates or perhaps unmasks additional errors. So it's as though there is a new prj.conf or overlay configuration requirement of the newer version of the library (sdk-mbedtls) that is missing, but I haven't been able to track down any information that indicates what that might be.  Or perhaps this is on completely the wrong track!  In any case further assistance with this problem would be very much appreciated. Cheers Ron. 

  • Hi Marte,

    Modem initialisation is based on the nRF9160 udp sample code, which has been modified to use dtls with psk.  Data is received via uart2 from an application mcu, sent via dtls (over NB-IoT) to a remote gateway, with responses being returned to the application mcu.

    You'll have gathered that I'm new to Zephyr and indeed Nordic. So still trying to find my way.  Modem init and associated code is here:

    #if defined(CONFIG_NRF_MODEM_LIB) // set to y in prj.conf
    
    static int configure_low_power(void)
    {
    	int err;
    
    #if defined(CONFIG_UDP_PSM_ENABLE)
    	/** Power Saving Mode */
    	err = lte_lc_psm_req(true);
    	if (err) {
    		printk("lte_lc_psm_req, error: %d\n", err);
    	}
    #else
    	err = lte_lc_psm_req(false);
    	if (err) {
    		printk("lte_lc_psm_req, error: %d\n", err);
    	}
    #endif
    
    #if defined(CONFIG_UDP_EDRX_ENABLE)
    	/** enhanced Discontinuous Reception */
    	err = lte_lc_edrx_req(true);
    	if (err) {
    		printk("lte_lc_edrx_req, error: %d\n", err);
    	}
    #else
    	err = lte_lc_edrx_req(false);
    	if (err) {
    		printk("lte_lc_edrx_req, error: %d\n", err);
    	}
    #endif
    
    #if defined(CONFIG_UDP_RAI_ENABLE)
    	/** Release Assistance Indication  */
    	err = lte_lc_rai_req(true);
    	if (err) {
    		printk("lte_lc_rai_req, error: %d\n", err);
    	}
    #endif
    
    	return err;
    }
    
    
    static int modem_init(void)
    {
    	int err = 0;
    
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already configured and LTE connected. */
    	} else {
    		err = lte_lc_init();
    		if (err) {
    			printk("LTE Modem initialization failed, error: %d\n", err);
    			return err;
    		}
    		else {
    			DBG_PRINTF("LTE modem initialised\r\n");
    		}
    	}
    	return err;
    }
    
    static int modem_connect(void)
    {
    	int err = 0;
    
    	DBG_PRINTF("Waiting for network.. ");
    	//## Note that timeout in seconds is set in prj.conf by CONFIG_LTE_NETWORK_TIMEOUT
    	err = lte_lc_init_and_connect();
    
    	if (err) {
    			DBG_PRINTF("Connecting to celluar network failed, error: %d\n",err);
    			return err;
    		}
    		else {
    			DBG_PRINTF(".Cellular modem connected\r\n");
    		}
    	
    	return err;
    }
    #endif
    
    
    static int dtls_init(void) {
    
    int err;
    
    // Check for existing credentials
    bool exists;
    err = modem_key_mgmt_exists(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, &exists);
    if (err == 0) {
    	DBG_PRINTF("Modem PSK Credential %s\r\n", exists ? "psk exists" : "psk doesn't exist");
    }
    else {
    	printk("Modem psk credentials check failed!\r\n");
    }
    
    err = modem_key_mgmt_exists(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, &exists);
    if (err == 0) {
    	DBG_PRINTF("Modem PSK_ID Credential %s\r\n", exists ? "psk id exists" : "psk id doesn't exist");
    }
    else {
    	printk("Modem psk id credentials check failed!\r\n");
    }
    
    err = modem_key_mgmt_cmp(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, psk_id, (size_t) sizeof(psk_id)-1);
    if (err == 0) {
    	DBG_PRINTF("PSK ID matches modem\r\n");
    }
    else if (err == 1) {
    		DBG_PRINTF("PSK ID doesn't match modem\r\n");
    	}
    	else {
    		printk("PSK ID compare match error %d\r\n", err);
    	}
    
    // Write DTLS credentials to the modem store, i.e. psk and psk identity
    // modem_key_mgmt_write(nrf_sec_tag_t sec_tag, enum modem_key_mgmt_cred_type cred_type, const void *buf, size_t len)
    #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT) // set to y in prj.conf
    	err = modem_key_mgmt_write(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, psk, (size_t) sizeof(psk));
    	if (err < 0) {
    		printk("Failed to register PSK: %d\r\n", err);
    	}
    	else {
    		DBG_PRINTF("PSK registered: %.*s\r\n", (size_t) sizeof(psk), psk);
    	}
    
    	err = modem_key_mgmt_write(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, psk_id,(size_t) sizeof(psk_id)-1);
    	if (err < 0) {
    		printk("Failed to register PSK ID: %d\r\n", err);
    	}
    	else {
    		DBG_PRINTF("PSK ID registered: %.*s\r\n", (size_t) sizeof(psk_id)-1, psk_id);
    	}
    
    #endif
    
    }
    
    static K_MUTEX_DEFINE(lte_mutex);
    static K_CONDVAR_DEFINE(lte_condvar);
    static volatile int lte_connected_state = 0;
    static k_timeout_t timeout;
    time_t time;
    
    static int lte_connection_wait(k_timeout_t timeout)
    {
       int res = 0;
       k_mutex_lock(&lte_mutex, timeout);
       res = lte_connected_state;
       if (!res) {
          k_condvar_wait(&lte_condvar, &lte_mutex, timeout);
          res = lte_connected_state;
       }
       k_mutex_unlock(&lte_mutex);
       return res;
    }
    
    static int modem_connection_wait(const k_timeout_t timeout)
    {
       int err = 0;
       k_timeout_t time = K_MSEC(0);
       k_timeout_t interval = K_MSEC(1500);
       while (!lte_connection_wait(interval)) {
          time.ticks += interval.ticks;
          if ((time.ticks - timeout.ticks) > 0) {
             err = 1;
             break;
          }
       }
       return err;
    }
    
    
    
    main () {
    .
    .
    .
    
    #if defined(CONFIG_NRF_MODEM_LIB) // set to y in prj.conf
    
    	// Initialize the modem before calling configure_low_power(). This is
    	// because the enabling of RAI is dependent on the
    	// configured network mode which is set during modem initialization.
    	
    	err = modem_init();
    	if (err) goto err_exit;
    
    	err = configure_low_power();
    	if (err) {
    		printk("Unable to set low power configuration, error: %d\n", err);
    		goto err_exit;
    	}
    
    // all set to y in prj.conf
    #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT) &&  defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    	dtls_init( );
    #endif
    	err = modem_connect();
    	if (err) 
    		goto err_exit;
    
    	if (!err) {
          time = k_uptime_get();
          err = modem_connection_wait(timeout);
          time = k_uptime_get() - time;
          if (!err) 
            printk("LTE connected in %ld [ms]", (long)time);
    	}
    
    #endif
    
    ...
    }
    

    As said, the application is working well with nRF Connect 2.0.0, end-to-end communications working as needed (builds from VSC and from the command line using West) but obviously we would prefer not to be 'stuck' using an older version.

    Tried building with TF-M:

    i.e. in prj.conf changed:

    CONFIG_BUILD_WITH_TFM=y
    CONFIG_SPM=n

    but am getting the same errors, including "implcit declarations" of the same functions such as mbedtls_ssl_conf_dtls_cookies

    Reproducing those errors again here:

    [113/267] Building C object zephyr/CMakeFiles/zephyr.dir/subsys/net/lib/sockets/sockets_tls.c.obj
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c: In function 'tls_session_store':
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:638:8: warning: implicit declaration of function 'mbedtls_ssl_get_session'; did you mean 'mbedtls_ssl_get_version'? [-Wimplicit-function-declaration]
      638 |  ret = mbedtls_ssl_get_session(&context->ssl, &session);
          |        ^~~~~~~~~~~~~~~~~~~~~~~
          |        mbedtls_ssl_get_version
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c: In function 'tls_session_restore':
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:674:8: warning: implicit declaration of function 'mbedtls_ssl_set_session'; did you mean 'mbedtls_ssl_get_version'? [-Wimplicit-function-declaration]
      674 |  ret = mbedtls_ssl_set_session(&context->ssl, &session);
          |        ^~~~~~~~~~~~~~~~~~~~~~~
          |        mbedtls_ssl_get_version
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c: In function 'dtls_rx':
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:804:11: warning: implicit declaration of function 'mbedtls_ssl_set_client_transport_id'; did you mean 'mbedtls_ssl_conf_transport'? [-Wimplicit-function-declaration]
      804 |     err = mbedtls_ssl_set_client_transport_id(
          |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |           mbedtls_ssl_conf_transport
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c: In function 'tls_mbedtls_init':
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:1236:3: warning: implicit declaration of function 'mbedtls_ssl_conf_handshake_timeout'; did you mean 'mbedtls_ssl_conf_read_timeout'? [-Wimplicit-function-declaration]
     1236 |   mbedtls_ssl_conf_handshake_timeout(&context->config,
          |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |   mbedtls_ssl_conf_read_timeout
    /media/sam/ncs21/zephyr/subsys/net/lib/sockets/sockets_tls.c:1249:4: warning: implicit declaration of function 'mbedtls_ssl_conf_dtls_cookies'; did you mean 'mbedtls_ssl_conf_curves'? [-Wimplicit-function-declaration]
     1249 |    mbedtls_ssl_conf_dtls_cookies(&context->config,
          |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |    mbedtls_ssl_conf_curves
    [255/267] Linking C executable zephyr/zephyr_pre0.elf
    FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map /media/sam/ncs21/nrf/samples/nrf9160/dtlsnbiot/build/zephyr/zephyr_pre0.map 
    

    Further suggestions very much appreciated.

    Cheers Ron

  • Hi Ron,

    Can you please share your prj.conf as well?

    Best regards,

    Marte

  • Hi Marte, yes of course:

    prj.conf

    #
    # Copyright (c) 2020 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # General config
    CONFIG_ASSERT=n
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    CONFIG_SERIAL=y
    CONFIG_UART_ASYNC_API=y
    # CONFIG_UART_LINE_CTRL=y
    CONFIG_UART_USE_RUNTIME_CONFIGURE=y
    # CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_LOG_MODE_DEFERRED=n
    
    # Network
    CONFIG_NET_UDP=y
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=n
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_OFFLOAD=y
    
    CONFIG_LTE_NETWORK_TIMEOUT=20
    # CONFIG_NET_SOCKETS_CONNECT_TIMEOUT=5
    
    CONFIG_UDP_DATA_UPLOAD_SIZE_BYTES=32
    CONFIG_UDP_DATA_UPLOAD_FREQUENCY_SECONDS=180
    CONFIG_UDP_SERVER_ADDRESS_STATIC="149.28.170.96"
    # CONFIG_UDP_SERVER_ADDRESS_STATIC="127.0.0.1"
    CONFIG_UDP_SERVER_PORT=9009
    CONFIG_NET_SAMPLE_PSK_HEADER_FILE="device_psk.h"
    
    # LTE link control
    CONFIG_LTE_LINK_CONTROL=y
    CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
    
    # Modem library
    CONFIG_NRF_MODEM_LIB=y
    CONFIG_MODEM_KEY_MGMT=y
    
    # Heap and stacks
    CONFIG_HEAP_MEM_POOL_SIZE=8128
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    CONFIG_NRF_MODEM_LIB_HEAP_SIZE=2048
    CONFIG_AT_MONITOR_HEAP_SIZE=1024
    
    # LTE parameters
    ## Network Mode / LTE category
    # CONFIG_LTE_NETWORK_MODE_LTE_M=y
    CONFIG_LTE_NETWORK_MODE_NBIOT=y
    
    ## PSM
    CONFIG_UDP_PSM_ENABLE=y
    CONFIG_LTE_PSM_REQ_RPTAU="00100001"
    CONFIG_LTE_PSM_REQ_RAT="00000000"
    
    ## eDRX
    CONFIG_UDP_EDRX_ENABLE=n
    CONFIG_LTE_EDRX_REQ_VALUE_LTE_M="1001"
    
    ## RAI
    CONFIG_UDP_RAI_ENABLE=n
    CONFIG_LTE_RAI_REQ_VALUE="4"
    
    CONFIG_BUILD_WITH_TFM=y
    CONFIG_SPM=n
    
    # Disable Console Printing
    # CONFIG_BOOT_BANNER=n
    # CONFIG_PRINTK=n
    

    Also overlay-tls.conf

    CONFIG_NET_BUF_RX_COUNT=100
    CONFIG_NET_BUF_TX_COUNT=100
    
    # TLS configuration
    CONFIG_MBEDTLS=y
    CONFIG_MBEDTLS_BUILTIN=n
    CONFIG_MBEDTLS_LIBRARY_NRF_SECURITY=y
    CONFIG_MBEDTLS_ENABLE_HEAP=y
    # CONFIG_MBEDTLS_HEAP_SIZE=60000
    # CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
    # CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y
    
    
    # CONFIG_MBEDTLS_CFG_FILE="config-tls-generic.h"
    
    # This enables DTLS
    CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
    
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4
    CONFIG_NET_SOCKETS_ENABLE_DTLS=y
    CONFIG_POSIX_MAX_FDS=8
    
    
    # Crypto
    # CONFIG_OBERON_BACKEND=y
    CONFIG_NORDIC_SECURITY_BACKEND=y
    # Disable all non-used crypto
    CONFIG_NRF_SECURITY_RNG=y
    CONFIG_MBEDTLS_CHACHA20_C=y
    CONFIG_MBEDTLS_POLY1305_C=y
    CONFIG_MBEDTLS_ECP_C=y
    CONFIG_MBEDTLS_RSA_C=y
    CONFIG_MBEDTLS_DHM_C=y
    CONFIG_MBEDTLS_SHA1_C=y
    CONFIG_MBEDTLS_SHA384_C=y
    CONFIG_MBEDTLS_SHA512_C=y
    # This is the one we need
    CONFIG_MBEDTLS_SHA256_C=y
    # TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256
    
    # CONFIG_NRF_SECURITY_ADVANCED=y
    

    Thanks.

  • Hi Ron,

    How are you opening the socket?

    Best regards,

    Marte

  • Hi Marte

    Simplest is to list the entire application here, which isn't particularly lengthy:

    /*
     * Copyright (c) 2020 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    #include <zephyr/logging/log.h>
    // LOG_MODULE_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG);
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <modem/lte_lc.h>
    #include <zephyr/net/socket.h>
    #include <zephyr/net/tls_credentials.h>
    #include <drivers/uart.h>
    #include <string.h>
    #include "ca_certificate.h"
    #include <zephyr/net/net_context.h>
    #include <modem/modem_key_mgmt.h>
    #include <nrfx.h>
    #include <nrf_socket.h>
    #include <modem/nrf_modem_lib.h>
    
    
    
    #define CONFIG_PRINT_DBG 1
    
    #ifdef CONFIG_PRINT_DBG
    #define DBG_PRINTF(...)    printk(__VA_ARGS__)
    #else
    #define DBG_PRINTF(...)
    #endif
    
    // static const char psk[] = "3081269BCCC4FA7509AAA00C182D0595";
    // static const char psk_id[] = "70B3D5CD00010064";
    
    static char psk[] = "3081269BCCC4FA7509AAA00C182D0595";
    static char psk_id[] = "70B3D5CD00010064";
    static uint8_t validkeysexist = 0;
    
    
    
    #define UDP_IP_HEADER_SIZE 28
    
    
    /**
     * @brief Max size of baseuart event queue
     * 
     */
    #define RECEIVE_EVENT_QUEUE_SIZE 4
    
    //## dtls receive buffer size
    #define DOWNLINK_RCV_BUF_SIZE 16
    //## baseuart dma receive buffer size - multiple of 4 bytes boundary
    #define UPLINK_RCV_BUF_SIZE 24
    
    
    #define MAXSENDRETRIES 3
    #define MAXINITRETRIES	5
    #define MAXSERVERCONNECTRETRIES 5
    
    static int client_fd;
    static struct sockaddr_storage host_addr; 
    static struct k_work server_transmission_work; // A work Q element - infinite loop that receives, parses and acts on message events
    static void server_disconnect(void);
    static uint8_t dtlssendretrycount = 0;
    static uint8_t serverfailcount = 0; // connection failure count
    uint8_t sendretrycount = 0;
    
    #define TRANSMISSION_STACK_SIZE 1536
    #define TRANSMISSION_PRIORITY 5
    
    K_THREAD_STACK_DEFINE(transmission_stack_area, TRANSMISSION_STACK_SIZE); // define memory for application workqueue
    
    struct k_work_q transmission_work_q;
    
    
    // static struct k_work sensor_rx_event_work;
    
    K_SEM_DEFINE(lte_connected, 0, 1);
    
    
    struct communications_event
    {
       size_t length; 
       uint8_t data[UPLINK_RCV_BUF_SIZE];
    };
    
    //## A socket peer connect timeout value
    #define CONNECT_TIMEOUT	8
    
    //## Define message queue to receive sensor data to be transmitted via udp
    K_MSGQ_DEFINE(receive_event_msq, sizeof(struct communications_event), RECEIVE_EVENT_QUEUE_SIZE, 4);
    
    //## Do we need another message queue for downlink commands data?
    
    
    uint32_t  packet_seqno = 0;
    
    
    const struct device *baseuart;  // base board link UART
    
    //## Configure the base board link UART at run time
    const struct uart_config baseuart_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
    	};
    
    
    static K_MEM_SLAB_DEFINE(uart_slab, UPLINK_RCV_BUF_SIZE, 3, 4);
    
    uint8_t rx_buf[UPLINK_RCV_BUF_SIZE] = {0}; // A buffer to store incoming UART data
    
    // char __aligned(4) my_msgq_buffer[10 * sizeof(rx_buf)];
    //K_MSGQ_DEFINE(my_msgq, sizeof(rx_buf), 10, 4);
    
    static void baseuart_cb(const struct device *dev, struct uart_event *evt, void *user_data);
    static int server_init(void);
    static int server_connect(void);
    
    typedef enum eventtype_e  // uplink event type - first byte sent
    {
    	sensorevent = 0,
        configevent,
        dataevent,
        errorevent,
        alarmevent,
        linkcntrl    // Link control event such as check for modem ready
    } eventtype_t;
    
    typedef enum lnkctrlcmnd_e // uplink linkcntrl value, downlink ack command value
    {
    	dummy = 0,
        ok = 0x31,	// cmnd is used to indicate both modem ready query and ok response
    	ko = 0x32 // error
    } lnkctrlcmnd_t;
    
    typedef enum command_e
    {
    	sleepperiod = 0x10,
    	acknowledge = 0x41,
    	sendpsk = 0x91,
    	resetdevice = 0xFF
    } command_t;
    
    
    #ifdef CONFIG_PRINT_DBG
    static void printhex(uint8_t * buf, int size) {
    	for (uint8_t i=0; i<size; i++) {
    		printk("%02X",buf[i]);
    	}
    	printk("\r\n");
    }
    #endif
    
    
    
    static void baseuart_connect_async(const struct device *baseuart)
    {
    	int err;
    
    	err = k_mem_slab_alloc(&uart_slab, (void **)rx_buf, K_NO_WAIT);
    	__ASSERT(err == 0, "Failed to alloc slab");
    
    	err = uart_callback_set(baseuart, baseuart_cb, (void *)baseuart);
    	__ASSERT(err == 0, "Failed to set callback");
    
    	err = uart_rx_enable(baseuart ,rx_buf,sizeof(rx_buf), 100);
    	if (err == 0) {
    		DBG_PRINTF("Rx from sensor enabled\r\n");
    	}
    	else {
    		printk("Rx enable failed\r\n");
    	}
    }
    
    
    
    static int send2base(uint8_t* msgbuf, size_t msglen) {
    	//## Messages sent to the application mcu via uart are fixed length binary
    	//*  of length DOWNLINK_RCV_BUF_SIZE so need to be padded accordingly
    	memset(&msgbuf[msglen], 0, DOWNLINK_RCV_BUF_SIZE - msglen);
    	//## Send receive message to base board via dma transmit
    	uart_tx(baseuart, msgbuf, DOWNLINK_RCV_BUF_SIZE, SYS_FOREVER_MS);
    	printk("--> Sending: ");
    	printhex(msgbuf,DOWNLINK_RCV_BUF_SIZE);	
    	return 0;
    }
    
    static void sendack2base(int value) { // 0 is OK, 1 is KO
    	#define MSGLEN 2
    	uint8_t msgbuf[DOWNLINK_RCV_BUF_SIZE];
    	msgbuf[0] = acknowledge;
    	if (value == ok) {
    		msgbuf[1] = ok;	
    	}
    	else {
    		msgbuf[1] = ko;
    	}
    	send2base(msgbuf, MSGLEN);
    }
    
    int8_t storePSK(struct communications_event commsevent) {
    
    	if (crc8(commsevent.data, commsevent.length-1) == commsevent.data[commsevent.length]) {
    		// store keys
    		memcpy(psk_id, &commsevent.data[1], 8);
    		memcpy(psk, &commsevent.data[9], 16);
    		DBG_PRINTF("PSK_ID & PSK were stored\r\n");
    		validkeysexist = 1;
    	}
    	else { //crc error
    		DBG_PRINTF("storePSK CRC Error!\r\n");
    		return -1;
    	}
    	return 0;
    }
    
    //## Sends sensor data to the remote udp destination and receives downlink data replies 
    static void server_transmission_work_fn(struct k_work *work)
    {
    	int err;
    	struct communications_event commsevent; //## NB - communications_event struct data buffer is currently size 96 in sockets.h
    	int received;
    	uint8_t recv_buf[DOWNLINK_RCV_BUF_SIZE];
    
    	for(;;) { // infinite loop
    
    		DBG_PRINTF("\r\n>>> server_transmission_work_fn started <<<\r\n\r\n");
    
    		//## read message to process from the message queue
    		//## NB - k_forever waits until a message arrives in the queue
    		k_msgq_get(&receive_event_msq, &commsevent, K_FOREVER);
    
    
    		//## Parse event messages from the message receive queue - base mcu and gateway messages
    		//## first byte indicates message type, e.g. sensor data, modem command etc
    		//## if modem command type message second byte is the command itself
    		uint8_t skiptoend = 0;
    		switch(commsevent.data[0]) {
    			case linkcntrl: // uplink message type 0x05
    				switch(commsevent.data[1]) {
    					case ok:
    						DBG_PRINTF(">RuRdy request received\r\n");
    						// check if keys are stored
    						if (!validkeysexist) { // send request for keys
    							DBG_PRINTF(">Requesting keys\r\n");
    							commsevent.data[0] = sendpsk;
    							err = send2base(commsevent.data, 1); // send 1 bytes
    						}
    						else {
    							// need to return 2 downlink acknowledgement bytes: command, value
    							commsevent.data[0] = acknowledge;
    							commsevent.data[1] = ok; //set value to return
    							err = send2base(commsevent.data, 2); // send 2 bytes
    						}
    						skiptoend = 1; // restart main loop
    						break;
    				} // end switch commsevent.data[1]
    				break;
    			case acknowledge: // 0x41 - ack from dtls2mqtt gateway
    				//## NB - Gateway response can be passed through to base mcu
    				//##  command 0x41 followed by val 0x31=ok or 0x32=ko
    				err = send2base(commsevent.data, 2); // send 2 bytes
    				skiptoend = 1; // restart main loop
    			case sensorevent: // 0x00
    				//## For a sensorevent the code after the switch is executed without skipping to end
    				;
    				break;	
    			case configevent: // 0x01 - configuration echo from app mcu
    				//## For a config echo the code after the switch is executed without skipping to end
    				;
    				break;	
    			case sendpsk: // 0x91 - payload arrived = sendpsk + psk_id + psk + crc8
    				// check the validity of the payload crc8
    				if (storePSK(commsevent) != 0) {
    					// if fail return another sendpsk request
    					commsevent.data[0] = sendpsk;
    					err = send2base(commsevent.data, 1); // send 1 bytes
    				}
    				else {
    					// otherwise update the keys and return ok
    					commsevent.data[0] = acknowledge;
    					commsevent.data[1] = ok; //set value to return
    					err = send2base(commsevent.data, 2); // send 2 bytes
    				}
    				skiptoend = 1;
    				break;
    			default:
    				//## All other data events assumed to be downlink commands
    				//## to be passed through to base mcu as is
    				//## base mcu is expected to validate, avoids modem storing
    				//## valid commands
    				err = send2base(commsevent.data, DOWNLINK_RCV_BUF_SIZE); // send max bytes
    				skiptoend = 1; // restart main loop
    		} // end switch commsevent.data[0]
    
    		if (skiptoend)
    			continue;
    
    		DBG_PRINTF("Transmitting UDP/IP payload of %d bytes to the ", commsevent.length);
    		// DBG_PRINTF("Transmitting UDP/IP payload of %d bytes to the ", commsevent.length + UDP_IP_HEADER_SIZE);
    		DBG_PRINTF("IP address %s, port number %d\n", CONFIG_UDP_SERVER_ADDRESS_STATIC, CONFIG_UDP_SERVER_PORT);
    		DBG_PRINTF("Message buffer to send is: ");	
    #ifdef CONFIG_PRINT_DBG
    		for (int i = 0; i < commsevent.length; i++) printk("%02X",commsevent.data[i]);
    		printk("\r\n");
    #endif
    
    		/*******************************************************************/
    
    		//## NB - need to reconnect (create socket) for each transmission, disconnect after receive timeout
    		//## or on error
    	
    		uint8_t serverconnected = 0;
    		err = server_connect();
    		if (err) {
    			printk("Not able to connect to UDP server\n");
    			serverfailcount += 1;
    			if (serverfailcount >= MAXSERVERCONNECTRETRIES) {
    				printk("Server Connect failed after %u retries - resetting!\r\n",MAXSERVERCONNECTRETRIES);
    				NVIC_SystemReset();
    			}
    			goto exitloop;
    			
    		}
    		else {
    			DBG_PRINTF("Connected to UDP Server\r\n");
    			serverfailcount = 0;
    			serverconnected = 1;
    		}
    
    		/******************************************************************/
    
    		// if (endndx > 0) { // endndx is the length of data to send - packet found if endndx > 0
    		if (commsevent.length > 0) { // packet from base to send
    			uint8_t dtlssendretrycount = 0;
    			do {
    				// err = send(client_fd,&commsevent.data[startndx],endndx, 0);
    				err = send(client_fd, commsevent.data, commsevent.length, 0);
    				if (err < 0) {
    					printk("Failed to transmit UDP packet, %d\n", errno);
    					dtlssendretrycount += 1;
    					if (dtlssendretrycount > 3) {
    						printk("dtls send command repeatedly failed!\r\n");
    						//## send KO to base
    						sendack2base(ko);
    						DBG_PRINTF("--> ko to base\r\n");
    						goto exitloop;
    					}
    					k_msleep(1000);
    				}
    				else {
    					//## send OK to base
    					sendack2base(ok);
    					DBG_PRINTF("--> ok to base\r\n");
    				}
    			} while ((dtlssendretrycount <= 3) && (err < 0));
    
    
    			memset(recv_buf,0, sizeof(recv_buf));
    			//## Receive udp return message
    			received = recv(client_fd, recv_buf, sizeof(recv_buf), MSG_WAITALL); //NB - If MSG_DONTWAIT flag used recv returns err and no message
    
    			if (received <= 0) {
    				DBG_PRINTF("No udp reply\r\n");
    				//## Saved outgoing message should be resent up to n times
    				//## By injecting into base uart receive message queue  
    				if (sendretrycount < MAXSENDRETRIES) {
    					//## push base uart received buffer back into message queue
    					while (k_msgq_put(&receive_event_msq, &commsevent, K_NO_WAIT) != 0)  {
    						//## message queue is full: purge old data & try again 
    						// k_msgq_purge(&receive_event_msq);
    						printk("Message Q full, shouldn't happen - resetting!\r\n");
    						NVIC_SystemReset();
    					}
    					sendretrycount += 1; // increment retry count
    				}
    				else { // return message ack ko or failure
    					sendack2base(ko);
    				}
    			}
    			else {
    				sendretrycount = 0;
    // #ifdef CONFIG_PRINT_DBG
    				printk("udp reply is: ");
    				for (int i = 0; i < received; i++) printk("%02X",recv_buf[i]);
    				printk(" length: %d\r\n", received);
    // #endif
    				
    				err = send2base(recv_buf, received); // send received data to base mcu
    
    			}
    		}
    		else {
    			printk("Failed to find valid data to send\r\n");
    			//## return message ack ko or failure
    			sendack2base(ko);
    		}
    
    	exitloop:
    		//## Disconnect udp socket - closes client_fd
    		if (serverconnected)
    			server_disconnect( );
    
    
    	}// end infinite for(;;)
    
    }
    
    static void server_transmission_worker_init(void)
    {
    	// k_server_transmission_worker_init_delayable(&server_transmission_work, server_transmission_work_fn);
    	k_work_init(&server_transmission_work, server_transmission_work_fn);
    	// k_server_transmission_worker_init(&sensor_rx_event_work, sensor_rx_event_work_fn);
    	DBG_PRINTF("server transmission worker initialised\r\n");
    }
    
    #if defined(CONFIG_NRF_MODEM_LIB)
    /* static void lte_handler(const struct lte_lc_evt *const evt)
    {
    	switch (evt->type) {
    	case LTE_LC_EVT_NW_REG_STATUS:
    		if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
    		     (evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
    			break;
    		}
    
    		printk("Network registration status: %s\n",
    			evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
    			"Connected - home network" : "Connected - roaming\n");
    		k_sem_give(&lte_connected);
    		break;
    	case LTE_LC_EVT_PSM_UPDATE:
    		DBG_PRINTF("PSM parameter update: TAU: %d, Active time: %d\n",
    			evt->psm_cfg.tau, evt->psm_cfg.active_time);
    		break;
    	case LTE_LC_EVT_EDRX_UPDATE: {
    		char log_buf[60];
    		ssize_t len;
    
    		len = snprintf(log_buf, sizeof(log_buf),
    			       "eDRX parameter update: eDRX: %f, PTW: %f\n",
    			       evt->edrx_cfg.edrx, evt->edrx_cfg.ptw);
    		if (len > 0) {
    			DBG_PRINTF("%s\n", log_buf);
    		}
    		break;
    	}
    	case LTE_LC_EVT_RRC_UPDATE:
    		DBG_PRINTF("RRC mode: %s\n",
    			evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ?
    			"Connected" : "Idle\n");
    		break;
    	case LTE_LC_EVT_CELL_UPDATE:
    		DBG_PRINTF("LTE cell changed: Cell ID: %d, Tracking area: %d\n",
    		       evt->cell.id, evt->cell.tac);
    		break;
    	default:
    		break;
    	}
    } */
    
    static int configure_low_power(void)
    {
    	int err;
    
    #if defined(CONFIG_UDP_PSM_ENABLE)
    	/** Power Saving Mode */
    	err = lte_lc_psm_req(true);
    	if (err) {
    		printk("lte_lc_psm_req, error: %d\n", err);
    	}
    #else
    	err = lte_lc_psm_req(false);
    	if (err) {
    		printk("lte_lc_psm_req, error: %d\n", err);
    	}
    #endif
    
    #if defined(CONFIG_UDP_EDRX_ENABLE)
    	/** enhanced Discontinuous Reception */
    	err = lte_lc_edrx_req(true);
    	if (err) {
    		printk("lte_lc_edrx_req, error: %d\n", err);
    	}
    #else
    	err = lte_lc_edrx_req(false);
    	if (err) {
    		printk("lte_lc_edrx_req, error: %d\n", err);
    	}
    #endif
    
    #if defined(CONFIG_UDP_RAI_ENABLE)
    	/** Release Assistance Indication  */
    	err = lte_lc_rai_req(true);
    	if (err) {
    		printk("lte_lc_rai_req, error: %d\n", err);
    	}
    #endif
    
    	return err;
    }
    
    static int modem_init(void)
    {
    	int err = 0;
    
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already configured and LTE connected. */
    	} else {
    		err = lte_lc_init();
    		if (err) {
    			printk("LTE Modem initialization failed, error: %d\n", err);
    			return err;
    		}
    		else {
    			DBG_PRINTF("LTE modem initialised\r\n");
    		}
    	}
    	return err;
    }
    
    static int modem_connect(void)
    {
    	int err = 0;
    
    	DBG_PRINTF("Waiting for network.. ");
    	//## Note that timeout in seconds is set in prj.conf by CONFIG_LTE_NETWORK_TIMEOUT
    	err = lte_lc_init_and_connect();
    
    	if (err) {
    			DBG_PRINTF("Connecting to celluar network failed, error: %d\n",
    			       err);
    			return err;
    		}
    		else {
    			DBG_PRINTF(".Cellular modem connected\r\n");
    		}
    	
    	/* if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		// Do nothing, modem is already configured and LTE connected.
    	} else {
    		err = lte_lc_connect_async(lte_handler);
    		if (err) {
    			DBG_PRINTF("Connecting to LTE network failed, error: %d\n",
    			       err);
    			return;
    		}
    		else {
    			DBG_PRINTF("LTE modem connected\r\n");
    		}
    	} */
    
    	return err;
    }
    #endif
    
    static void server_disconnect(void)
    {
    	(void)close(client_fd);
    }
    
    //## Configures the socket host address in struct host_addr
    static int server_init(void)
    {
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&host_addr);
    
    	server4->sin_family = AF_INET;
    	server4->sin_port = htons(CONFIG_UDP_SERVER_PORT);
    
    	//## CONFIG_UDP_SERVER_ADDRESS_STATIC is the udp destination address - defined in prj.conf
    	inet_pton(AF_INET, CONFIG_UDP_SERVER_ADDRESS_STATIC, &server4->sin_addr);
    
    	return 0;
    }
    
    
    //## Creates the DTLS socket
    static int server_connect(void)
    {
    	int err;
    
    #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    	client_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_DTLS_1_2);
    
    	if (client_fd < 0) {
    	printk("Failed to create DTLS socket: %d\r\n", errno);
    	err = -errno;
    	goto error;
    	}
    	else {
    		DBG_PRINTF("\r\nCreated DTLS socket: %d\r\n", client_fd);
    	}
    
    	sec_tag_t sec_tag_list[] = {
    		// CA_CERTIFICATE_TAG,
    		PSK_TAG
    	};
    
    
    	err = setsockopt(client_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, sizeof(sec_tag_t) * ARRAY_SIZE(sec_tag_list));
    	if (err < 0) {
    		printk("Failed to set TLS_SEC_TAG_LIST option: %d\r\n", errno);
    		err = -errno;
    		goto error;
    	}
    	else {
    		DBG_PRINTF("Set TLS_SEC_TAG_LIST option\r\n");
    	}
    
    
    	/******************************* Sets the cipher suite ***********************************/
    
    	// If this section is commented all cipher suites enabled in overlay-tls-conf become available
    
    	nrf_sec_cipher_t cipher_list[] = {0x008D}; // IANA id for TLS_PSK_WITH_AES_256_CBC_SHA
    
    	err = setsockopt(client_fd, SOL_TLS, TLS_CIPHERSUITE_LIST, cipher_list, sizeof(cipher_list));
    	if (err < 0) {
    		printk("Failed to set cipher\r\n");
    	}
    	else {
    		DBG_PRINTF("cypher was set\r\n");
    	}
    
    	/********************************************************************************************/
    	
    
    #else	
    	client_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    
    	if (client_fd < 0) {
    		printk("Failed to create UDP socket: %d\r\n", errno);
    		err = -errno;
    		goto error;
    	}
    	else {
    		DBG_PRINTF("\r\nCreated UDP socket: %d\r\n", client_fd);
    	}
    
    #endif	
    
    	err = setsockopt(client_fd, SOL_TLS, TLS_HOSTNAME, TLS_PEER_HOSTNAME, sizeof(TLS_PEER_HOSTNAME));
    	if (err < 0) {
    		printk("Failed to set TLS_HOSTNAME option: %d\r\n",errno);
    		err = -errno;
    		goto error;
    	}
    	else {
    		DBG_PRINTF("TLS_HOSTNAME set to: %.*s\r\n", sizeof(TLS_PEER_HOSTNAME)-1, TLS_PEER_HOSTNAME);
    	}
    
    	//## Time structure for the socket timeout option below
    	struct timeval timeo = {
    		.tv_sec = CONNECT_TIMEOUT,
    		.tv_usec = 0,
    	};
    
    	//## Set a socket peer connect timeout - times out if the dtls2mqtt gateway doesn't respond
    	err = setsockopt(client_fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo));
    	if (err) {
    		DBG_PRINTF("Failed to set socket timeout, errno %d", errno);
    		err = -errno;
    		goto error;
    	}
    
    	DBG_PRINTF("Trying to connect to: ");
    #ifdef CONFIG_PRINT_DBG
    	printhex(host_addr.data,sizeof(host_addr.data));
    #endif
    	DBG_PRINTF("\r\n");
    
    	//## zsock_connect - connect socket to dtls peer - our udp2mqtt gateway
    	//## https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/zephyr/connectivity/networking/api/sockets.html
    	err = connect(client_fd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		printk("Connect failed : %d\n", errno);
    		goto error;
    	}
    	else {
    		DBG_PRINTF("Server Connected\r\n");
    	}
    
    	return 0;
    
    error:
    	server_disconnect();
    	return err;
    }
    
    static void baseuart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	struct communications_event commsevent; // message queue item
    
    	switch (evt->type) {
    	
    	case UART_TX_DONE:
    		// DBG_PRINTF("--> Reply sent to base\r\n");
    		// do something
    		break;
    
    	case UART_TX_ABORTED:
    		// do something
    		break;
    		
    	case UART_RX_RDY:
    		// DBG_PRINTF("Received data %d bytes\r\n", evt->data.rx.len);
    		commsevent.length = evt->data.rx.len;
    		//## Copy data from dma rx buffer to message queue buffer
    		memcpy(commsevent.data, &evt->data.rx.buf[evt->data.rx.offset], evt->data.rx.len); // copy received bytes to message queue
    		
    		printk("commsevent data is: ");
    		for (int i = 0; i < commsevent.length; i++) printk("%02X",commsevent.data[i]);
    		printk(" length: %u\r\n",commsevent.length);
    
    		if (commsevent.length != UPLINK_RCV_BUF_SIZE) { // Error
    			// send an error control message to base uart
    			// should then resend
    			DBG_PRINTF("Error - uart uplink message length\r\n");
    			//## reset DMA receive buffer
    		}
    		//## push base uart received buffer on message queue
    		while (k_msgq_put(&receive_event_msq, &commsevent, K_NO_WAIT) != 0)  {
    			//## message queue is full: purge old data & try again
    			// DBG_PRINTF("k_msgq is full, purging\r\n"); 
    			// k_msgq_purge(&receive_event_msq);
    			printk("Message Q full, shouldn't happen - resetting!\r\n");
    			NVIC_SystemReset();
    		}
    	
    		//## Disabling the uart causes it to be enabled again below
    		uart_rx_disable(baseuart);
    		DBG_PRINTF("Base Uart disabled ..");
    		
    		break;
    
    	case UART_RX_BUF_REQUEST:
    		// do something
    		break;
    
    	case UART_RX_BUF_RELEASED:
    		// DBG_PRINTF("Rx buffer released\r\n");
    
    		// do something
    		break;
    		
    	case UART_RX_DISABLED:
    		uart_rx_enable(baseuart, rx_buf, sizeof(rx_buf), 100);
    		DBG_PRINTF("..re-enabled\r\n");
    		break;
    
    	case UART_RX_STOPPED:
    		// do something
    		break;
    		
    	default:
    		break;
    				}
    }
    
    
    /******************************************************************************/
    
    static int dtls_init(void) {
    
    int err;
    
    // Delete Modem Credentials
    // modem_key_mgmt_delete(PSK_TAG,  MODEM_KEY_MGMT_CRED_TYPE_PSK);
    // modem_key_mgmt_delete(PSK_TAG,  MODEM_KEY_MGMT_CRED_TYPE_IDENTITY);
    
    // Check for existing credentials
    bool exists;
    err = modem_key_mgmt_exists(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, &exists);
    if (err == 0) {
    	DBG_PRINTF("Modem PSK Credential %s\r\n", exists ? "psk exists" : "psk doesn't exist");
    }
    else {
    	printk("Modem psk credentials check failed!\r\n");
    }
    
    err = modem_key_mgmt_exists(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, &exists);
    if (err == 0) {
    	DBG_PRINTF("Modem PSK_ID Credential %s\r\n", exists ? "psk id exists" : "psk id doesn't exist");
    }
    else {
    	printk("Modem psk id credentials check failed!\r\n");
    }
    
    err = modem_key_mgmt_cmp(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, psk_id, (size_t) sizeof(psk_id)-1);
    if (err == 0) {
    	DBG_PRINTF("PSK ID matches modem\r\n");
    }
    else if (err == 1) {
    		DBG_PRINTF("PSK ID doesn't match modem\r\n");
    	}
    	else {
    		printk("PSK ID compare match error %d\r\n", err);
    	}
    
    
    // Write DTLS credentials to the modem store, i.e. psk and psk identity
    // modem_key_mgmt_write(nrf_sec_tag_t sec_tag, enum modem_key_mgmt_cred_type cred_type, const void *buf, size_t len)
    #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT)
    	err = modem_key_mgmt_write(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, psk, (size_t) sizeof(psk));
    	if (err < 0) {
    		printk("Failed to register PSK: %d\r\n", err);
    	}
    	else {
    		DBG_PRINTF("PSK registered: %.*s\r\n", (size_t) sizeof(psk), psk);
    	}
    
    	err = modem_key_mgmt_write(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, psk_id,(size_t) sizeof(psk_id)-1);
    	if (err < 0) {
    		printk("Failed to register PSK ID: %d\r\n", err);
    	}
    	else {
    		DBG_PRINTF("PSK ID registered: %.*s\r\n", (size_t) sizeof(psk_id)-1, psk_id);
    	}
    
    	// err = modem_key_mgmt_delete(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY);
    	// if (err < 0) {
    	// printk("Failed to delete PSK ID: %d\r\n", err);
    	// }
    	// else {
    	// 	DBG_PRINTF("PSK ID deleted: %.*s\r\n", sizeof(psk_id)-1, psk_id);
    	// }
    
    
    #endif
    
    
    #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    
            // Provision Client PSK.
    	// err = tls_credential_add(PSK_TAG,TLS_CREDENTIAL_PSK,psk,sizeof(psk));
    	// if (err < 0) {
    	// 	DBG_PRINTF("Failed to register TLS PSK: %d", err);
        //             return err;
    	// }
    	// else {
    	// 	DBG_PRINTF("TLS PSK registered\r\n");
    	// }
    
            // Provision Client Identity.
    	// err = tls_credential_add(PSK_TAG,TLS_CREDENTIAL_PSK_ID,psk_id,sizeof(psk_id)-1);
    	// if (err < 0) {
    	// 	printk("Failed to register TLS PSK ID: %d", err);
        //             return err;
    	// }
    	// else {
    	// 	DBG_PRINTF("TLS PSK ID registered\r\n");
    	// }
    
    #endif
    
    return err;
    
    }
    
    static K_MUTEX_DEFINE(lte_mutex);
    static K_CONDVAR_DEFINE(lte_condvar);
    static volatile int lte_connected_state = 0;
    static k_timeout_t timeout;
    time_t time;
    
    static int lte_connection_wait(k_timeout_t timeout)
    {
       int res = 0;
       k_mutex_lock(&lte_mutex, timeout);
       res = lte_connected_state;
       if (!res) {
          k_condvar_wait(&lte_condvar, &lte_mutex, timeout);
          res = lte_connected_state;
       }
       k_mutex_unlock(&lte_mutex);
       return res;
    }
    
    static int modem_connection_wait(const k_timeout_t timeout)
    {
       int err = 0;
       k_timeout_t time = K_MSEC(0);
       k_timeout_t interval = K_MSEC(1500);
       while (!lte_connection_wait(interval)) {
          time.ticks += interval.ticks;
          if ((time.ticks - timeout.ticks) > 0) {
             err = 1;
             break;
          }
       }
       return err;
    }
    
    /****************************************************************************/
    
    void main(void)
    {
    	int err = 0;
    
    	DBG_PRINTF("UDP DTLS client has started\n");
    
    	// baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)
    	baseuart = DEVICE_DT_GET(DT_NODELABEL(uart2));
    
    	if (!device_is_ready(baseuart)) {
    		printk("Uart2 not ready!\r\n");
    		return;
    	}
    
    	err = uart_configure(baseuart, &baseuart_cfg);
    	if (err == 0) {
    		DBG_PRINTF("baseuart configured\r\n");
    	}
    
    	do {
    
    	
    #if defined(CONFIG_NRF_MODEM_LIB)
    
    	// Initialize the modem before calling configure_low_power(). This is
    	// because the enabling of RAI is dependent on the
    	// configured network mode which is set during modem initialization.
    	
    	err = modem_init();
    	if (err) goto err_exit;
    
    	err = configure_low_power();
    	if (err) {
    		printk("Unable to set low power configuration, error: %d\n", err);
    		goto err_exit;
    	}
    
    #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT) &&  defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    	dtls_init( );
    #endif
    	err = modem_connect();
    	if (err) 
    		goto err_exit;
    
    	if (!err) {
          time = k_uptime_get();
          err = modem_connection_wait(timeout);
          time = k_uptime_get() - time;
          if (!err) 
            printk("LTE connected in %ld [ms]", (long)time);
    	}
    
    	// k_sem_take(&lte_connected, K_FOREVER);
    #endif
    
    	err = server_init();
    	if (err) {
    		printk("Not able to initialize UDP server connection\n");
    		goto err_exit;
    	}
    
    
    //## Start transmission application workqueue here ######
    
    k_work_queue_init(&transmission_work_q);
    
    k_work_queue_start(&transmission_work_q, transmission_stack_area,
                       K_THREAD_STACK_SIZEOF(transmission_stack_area), TRANSMISSION_PRIORITY,
                       NULL);
    
    //##############################################
    
    err_exit:
    
    	dtlssendretrycount += 1;
    
    	if ((err != 0) && (dtlssendretrycount <= MAXINITRETRIES)) {
    		printk("Modem initialisation failed ..wait.");
    		k_msleep(10000);
    		printk("..retrying\r\n");
    	}
    
    	} while( (err != 0) && (dtlssendretrycount > MAXINITRETRIES) );
    
    	if (err != 0) { // Init failed after max retries, resetting modem
    		printk("Modem initialisation failed after %u retries\r\n",MAXINITRETRIES);
    		NVIC_SystemReset();
    	}
    
    	server_transmission_worker_init();  // initialise the udp worker
    	baseuart_connect_async(baseuart); // Also creates dma buffer storage
    	//## Kick off main transmission worker here
     	// k_work_submit(&server_transmission_work);  // uses system workqueue
    	k_work_submit_to_queue(&transmission_work_q, &server_transmission_work); // uses application workqueue
    
    
    }
    

    Again, appreciate your assistance with this, as I've had another look but am still stuck!

    Cheers, Ron

Reply
  • Hi Marte

    Simplest is to list the entire application here, which isn't particularly lengthy:

    /*
     * Copyright (c) 2020 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    #include <zephyr/logging/log.h>
    // LOG_MODULE_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG);
    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <modem/lte_lc.h>
    #include <zephyr/net/socket.h>
    #include <zephyr/net/tls_credentials.h>
    #include <drivers/uart.h>
    #include <string.h>
    #include "ca_certificate.h"
    #include <zephyr/net/net_context.h>
    #include <modem/modem_key_mgmt.h>
    #include <nrfx.h>
    #include <nrf_socket.h>
    #include <modem/nrf_modem_lib.h>
    
    
    
    #define CONFIG_PRINT_DBG 1
    
    #ifdef CONFIG_PRINT_DBG
    #define DBG_PRINTF(...)    printk(__VA_ARGS__)
    #else
    #define DBG_PRINTF(...)
    #endif
    
    // static const char psk[] = "3081269BCCC4FA7509AAA00C182D0595";
    // static const char psk_id[] = "70B3D5CD00010064";
    
    static char psk[] = "3081269BCCC4FA7509AAA00C182D0595";
    static char psk_id[] = "70B3D5CD00010064";
    static uint8_t validkeysexist = 0;
    
    
    
    #define UDP_IP_HEADER_SIZE 28
    
    
    /**
     * @brief Max size of baseuart event queue
     * 
     */
    #define RECEIVE_EVENT_QUEUE_SIZE 4
    
    //## dtls receive buffer size
    #define DOWNLINK_RCV_BUF_SIZE 16
    //## baseuart dma receive buffer size - multiple of 4 bytes boundary
    #define UPLINK_RCV_BUF_SIZE 24
    
    
    #define MAXSENDRETRIES 3
    #define MAXINITRETRIES	5
    #define MAXSERVERCONNECTRETRIES 5
    
    static int client_fd;
    static struct sockaddr_storage host_addr; 
    static struct k_work server_transmission_work; // A work Q element - infinite loop that receives, parses and acts on message events
    static void server_disconnect(void);
    static uint8_t dtlssendretrycount = 0;
    static uint8_t serverfailcount = 0; // connection failure count
    uint8_t sendretrycount = 0;
    
    #define TRANSMISSION_STACK_SIZE 1536
    #define TRANSMISSION_PRIORITY 5
    
    K_THREAD_STACK_DEFINE(transmission_stack_area, TRANSMISSION_STACK_SIZE); // define memory for application workqueue
    
    struct k_work_q transmission_work_q;
    
    
    // static struct k_work sensor_rx_event_work;
    
    K_SEM_DEFINE(lte_connected, 0, 1);
    
    
    struct communications_event
    {
       size_t length; 
       uint8_t data[UPLINK_RCV_BUF_SIZE];
    };
    
    //## A socket peer connect timeout value
    #define CONNECT_TIMEOUT	8
    
    //## Define message queue to receive sensor data to be transmitted via udp
    K_MSGQ_DEFINE(receive_event_msq, sizeof(struct communications_event), RECEIVE_EVENT_QUEUE_SIZE, 4);
    
    //## Do we need another message queue for downlink commands data?
    
    
    uint32_t  packet_seqno = 0;
    
    
    const struct device *baseuart;  // base board link UART
    
    //## Configure the base board link UART at run time
    const struct uart_config baseuart_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
    	};
    
    
    static K_MEM_SLAB_DEFINE(uart_slab, UPLINK_RCV_BUF_SIZE, 3, 4);
    
    uint8_t rx_buf[UPLINK_RCV_BUF_SIZE] = {0}; // A buffer to store incoming UART data
    
    // char __aligned(4) my_msgq_buffer[10 * sizeof(rx_buf)];
    //K_MSGQ_DEFINE(my_msgq, sizeof(rx_buf), 10, 4);
    
    static void baseuart_cb(const struct device *dev, struct uart_event *evt, void *user_data);
    static int server_init(void);
    static int server_connect(void);
    
    typedef enum eventtype_e  // uplink event type - first byte sent
    {
    	sensorevent = 0,
        configevent,
        dataevent,
        errorevent,
        alarmevent,
        linkcntrl    // Link control event such as check for modem ready
    } eventtype_t;
    
    typedef enum lnkctrlcmnd_e // uplink linkcntrl value, downlink ack command value
    {
    	dummy = 0,
        ok = 0x31,	// cmnd is used to indicate both modem ready query and ok response
    	ko = 0x32 // error
    } lnkctrlcmnd_t;
    
    typedef enum command_e
    {
    	sleepperiod = 0x10,
    	acknowledge = 0x41,
    	sendpsk = 0x91,
    	resetdevice = 0xFF
    } command_t;
    
    
    #ifdef CONFIG_PRINT_DBG
    static void printhex(uint8_t * buf, int size) {
    	for (uint8_t i=0; i<size; i++) {
    		printk("%02X",buf[i]);
    	}
    	printk("\r\n");
    }
    #endif
    
    
    
    static void baseuart_connect_async(const struct device *baseuart)
    {
    	int err;
    
    	err = k_mem_slab_alloc(&uart_slab, (void **)rx_buf, K_NO_WAIT);
    	__ASSERT(err == 0, "Failed to alloc slab");
    
    	err = uart_callback_set(baseuart, baseuart_cb, (void *)baseuart);
    	__ASSERT(err == 0, "Failed to set callback");
    
    	err = uart_rx_enable(baseuart ,rx_buf,sizeof(rx_buf), 100);
    	if (err == 0) {
    		DBG_PRINTF("Rx from sensor enabled\r\n");
    	}
    	else {
    		printk("Rx enable failed\r\n");
    	}
    }
    
    
    
    static int send2base(uint8_t* msgbuf, size_t msglen) {
    	//## Messages sent to the application mcu via uart are fixed length binary
    	//*  of length DOWNLINK_RCV_BUF_SIZE so need to be padded accordingly
    	memset(&msgbuf[msglen], 0, DOWNLINK_RCV_BUF_SIZE - msglen);
    	//## Send receive message to base board via dma transmit
    	uart_tx(baseuart, msgbuf, DOWNLINK_RCV_BUF_SIZE, SYS_FOREVER_MS);
    	printk("--> Sending: ");
    	printhex(msgbuf,DOWNLINK_RCV_BUF_SIZE);	
    	return 0;
    }
    
    static void sendack2base(int value) { // 0 is OK, 1 is KO
    	#define MSGLEN 2
    	uint8_t msgbuf[DOWNLINK_RCV_BUF_SIZE];
    	msgbuf[0] = acknowledge;
    	if (value == ok) {
    		msgbuf[1] = ok;	
    	}
    	else {
    		msgbuf[1] = ko;
    	}
    	send2base(msgbuf, MSGLEN);
    }
    
    int8_t storePSK(struct communications_event commsevent) {
    
    	if (crc8(commsevent.data, commsevent.length-1) == commsevent.data[commsevent.length]) {
    		// store keys
    		memcpy(psk_id, &commsevent.data[1], 8);
    		memcpy(psk, &commsevent.data[9], 16);
    		DBG_PRINTF("PSK_ID & PSK were stored\r\n");
    		validkeysexist = 1;
    	}
    	else { //crc error
    		DBG_PRINTF("storePSK CRC Error!\r\n");
    		return -1;
    	}
    	return 0;
    }
    
    //## Sends sensor data to the remote udp destination and receives downlink data replies 
    static void server_transmission_work_fn(struct k_work *work)
    {
    	int err;
    	struct communications_event commsevent; //## NB - communications_event struct data buffer is currently size 96 in sockets.h
    	int received;
    	uint8_t recv_buf[DOWNLINK_RCV_BUF_SIZE];
    
    	for(;;) { // infinite loop
    
    		DBG_PRINTF("\r\n>>> server_transmission_work_fn started <<<\r\n\r\n");
    
    		//## read message to process from the message queue
    		//## NB - k_forever waits until a message arrives in the queue
    		k_msgq_get(&receive_event_msq, &commsevent, K_FOREVER);
    
    
    		//## Parse event messages from the message receive queue - base mcu and gateway messages
    		//## first byte indicates message type, e.g. sensor data, modem command etc
    		//## if modem command type message second byte is the command itself
    		uint8_t skiptoend = 0;
    		switch(commsevent.data[0]) {
    			case linkcntrl: // uplink message type 0x05
    				switch(commsevent.data[1]) {
    					case ok:
    						DBG_PRINTF(">RuRdy request received\r\n");
    						// check if keys are stored
    						if (!validkeysexist) { // send request for keys
    							DBG_PRINTF(">Requesting keys\r\n");
    							commsevent.data[0] = sendpsk;
    							err = send2base(commsevent.data, 1); // send 1 bytes
    						}
    						else {
    							// need to return 2 downlink acknowledgement bytes: command, value
    							commsevent.data[0] = acknowledge;
    							commsevent.data[1] = ok; //set value to return
    							err = send2base(commsevent.data, 2); // send 2 bytes
    						}
    						skiptoend = 1; // restart main loop
    						break;
    				} // end switch commsevent.data[1]
    				break;
    			case acknowledge: // 0x41 - ack from dtls2mqtt gateway
    				//## NB - Gateway response can be passed through to base mcu
    				//##  command 0x41 followed by val 0x31=ok or 0x32=ko
    				err = send2base(commsevent.data, 2); // send 2 bytes
    				skiptoend = 1; // restart main loop
    			case sensorevent: // 0x00
    				//## For a sensorevent the code after the switch is executed without skipping to end
    				;
    				break;	
    			case configevent: // 0x01 - configuration echo from app mcu
    				//## For a config echo the code after the switch is executed without skipping to end
    				;
    				break;	
    			case sendpsk: // 0x91 - payload arrived = sendpsk + psk_id + psk + crc8
    				// check the validity of the payload crc8
    				if (storePSK(commsevent) != 0) {
    					// if fail return another sendpsk request
    					commsevent.data[0] = sendpsk;
    					err = send2base(commsevent.data, 1); // send 1 bytes
    				}
    				else {
    					// otherwise update the keys and return ok
    					commsevent.data[0] = acknowledge;
    					commsevent.data[1] = ok; //set value to return
    					err = send2base(commsevent.data, 2); // send 2 bytes
    				}
    				skiptoend = 1;
    				break;
    			default:
    				//## All other data events assumed to be downlink commands
    				//## to be passed through to base mcu as is
    				//## base mcu is expected to validate, avoids modem storing
    				//## valid commands
    				err = send2base(commsevent.data, DOWNLINK_RCV_BUF_SIZE); // send max bytes
    				skiptoend = 1; // restart main loop
    		} // end switch commsevent.data[0]
    
    		if (skiptoend)
    			continue;
    
    		DBG_PRINTF("Transmitting UDP/IP payload of %d bytes to the ", commsevent.length);
    		// DBG_PRINTF("Transmitting UDP/IP payload of %d bytes to the ", commsevent.length + UDP_IP_HEADER_SIZE);
    		DBG_PRINTF("IP address %s, port number %d\n", CONFIG_UDP_SERVER_ADDRESS_STATIC, CONFIG_UDP_SERVER_PORT);
    		DBG_PRINTF("Message buffer to send is: ");	
    #ifdef CONFIG_PRINT_DBG
    		for (int i = 0; i < commsevent.length; i++) printk("%02X",commsevent.data[i]);
    		printk("\r\n");
    #endif
    
    		/*******************************************************************/
    
    		//## NB - need to reconnect (create socket) for each transmission, disconnect after receive timeout
    		//## or on error
    	
    		uint8_t serverconnected = 0;
    		err = server_connect();
    		if (err) {
    			printk("Not able to connect to UDP server\n");
    			serverfailcount += 1;
    			if (serverfailcount >= MAXSERVERCONNECTRETRIES) {
    				printk("Server Connect failed after %u retries - resetting!\r\n",MAXSERVERCONNECTRETRIES);
    				NVIC_SystemReset();
    			}
    			goto exitloop;
    			
    		}
    		else {
    			DBG_PRINTF("Connected to UDP Server\r\n");
    			serverfailcount = 0;
    			serverconnected = 1;
    		}
    
    		/******************************************************************/
    
    		// if (endndx > 0) { // endndx is the length of data to send - packet found if endndx > 0
    		if (commsevent.length > 0) { // packet from base to send
    			uint8_t dtlssendretrycount = 0;
    			do {
    				// err = send(client_fd,&commsevent.data[startndx],endndx, 0);
    				err = send(client_fd, commsevent.data, commsevent.length, 0);
    				if (err < 0) {
    					printk("Failed to transmit UDP packet, %d\n", errno);
    					dtlssendretrycount += 1;
    					if (dtlssendretrycount > 3) {
    						printk("dtls send command repeatedly failed!\r\n");
    						//## send KO to base
    						sendack2base(ko);
    						DBG_PRINTF("--> ko to base\r\n");
    						goto exitloop;
    					}
    					k_msleep(1000);
    				}
    				else {
    					//## send OK to base
    					sendack2base(ok);
    					DBG_PRINTF("--> ok to base\r\n");
    				}
    			} while ((dtlssendretrycount <= 3) && (err < 0));
    
    
    			memset(recv_buf,0, sizeof(recv_buf));
    			//## Receive udp return message
    			received = recv(client_fd, recv_buf, sizeof(recv_buf), MSG_WAITALL); //NB - If MSG_DONTWAIT flag used recv returns err and no message
    
    			if (received <= 0) {
    				DBG_PRINTF("No udp reply\r\n");
    				//## Saved outgoing message should be resent up to n times
    				//## By injecting into base uart receive message queue  
    				if (sendretrycount < MAXSENDRETRIES) {
    					//## push base uart received buffer back into message queue
    					while (k_msgq_put(&receive_event_msq, &commsevent, K_NO_WAIT) != 0)  {
    						//## message queue is full: purge old data & try again 
    						// k_msgq_purge(&receive_event_msq);
    						printk("Message Q full, shouldn't happen - resetting!\r\n");
    						NVIC_SystemReset();
    					}
    					sendretrycount += 1; // increment retry count
    				}
    				else { // return message ack ko or failure
    					sendack2base(ko);
    				}
    			}
    			else {
    				sendretrycount = 0;
    // #ifdef CONFIG_PRINT_DBG
    				printk("udp reply is: ");
    				for (int i = 0; i < received; i++) printk("%02X",recv_buf[i]);
    				printk(" length: %d\r\n", received);
    // #endif
    				
    				err = send2base(recv_buf, received); // send received data to base mcu
    
    			}
    		}
    		else {
    			printk("Failed to find valid data to send\r\n");
    			//## return message ack ko or failure
    			sendack2base(ko);
    		}
    
    	exitloop:
    		//## Disconnect udp socket - closes client_fd
    		if (serverconnected)
    			server_disconnect( );
    
    
    	}// end infinite for(;;)
    
    }
    
    static void server_transmission_worker_init(void)
    {
    	// k_server_transmission_worker_init_delayable(&server_transmission_work, server_transmission_work_fn);
    	k_work_init(&server_transmission_work, server_transmission_work_fn);
    	// k_server_transmission_worker_init(&sensor_rx_event_work, sensor_rx_event_work_fn);
    	DBG_PRINTF("server transmission worker initialised\r\n");
    }
    
    #if defined(CONFIG_NRF_MODEM_LIB)
    /* static void lte_handler(const struct lte_lc_evt *const evt)
    {
    	switch (evt->type) {
    	case LTE_LC_EVT_NW_REG_STATUS:
    		if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
    		     (evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
    			break;
    		}
    
    		printk("Network registration status: %s\n",
    			evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
    			"Connected - home network" : "Connected - roaming\n");
    		k_sem_give(&lte_connected);
    		break;
    	case LTE_LC_EVT_PSM_UPDATE:
    		DBG_PRINTF("PSM parameter update: TAU: %d, Active time: %d\n",
    			evt->psm_cfg.tau, evt->psm_cfg.active_time);
    		break;
    	case LTE_LC_EVT_EDRX_UPDATE: {
    		char log_buf[60];
    		ssize_t len;
    
    		len = snprintf(log_buf, sizeof(log_buf),
    			       "eDRX parameter update: eDRX: %f, PTW: %f\n",
    			       evt->edrx_cfg.edrx, evt->edrx_cfg.ptw);
    		if (len > 0) {
    			DBG_PRINTF("%s\n", log_buf);
    		}
    		break;
    	}
    	case LTE_LC_EVT_RRC_UPDATE:
    		DBG_PRINTF("RRC mode: %s\n",
    			evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ?
    			"Connected" : "Idle\n");
    		break;
    	case LTE_LC_EVT_CELL_UPDATE:
    		DBG_PRINTF("LTE cell changed: Cell ID: %d, Tracking area: %d\n",
    		       evt->cell.id, evt->cell.tac);
    		break;
    	default:
    		break;
    	}
    } */
    
    static int configure_low_power(void)
    {
    	int err;
    
    #if defined(CONFIG_UDP_PSM_ENABLE)
    	/** Power Saving Mode */
    	err = lte_lc_psm_req(true);
    	if (err) {
    		printk("lte_lc_psm_req, error: %d\n", err);
    	}
    #else
    	err = lte_lc_psm_req(false);
    	if (err) {
    		printk("lte_lc_psm_req, error: %d\n", err);
    	}
    #endif
    
    #if defined(CONFIG_UDP_EDRX_ENABLE)
    	/** enhanced Discontinuous Reception */
    	err = lte_lc_edrx_req(true);
    	if (err) {
    		printk("lte_lc_edrx_req, error: %d\n", err);
    	}
    #else
    	err = lte_lc_edrx_req(false);
    	if (err) {
    		printk("lte_lc_edrx_req, error: %d\n", err);
    	}
    #endif
    
    #if defined(CONFIG_UDP_RAI_ENABLE)
    	/** Release Assistance Indication  */
    	err = lte_lc_rai_req(true);
    	if (err) {
    		printk("lte_lc_rai_req, error: %d\n", err);
    	}
    #endif
    
    	return err;
    }
    
    static int modem_init(void)
    {
    	int err = 0;
    
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already configured and LTE connected. */
    	} else {
    		err = lte_lc_init();
    		if (err) {
    			printk("LTE Modem initialization failed, error: %d\n", err);
    			return err;
    		}
    		else {
    			DBG_PRINTF("LTE modem initialised\r\n");
    		}
    	}
    	return err;
    }
    
    static int modem_connect(void)
    {
    	int err = 0;
    
    	DBG_PRINTF("Waiting for network.. ");
    	//## Note that timeout in seconds is set in prj.conf by CONFIG_LTE_NETWORK_TIMEOUT
    	err = lte_lc_init_and_connect();
    
    	if (err) {
    			DBG_PRINTF("Connecting to celluar network failed, error: %d\n",
    			       err);
    			return err;
    		}
    		else {
    			DBG_PRINTF(".Cellular modem connected\r\n");
    		}
    	
    	/* if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		// Do nothing, modem is already configured and LTE connected.
    	} else {
    		err = lte_lc_connect_async(lte_handler);
    		if (err) {
    			DBG_PRINTF("Connecting to LTE network failed, error: %d\n",
    			       err);
    			return;
    		}
    		else {
    			DBG_PRINTF("LTE modem connected\r\n");
    		}
    	} */
    
    	return err;
    }
    #endif
    
    static void server_disconnect(void)
    {
    	(void)close(client_fd);
    }
    
    //## Configures the socket host address in struct host_addr
    static int server_init(void)
    {
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&host_addr);
    
    	server4->sin_family = AF_INET;
    	server4->sin_port = htons(CONFIG_UDP_SERVER_PORT);
    
    	//## CONFIG_UDP_SERVER_ADDRESS_STATIC is the udp destination address - defined in prj.conf
    	inet_pton(AF_INET, CONFIG_UDP_SERVER_ADDRESS_STATIC, &server4->sin_addr);
    
    	return 0;
    }
    
    
    //## Creates the DTLS socket
    static int server_connect(void)
    {
    	int err;
    
    #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    	client_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_DTLS_1_2);
    
    	if (client_fd < 0) {
    	printk("Failed to create DTLS socket: %d\r\n", errno);
    	err = -errno;
    	goto error;
    	}
    	else {
    		DBG_PRINTF("\r\nCreated DTLS socket: %d\r\n", client_fd);
    	}
    
    	sec_tag_t sec_tag_list[] = {
    		// CA_CERTIFICATE_TAG,
    		PSK_TAG
    	};
    
    
    	err = setsockopt(client_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, sizeof(sec_tag_t) * ARRAY_SIZE(sec_tag_list));
    	if (err < 0) {
    		printk("Failed to set TLS_SEC_TAG_LIST option: %d\r\n", errno);
    		err = -errno;
    		goto error;
    	}
    	else {
    		DBG_PRINTF("Set TLS_SEC_TAG_LIST option\r\n");
    	}
    
    
    	/******************************* Sets the cipher suite ***********************************/
    
    	// If this section is commented all cipher suites enabled in overlay-tls-conf become available
    
    	nrf_sec_cipher_t cipher_list[] = {0x008D}; // IANA id for TLS_PSK_WITH_AES_256_CBC_SHA
    
    	err = setsockopt(client_fd, SOL_TLS, TLS_CIPHERSUITE_LIST, cipher_list, sizeof(cipher_list));
    	if (err < 0) {
    		printk("Failed to set cipher\r\n");
    	}
    	else {
    		DBG_PRINTF("cypher was set\r\n");
    	}
    
    	/********************************************************************************************/
    	
    
    #else	
    	client_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    
    	if (client_fd < 0) {
    		printk("Failed to create UDP socket: %d\r\n", errno);
    		err = -errno;
    		goto error;
    	}
    	else {
    		DBG_PRINTF("\r\nCreated UDP socket: %d\r\n", client_fd);
    	}
    
    #endif	
    
    	err = setsockopt(client_fd, SOL_TLS, TLS_HOSTNAME, TLS_PEER_HOSTNAME, sizeof(TLS_PEER_HOSTNAME));
    	if (err < 0) {
    		printk("Failed to set TLS_HOSTNAME option: %d\r\n",errno);
    		err = -errno;
    		goto error;
    	}
    	else {
    		DBG_PRINTF("TLS_HOSTNAME set to: %.*s\r\n", sizeof(TLS_PEER_HOSTNAME)-1, TLS_PEER_HOSTNAME);
    	}
    
    	//## Time structure for the socket timeout option below
    	struct timeval timeo = {
    		.tv_sec = CONNECT_TIMEOUT,
    		.tv_usec = 0,
    	};
    
    	//## Set a socket peer connect timeout - times out if the dtls2mqtt gateway doesn't respond
    	err = setsockopt(client_fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo));
    	if (err) {
    		DBG_PRINTF("Failed to set socket timeout, errno %d", errno);
    		err = -errno;
    		goto error;
    	}
    
    	DBG_PRINTF("Trying to connect to: ");
    #ifdef CONFIG_PRINT_DBG
    	printhex(host_addr.data,sizeof(host_addr.data));
    #endif
    	DBG_PRINTF("\r\n");
    
    	//## zsock_connect - connect socket to dtls peer - our udp2mqtt gateway
    	//## https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/zephyr/connectivity/networking/api/sockets.html
    	err = connect(client_fd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		printk("Connect failed : %d\n", errno);
    		goto error;
    	}
    	else {
    		DBG_PRINTF("Server Connected\r\n");
    	}
    
    	return 0;
    
    error:
    	server_disconnect();
    	return err;
    }
    
    static void baseuart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	struct communications_event commsevent; // message queue item
    
    	switch (evt->type) {
    	
    	case UART_TX_DONE:
    		// DBG_PRINTF("--> Reply sent to base\r\n");
    		// do something
    		break;
    
    	case UART_TX_ABORTED:
    		// do something
    		break;
    		
    	case UART_RX_RDY:
    		// DBG_PRINTF("Received data %d bytes\r\n", evt->data.rx.len);
    		commsevent.length = evt->data.rx.len;
    		//## Copy data from dma rx buffer to message queue buffer
    		memcpy(commsevent.data, &evt->data.rx.buf[evt->data.rx.offset], evt->data.rx.len); // copy received bytes to message queue
    		
    		printk("commsevent data is: ");
    		for (int i = 0; i < commsevent.length; i++) printk("%02X",commsevent.data[i]);
    		printk(" length: %u\r\n",commsevent.length);
    
    		if (commsevent.length != UPLINK_RCV_BUF_SIZE) { // Error
    			// send an error control message to base uart
    			// should then resend
    			DBG_PRINTF("Error - uart uplink message length\r\n");
    			//## reset DMA receive buffer
    		}
    		//## push base uart received buffer on message queue
    		while (k_msgq_put(&receive_event_msq, &commsevent, K_NO_WAIT) != 0)  {
    			//## message queue is full: purge old data & try again
    			// DBG_PRINTF("k_msgq is full, purging\r\n"); 
    			// k_msgq_purge(&receive_event_msq);
    			printk("Message Q full, shouldn't happen - resetting!\r\n");
    			NVIC_SystemReset();
    		}
    	
    		//## Disabling the uart causes it to be enabled again below
    		uart_rx_disable(baseuart);
    		DBG_PRINTF("Base Uart disabled ..");
    		
    		break;
    
    	case UART_RX_BUF_REQUEST:
    		// do something
    		break;
    
    	case UART_RX_BUF_RELEASED:
    		// DBG_PRINTF("Rx buffer released\r\n");
    
    		// do something
    		break;
    		
    	case UART_RX_DISABLED:
    		uart_rx_enable(baseuart, rx_buf, sizeof(rx_buf), 100);
    		DBG_PRINTF("..re-enabled\r\n");
    		break;
    
    	case UART_RX_STOPPED:
    		// do something
    		break;
    		
    	default:
    		break;
    				}
    }
    
    
    /******************************************************************************/
    
    static int dtls_init(void) {
    
    int err;
    
    // Delete Modem Credentials
    // modem_key_mgmt_delete(PSK_TAG,  MODEM_KEY_MGMT_CRED_TYPE_PSK);
    // modem_key_mgmt_delete(PSK_TAG,  MODEM_KEY_MGMT_CRED_TYPE_IDENTITY);
    
    // Check for existing credentials
    bool exists;
    err = modem_key_mgmt_exists(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, &exists);
    if (err == 0) {
    	DBG_PRINTF("Modem PSK Credential %s\r\n", exists ? "psk exists" : "psk doesn't exist");
    }
    else {
    	printk("Modem psk credentials check failed!\r\n");
    }
    
    err = modem_key_mgmt_exists(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, &exists);
    if (err == 0) {
    	DBG_PRINTF("Modem PSK_ID Credential %s\r\n", exists ? "psk id exists" : "psk id doesn't exist");
    }
    else {
    	printk("Modem psk id credentials check failed!\r\n");
    }
    
    err = modem_key_mgmt_cmp(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, psk_id, (size_t) sizeof(psk_id)-1);
    if (err == 0) {
    	DBG_PRINTF("PSK ID matches modem\r\n");
    }
    else if (err == 1) {
    		DBG_PRINTF("PSK ID doesn't match modem\r\n");
    	}
    	else {
    		printk("PSK ID compare match error %d\r\n", err);
    	}
    
    
    // Write DTLS credentials to the modem store, i.e. psk and psk identity
    // modem_key_mgmt_write(nrf_sec_tag_t sec_tag, enum modem_key_mgmt_cred_type cred_type, const void *buf, size_t len)
    #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT)
    	err = modem_key_mgmt_write(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, psk, (size_t) sizeof(psk));
    	if (err < 0) {
    		printk("Failed to register PSK: %d\r\n", err);
    	}
    	else {
    		DBG_PRINTF("PSK registered: %.*s\r\n", (size_t) sizeof(psk), psk);
    	}
    
    	err = modem_key_mgmt_write(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, psk_id,(size_t) sizeof(psk_id)-1);
    	if (err < 0) {
    		printk("Failed to register PSK ID: %d\r\n", err);
    	}
    	else {
    		DBG_PRINTF("PSK ID registered: %.*s\r\n", (size_t) sizeof(psk_id)-1, psk_id);
    	}
    
    	// err = modem_key_mgmt_delete(PSK_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY);
    	// if (err < 0) {
    	// printk("Failed to delete PSK ID: %d\r\n", err);
    	// }
    	// else {
    	// 	DBG_PRINTF("PSK ID deleted: %.*s\r\n", sizeof(psk_id)-1, psk_id);
    	// }
    
    
    #endif
    
    
    #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    
            // Provision Client PSK.
    	// err = tls_credential_add(PSK_TAG,TLS_CREDENTIAL_PSK,psk,sizeof(psk));
    	// if (err < 0) {
    	// 	DBG_PRINTF("Failed to register TLS PSK: %d", err);
        //             return err;
    	// }
    	// else {
    	// 	DBG_PRINTF("TLS PSK registered\r\n");
    	// }
    
            // Provision Client Identity.
    	// err = tls_credential_add(PSK_TAG,TLS_CREDENTIAL_PSK_ID,psk_id,sizeof(psk_id)-1);
    	// if (err < 0) {
    	// 	printk("Failed to register TLS PSK ID: %d", err);
        //             return err;
    	// }
    	// else {
    	// 	DBG_PRINTF("TLS PSK ID registered\r\n");
    	// }
    
    #endif
    
    return err;
    
    }
    
    static K_MUTEX_DEFINE(lte_mutex);
    static K_CONDVAR_DEFINE(lte_condvar);
    static volatile int lte_connected_state = 0;
    static k_timeout_t timeout;
    time_t time;
    
    static int lte_connection_wait(k_timeout_t timeout)
    {
       int res = 0;
       k_mutex_lock(&lte_mutex, timeout);
       res = lte_connected_state;
       if (!res) {
          k_condvar_wait(&lte_condvar, &lte_mutex, timeout);
          res = lte_connected_state;
       }
       k_mutex_unlock(&lte_mutex);
       return res;
    }
    
    static int modem_connection_wait(const k_timeout_t timeout)
    {
       int err = 0;
       k_timeout_t time = K_MSEC(0);
       k_timeout_t interval = K_MSEC(1500);
       while (!lte_connection_wait(interval)) {
          time.ticks += interval.ticks;
          if ((time.ticks - timeout.ticks) > 0) {
             err = 1;
             break;
          }
       }
       return err;
    }
    
    /****************************************************************************/
    
    void main(void)
    {
    	int err = 0;
    
    	DBG_PRINTF("UDP DTLS client has started\n");
    
    	// baseuart= device_get_binding(DT_LABEL(DT_NODELABEL(uart2)
    	baseuart = DEVICE_DT_GET(DT_NODELABEL(uart2));
    
    	if (!device_is_ready(baseuart)) {
    		printk("Uart2 not ready!\r\n");
    		return;
    	}
    
    	err = uart_configure(baseuart, &baseuart_cfg);
    	if (err == 0) {
    		DBG_PRINTF("baseuart configured\r\n");
    	}
    
    	do {
    
    	
    #if defined(CONFIG_NRF_MODEM_LIB)
    
    	// Initialize the modem before calling configure_low_power(). This is
    	// because the enabling of RAI is dependent on the
    	// configured network mode which is set during modem initialization.
    	
    	err = modem_init();
    	if (err) goto err_exit;
    
    	err = configure_low_power();
    	if (err) {
    		printk("Unable to set low power configuration, error: %d\n", err);
    		goto err_exit;
    	}
    
    #if defined(CONFIG_NRF_MODEM_LIB) && defined(CONFIG_MODEM_KEY_MGMT) &&  defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
    	dtls_init( );
    #endif
    	err = modem_connect();
    	if (err) 
    		goto err_exit;
    
    	if (!err) {
          time = k_uptime_get();
          err = modem_connection_wait(timeout);
          time = k_uptime_get() - time;
          if (!err) 
            printk("LTE connected in %ld [ms]", (long)time);
    	}
    
    	// k_sem_take(&lte_connected, K_FOREVER);
    #endif
    
    	err = server_init();
    	if (err) {
    		printk("Not able to initialize UDP server connection\n");
    		goto err_exit;
    	}
    
    
    //## Start transmission application workqueue here ######
    
    k_work_queue_init(&transmission_work_q);
    
    k_work_queue_start(&transmission_work_q, transmission_stack_area,
                       K_THREAD_STACK_SIZEOF(transmission_stack_area), TRANSMISSION_PRIORITY,
                       NULL);
    
    //##############################################
    
    err_exit:
    
    	dtlssendretrycount += 1;
    
    	if ((err != 0) && (dtlssendretrycount <= MAXINITRETRIES)) {
    		printk("Modem initialisation failed ..wait.");
    		k_msleep(10000);
    		printk("..retrying\r\n");
    	}
    
    	} while( (err != 0) && (dtlssendretrycount > MAXINITRETRIES) );
    
    	if (err != 0) { // Init failed after max retries, resetting modem
    		printk("Modem initialisation failed after %u retries\r\n",MAXINITRETRIES);
    		NVIC_SystemReset();
    	}
    
    	server_transmission_worker_init();  // initialise the udp worker
    	baseuart_connect_async(baseuart); // Also creates dma buffer storage
    	//## Kick off main transmission worker here
     	// k_work_submit(&server_transmission_work);  // uses system workqueue
    	k_work_submit_to_queue(&transmission_work_q, &server_transmission_work); // uses application workqueue
    
    
    }
    

    Again, appreciate your assistance with this, as I've had another look but am still stuck!

    Cheers, Ron

Children
  • Hi Ron,

    Based on this you do not need the additional configs in overlay-tls.conf, as you are using the TLS stack of the modem. Can you try building without this config?

    Best regards,

    Marte

  • Hi Marte

    Ok, I removed overlay-tls.conf from CMakeLists.txt

    and temporarily included conditional defines at the top of the application so that dtls_init etc that would otherwise be excluded is still built:

    #define CONFIG_NET_SOCKETS_SOCKOPT_TLS 
    #define CONFIG_NRF_MODEM_LIB 
    #define CONFIG_MODEM_KEY_MGMT 

    This now builds and runs, which is brilliant, thanks.

    Will remove those defines and corresponding conditional code that isn't being built.

    You've also encouraged me to do more study, as there's clearly been a misunderstanding on my part of what configuration options are needed and available when using the modem's TLS stack.

    Will now close the question as answered.

    Thanks again.

Related