This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

node cannot receive message

I use access_model_pulish to send group message by a server, and make other servers listen. the message can go through, but after 5~30 mins, one of the receiver server cannot receive the message any more. message sending are controlled by a timer which send one message out every 100ms. the code is based on the light_switch example from mesh v1.0.0.  I post the code here, if any one knows what's going on and why it stop listening, please help. thanks.

/* Copyright (c) 2010 - 2017, 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.
 */

#include <stdint.h>
#include <string.h>

/* HAL */
#include "nrf.h"
#include "boards.h"
#include "nrf_mesh_sdk.h"
#include "nrf_delay.h"
#include "simple_hal.h"

/* Core */
#include "nrf_mesh.h"
#include "nrf_mesh_events.h"
#include "log.h"

#include "access.h"
#include "access_config.h"
#include "device_state_manager.h"
#include "nrf_mesh_node_config.h"

#include "simple_on_off_server.h"
#include "simple_on_off_common.h"

#include "light_switch_example_common.h"

#include "test_config.h"
#include "uart.h"
#include "test_timer.h"

/*****************************************************************************
 * Definitions
 *****************************************************************************/

#define GROUP_ADDRESS (0xCAFE)

/*****************************************************************************
 * Static data
 *****************************************************************************/

static simple_on_off_server_t m_server;

/* Forward declaration */
static bool get_cb(const simple_on_off_server_t * p_server);
static bool set_cb(const simple_on_off_server_t * p_server, bool value);

static dsm_handle_t m_central_handle;
extern uint8_t dataready;
extern char cmd_buf[128];

typedef struct {
    bool active;
    uint16_t count;
} timer_ctrl_t;
timer_ctrl_t test_ctrl_timer = { .active = false, .count = 0 };

/*****************************************************************************
 * Static utility functions
 *****************************************************************************/
 uint32_t address_set(uint16_t addr) {
    uint32_t status = 0xFF;
    ERROR_CHECK(dsm_address_publish_add(addr, &m_central_handle));
    status = access_model_publish_address_set(m_server.model_handle, m_central_handle);
    return status;
 }

static void configuration_setup(void * p_unused)
{
    m_server.get_cb = get_cb;
    m_server.set_cb = set_cb;
    ERROR_CHECK(simple_on_off_server_init(&m_server, 0));
    ERROR_CHECK(access_model_subscription_list_alloc(m_server.model_handle));
}

static void provisioning_complete(void * p_unused)
{
    uart_writef(DEBUG_PRINT, "Successfully provisioned\r\n");
    nrf_gpio_pin_set(RGB_LED_RED);
}

/*****************************************************************************
 * Simple OnOff Callbacks
 *****************************************************************************/

static bool get_cb(const simple_on_off_server_t * p_server)
{
    return true;
}

static bool set_cb(const simple_on_off_server_t * p_server, bool value)
{
    nrf_gpio_pin_toggle(RGB_LED_GREEN);
    return value;
}

uint8_t test_message = 0;
void half_ms_tasks(void) {
    access_message_tx_t msg;
    static uint16_t count = 0;

    if (count % 2 == 0) {
        if (test_ctrl_timer.active == true) {
            test_ctrl_timer.count++;
            if (test_ctrl_timer.count >= 100) {
                test_ctrl_timer.count = 0;
                msg.opcode.opcode = SIMPLE_ON_OFF_OPCODE_SET;
                msg.opcode.company_id = ACCESS_COMPANY_ID_NORDIC;
                msg.p_buffer = &test_message;
                msg.length = sizeof(uint8_t);
                access_model_publish(m_server.model_handle, &msg);
                nrf_gpio_pin_toggle(RGB_LED_RED);
            }
        }
    }

    count++;
    if (count >= 2000) count = 0;
}

void input_handler(void) {
    if (dataready) {
        switch (cmd_buf[0]) {
            case 'S':
                uart_writef(DEBUG_PRINT, "Start sending message\r\n");
                test_ctrl_timer.active = true;
                test_ctrl_timer.count = 0;
                address_set(GROUP_ADDRESS);
                break;
            default:
                break;
        }
    }
}

int main(void)
{
    static const uint8_t static_auth_data[NRF_MESH_KEY_SIZE] = STATIC_AUTH_DATA;
    static nrf_mesh_node_config_params_t config_params =
        {.prov_caps = NRF_MESH_PROV_OOB_CAPS_DEFAULT(ACCESS_ELEMENT_COUNT)};
    config_params.p_static_data = static_auth_data;
    config_params.complete_callback = provisioning_complete;
    config_params.setup_callback = configuration_setup;
    config_params.irq_priority = NRF_MESH_IRQ_PRIORITY_LOWEST;

    /*clock settings for ivani board*/
    config_params.lf_clk_cfg.source        = NRF_CLOCK_LF_SRC_RC;
    config_params.lf_clk_cfg.rc_ctiv       = 16;
    config_params.lf_clk_cfg.rc_temp_ctiv  = 2;
    config_params.lf_clk_cfg.accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM;

    uart_init();
    timer_init(half_ms_tasks);

    nrf_gpio_cfg_output(RGB_LED_RED);
    nrf_gpio_cfg_output(RGB_LED_GREEN);
    nrf_gpio_cfg_output(RGB_LED_BLUE);

    nrf_gpio_pin_clear(RGB_LED_RED);
    nrf_gpio_pin_set(RGB_LED_GREEN);
    nrf_gpio_pin_set(RGB_LED_BLUE);

    ERROR_CHECK(nrf_mesh_node_config(&config_params));

    while (true) {
        input_handler();
        flush_uart_buffer();
    }
}

Parents
  • Hi,

    I suspect that the issue might be that you are calling the mesh from different IRQ levels. I suggest you to take a look at this to start with. On line 179 in your code, you set the mesh IRQ priority to LOWEST, you have to keep the code consistent and see to that all of the code are on the same level. You have two functions that is being called in your main-loop that ends up calling the mesh, which is something that breaks this. You also have to check that your timer-callback comes back in LOWEST.

Reply
  • Hi,

    I suspect that the issue might be that you are calling the mesh from different IRQ levels. I suggest you to take a look at this to start with. On line 179 in your code, you set the mesh IRQ priority to LOWEST, you have to keep the code consistent and see to that all of the code are on the same level. You have two functions that is being called in your main-loop that ends up calling the mesh, which is something that breaks this. You also have to check that your timer-callback comes back in LOWEST.

Children
Related