Hi Nordic Team:
I use this example "freertos_coap_server", when the communication is abnormal, the network communication can be restored only after power failure and restart. Based on this example, I
changed the transmission protocol to udp. main.c is the only file I changed.This makes it easy to repeat the problem of abnormal test communication.I really hope to get your help.Thank you.
OS: Windows 10, IDE: Segger Embedded Studio for ARM 5.32, HW: NRF52840 DK
Segger project file is in examples\thread\freertos_coap_server\pca10056\blank\ses
NRF5_SDK_version:V4.2.0
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup freertos_coap_server_example_main main.c
* @{
* @ingroup freertos_coap_server_example
*
* @brief Thread CoAP server example with FreeRTOS Application main file.
*
* This file contains the source code for a sample application using Thread CoAP server and FreeRTOS.
*
*/
#include "FreeRTOS.h"
#include "nrf_drv_clock.h"
#include "task.h"
#define NRF_LOG_MODULE_NAME APP
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
#include "app_timer.h"
#include "bsp_thread.h"
#include "thread_coap_utils.h"
#include "thread_utils.h"
#include <openthread/instance.h>
#include <openthread/thread.h>
#define THREAD_STACK_TASK_STACK_SIZE (( 1024 * 8 ) / sizeof(StackType_t)) /**< FreeRTOS task stack size is determined in multiples of StackType_t. */
#define LOG_TASK_STACK_SIZE ( 1024 / sizeof(StackType_t)) /**< FreeRTOS task stack size is determined in multiples of StackType_t. */
#define THREAD_STACK_TASK_PRIORITY 2
#define LOG_TASK_PRIORITY 1
#define LED1_TASK_PRIORITY 1
#define LED2_TASK_PRIORITY 1
#define LED1_BLINK_INTERVAL 427
#define LED2_BLINK_INTERVAL 472
#define LOG_TASK_INTERVAL 100
typedef struct
{
TaskHandle_t thread_stack_task; /**< Thread stack task handle */
TaskHandle_t led1_task; /**< LED1 task handle*/
TaskHandle_t led2_task; /**< LED2 task handle*/
TaskHandle_t ot_app;
#if NRF_LOG_ENABLED
TaskHandle_t logger_task; /**< Definition of Logger thread. */
#endif
} application_t;
application_t m_app =
{
.thread_stack_task = NULL,
.led1_task = NULL,
.led2_task = NULL,
.ot_app = NULL,
#if NRF_LOG_ENABLED
.logger_task = NULL,
#endif
};
/***************************************************************************************************
* @section CoAP
**************************************************************************************************/
static inline void light_on(void)
{
vTaskResume(m_app.led1_task);
vTaskResume(m_app.led2_task);
}
static inline void light_off(void)
{
vTaskSuspend(m_app.led1_task);
LEDS_OFF(BSP_LED_2_MASK);
vTaskSuspend(m_app.led2_task);
LEDS_OFF(BSP_LED_3_MASK);
}
static inline void light_toggle(void)
{
if (!thread_coap_utils_light_is_led_blinking())
{
light_on();
}
else
{
light_off();
}
}
static void on_light_change(thread_coap_utils_light_command_t command)
{
switch (command)
{
case THREAD_COAP_UTILS_LIGHT_CMD_ON:
light_on();
break;
case THREAD_COAP_UTILS_LIGHT_CMD_OFF:
light_off();
break;
case THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE:
light_toggle();
break;
default:
ASSERT(false);
break;
}
}
/***************************************************************************************************
* @section Signal handling
**************************************************************************************************/
void otTaskletsSignalPending(otInstance * p_instance)
{
if (m_app.thread_stack_task == NULL)
{
return;
}
UNUSED_RETURN_VALUE(xTaskNotifyGive(m_app.thread_stack_task));
}
void otSysEventSignalPending(void)
{
static BaseType_t xHigherPriorityTaskWoken;
if (m_app.thread_stack_task == NULL)
{
return;
}
vTaskNotifyGiveFromISR(m_app.thread_stack_task, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/***************************************************************************************************
* @section State change handling
**************************************************************************************************/
static void thread_state_changed_callback(uint32_t flags, void * p_context)
{
if (flags & OT_CHANGED_THREAD_ROLE)
{
switch(otThreadGetDeviceRole(p_context))
{
case OT_DEVICE_ROLE_CHILD:
case OT_DEVICE_ROLE_ROUTER:
case OT_DEVICE_ROLE_LEADER:
break;
case OT_DEVICE_ROLE_DISABLED:
case OT_DEVICE_ROLE_DETACHED:
default:
thread_coap_utils_provisioning_enable_set(false);
break;
}
}
NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n", flags, otThreadGetDeviceRole(p_context));
}
/***************************************************************************************************
* @section Buttons
**************************************************************************************************/
static void bsp_event_handler(bsp_event_t event)
{
switch (event)
{
case BSP_EVENT_KEY_3:
thread_coap_utils_provisioning_enable_set(true);
break;
default:
return;
}
}
/***************************************************************************************************
* @section Initialization
**************************************************************************************************/
/**@brief Function for initializing the Application Timer Module
*/
static void timer_init(void)
{
uint32_t error_code = app_timer_init();
APP_ERROR_CHECK(error_code);
}
/**@brief Function for initializing the Thread Board Support Package
*/
static void thread_bsp_init(void)
{
uint32_t error_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
APP_ERROR_CHECK(error_code);
error_code = bsp_thread_init(thread_ot_instance_get());
APP_ERROR_CHECK(error_code);
}
/**@brief Function for initializing the Thread Stack
*/
static void thread_instance_init(void)
{
thread_configuration_t thread_configuration =
{
.radio_mode = THREAD_RADIO_MODE_RX_ON_WHEN_IDLE,
.autocommissioning = true,
};
thread_init(&thread_configuration);
//thread_cli_init();
thread_state_changed_callback_set(thread_state_changed_callback);
}
/**@brief Function for initializing the Constrained Application Protocol Module
*/
static void thread_coap_init(void)
{
thread_coap_utils_configuration_t thread_coap_configuration =
{
.coap_server_enabled = true,
.coap_client_enabled = false,
.configurable_led_blinking_enabled = true,
};
thread_coap_utils_init(&thread_coap_configuration);
}
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
/**@brief Function for initializing the clock.
*/
static void clock_init(void)
{
ret_code_t err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
}
static void thread_stack_task(void * arg)
{
UNUSED_PARAMETER(arg);
while (1)
{
thread_process();
UNUSED_RETURN_VALUE(ulTaskNotifyTake(pdTRUE, portMAX_DELAY));
}
}
/***************************************************************************************************
* @section Leds
**************************************************************************************************/
static void led1_task(void * pvParameter)
{
UNUSED_PARAMETER(pvParameter);
while (1)
{
LEDS_INVERT(BSP_LED_2_MASK);
vTaskDelay(LED1_BLINK_INTERVAL);
}
}
static void led2_task(void * pvParameter)
{
UNUSED_PARAMETER(pvParameter);
while (1)
{
LEDS_INVERT(BSP_LED_3_MASK);
vTaskDelay(LED2_BLINK_INTERVAL);
}
}
#if NRF_LOG_ENABLED
static void logger_thread(void * pvParameter)
{
UNUSED_PARAMETER(pvParameter);
while (true)
{
if (!(NRF_LOG_PROCESS()))
{
/* No more logs, let's sleep and wait for any */
//thread_coap_utils_multicast_light_request_send2(0, 1);
vTaskDelay(LOG_TASK_INTERVAL);
}
}
}
#endif //NRF_LOG_ENABLED
/***************************************************************************************************
* @section Main
**************************************************************************************************/
#include <openthread/message.h>
#include <openthread/udp.h>
#include <openthread/ip6.h>
#include <openthread/link.h>
typedef struct BACnet_IP6_Address {
uint8_t address[16];
uint16_t port;
} BACNET_IP6_ADDRESS;
/*UDP*/
static uint8_t Ttest_data[384];
/* Set Extended Pan ID to DEAD00BEEF00CAFE */
static const uint8_t thread_extPanId[OT_EXT_PAN_ID_SIZE] = {0xDE, 0xAD, 0x00, 0xBE, 0xEF, 0x00, 0xCA, 0xFE};//dafult
/* Set network key to 00112233445566778899aabbccddeeff */
static const uint8_t thread_network_key[OT_MASTER_KEY_SIZE] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
/*broadcast addr */
static const char UDP_DEST_ADDR[] = "ff03::1";
static otUdpSocket sUdpSocket;
static otMessage * ot_message;
const otMessageInfo *OTMessageInfo = NULL;
static uint8_t udp_buf[384];
static uint16_t ot_message_len = 16;
void handleUdpReceive(void *aContext, otMessage *aMessage,
const otMessageInfo *aMessageInfo)
{
OT_UNUSED_VARIABLE(aContext);
OT_UNUSED_VARIABLE(aMessage);
OT_UNUSED_VARIABLE(aMessageInfo);
OTMessageInfo = aMessageInfo;
ot_message_len = otMessageGetLength(aMessage);
otMessageRead(aMessage, 0, udp_buf, ot_message_len);
nrf_gpio_pin_toggle(LED_1);
}
otError udp_error = OT_ERROR_GENERIC;
void initUdp(otInstance *aInstance)
{
otSockAddr listenSockAddr;
otError error = OT_ERROR_NONE;
memset(&sUdpSocket, 0, sizeof(sUdpSocket));
memset(&listenSockAddr, 0, sizeof(listenSockAddr));
listenSockAddr.mPort = 0x1234;
udp_error = otUdpOpen(aInstance, &sUdpSocket, handleUdpReceive, aInstance);
udp_error = otUdpBind(&sUdpSocket, &listenSockAddr);
}
void ot_udp_init(void)
{
otInstance * aInstance = thread_ot_instance_get();
initUdp(aInstance);
}
otError setNetworkConfiguration(void)
{
static char aNetworkName[16] = {0};
otOperationalDataset aDataset;
const otExtAddress *ot_Extaddr;
otInstance * aInstance = thread_ot_instance_get();
memset(&aDataset, 0, sizeof(otOperationalDataset));
memset(aNetworkName, 0x00, sizeof(aNetworkName));
ot_Extaddr = otLinkGetExtendedAddress(aInstance);
/*
* Fields that can be configured in otOperationDataset to override defaults:
* Network Name, Mesh Local Prefix, Extended PAN ID, PAN ID, Delay Timer,
* Channel, Channel Mask Page 0, Network Key, PSKc, Security Policy
*/
aDataset.mActiveTimestamp = 1;
aDataset.mComponents.mIsActiveTimestampPresent = true;
/* Set Channel to 15 */
aDataset.mChannel = 11;
aDataset.mComponents.mIsChannelPresent = true;
/* Set Pan ID to 2222 */
aDataset.mPanId = (otPanId)0xabcc;
aDataset.mComponents.mIsPanIdPresent = true;
/* Set Extended Pan ID to C0DE1AB5C0DE1AB5 */
memcpy(aDataset.mExtendedPanId.m8, thread_extPanId, sizeof(aDataset.mExtendedPanId));
aDataset.mComponents.mIsExtendedPanIdPresent = true;
/* Set network key to 1234C0DE1AB51234C0DE1AB51234C0DE */
memcpy(aDataset.mMasterKey.m8, thread_network_key, sizeof(aDataset.mMasterKey));
aDataset.mComponents.mIsMasterKeyPresent = true;
/* Set Network Name to OTCodelab */
//size_t length = strlen(aNetworkName);
size_t length = sprintf(aNetworkName, "%s-%02x%02x", "WNGTTEST", ot_Extaddr->m8[6], ot_Extaddr->m8[7]);
ASSERT(length <= OT_NETWORK_NAME_MAX_SIZE);
memcpy(aDataset.mNetworkName.m8, aNetworkName, length);
aDataset.mComponents.mIsNetworkNamePresent = true;
/* Set the router selection jitter to override the 2 minute default.
CLI cmd > routerselectionjitter 20
Warning: For demo purposes only - not to be used in a real product */
// uint8_t jitterValue = 100;
// otThreadSetRouterSelectionJitter(aInstance, jitterValue);
return otDatasetSetActive(aInstance, &aDataset);
}
int bip6_send_mpdu(BACNET_IP6_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len)
{
static uint32_t otFreeCount = 0;
otError error = OT_ERROR_NONE;
otMessageInfo messageInfo;
otInstance * aInstance = thread_ot_instance_get();
otMessage * ot_message = NULL;
otBufferInfo mesInfo;
otMessageGetBufferInfo(aInstance, &mesInfo);
otMessageSettings aSentting = {.mLinkSecurityEnabled = false, .mPriority = OT_MESSAGE_PRIORITY_HIGH};
memset(&messageInfo, 0, sizeof(messageInfo));
memcpy(&messageInfo.mPeerAddr.mFields.m8[0], &dest->address[0], 16);
messageInfo.mPeerPort = dest->port;
/* send the packet */
do {
ot_message = otUdpNewMessage(aInstance, NULL);
if (ot_message == NULL) {
break;
}
error = otMessageAppend(ot_message, mtu, mtu_len);
if (error != OT_ERROR_NONE) {
break;
}
CRITICAL_REGION_ENTER();
error = otUdpSend(&sUdpSocket, ot_message, &messageInfo);
CRITICAL_REGION_EXIT();
} while(0);
if (error != OT_ERROR_NONE && ot_message != NULL)
{
NRF_LOG_INFO("**OT Free:%d\n", ++otFreeCount);
otMessageFree(ot_message);
return 0;
} else {
NRF_LOG_INFO("**OT Send:%d err:%d %x\n", ++otFreeCount, error, ot_message);
}
if (error != OT_ERROR_NONE) {
return 0;
}
return mtu_len;
}
void thread_send_test(void)
{
static uint32_t cnt = 0;
uint8_t len = 0;
otIp6Address broadcastAddr;
BACNET_IP6_ADDRESS dest = {{0}};
len = sprintf(Ttest_data, "Tsend cnt:%d\n", ++cnt);
memset(&broadcastAddr, 0x00, sizeof(broadcastAddr));
otIp6AddressFromString("FF03::1", &broadcastAddr);
dest.port = 0x1234;
memcpy(&dest.address[0], &broadcastAddr.mFields.m8[0], sizeof(broadcastAddr));
bip6_send_mpdu(&dest, Ttest_data, len);
//DEBUG_PRINTF("Tsend cnt:%d\n", cnt);
}
static void ot_app(void * pvParameter)
{
UNUSED_PARAMETER(pvParameter);
static bool flag = true;
while (1)
{
thread_send_test();
vTaskDelay(50);
}
}
int main(void)
{
log_init();
clock_init();
timer_init();
thread_instance_init();
//thread_coap_init();
thread_bsp_init();
//thread_coap_utils_light_command_handler_set(on_light_change);
ot_udp_init();
NRF_LOG_INFO("APP\n");
// Start thread stack execution.
if (pdPASS != xTaskCreate(thread_stack_task, "THR", THREAD_STACK_TASK_STACK_SIZE, NULL, THREAD_STACK_TASK_PRIORITY, &m_app.thread_stack_task))
{
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
// Start execution.
//if (pdPASS != xTaskCreate(led1_task, "LED1", configMINIMAL_STACK_SIZE, NULL, LED1_TASK_PRIORITY, &m_app.led1_task))
//{
// APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
//}
//// Start execution.
//if (pdPASS != xTaskCreate(led2_task, "LED2", configMINIMAL_STACK_SIZE, NULL, LED2_TASK_PRIORITY, &m_app.led2_task))
//{
// APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
//}
#if NRF_LOG_ENABLED
// Start execution.
if (pdPASS != xTaskCreate(logger_thread, "LOGGER", LOG_TASK_STACK_SIZE, NULL, LOG_TASK_PRIORITY, &m_app.logger_task))
{
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
#endif
// Start execution.
if (pdPASS != xTaskCreate(ot_app, "OTAPP", THREAD_STACK_TASK_STACK_SIZE, NULL, LED2_TASK_PRIORITY, &m_app.led2_task))
{
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
/* Start FreeRTOS scheduler. */
vTaskStartScheduler();
while (true)
{
/* FreeRTOS should not be here... FreeRTOS goes back to the start of stack
* in vTaskStartScheduler function. */
}
}
void HardFault_Handler(void)
{
//xTaskStackShowCurrentTask();
NVIC_SystemReset();
while(1);
}
/**
*@}
**/

