Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAN: Initialisation Timeout #47

Merged
merged 5 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/thingset/can.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ struct thingset_can
#ifdef CONFIG_THINGSET_CAN_CONTROL_REPORTING
int64_t next_control_report_time;
#endif
struct k_timer timeout_timer;
uint8_t node_addr;
/** bus or bridge number */
uint8_t route;
Expand Down Expand Up @@ -358,11 +359,12 @@ int thingset_can_set_item_rx_callback_inst(struct thingset_can *ts_can,
* @param ts_can Pointer to the thingset_can context.
* @param can_dev Pointer to the CAN device that should be used.
* @param bus_number Assigned bus number of this CAN device (ignored if bridge routing is used)
* @param timeout Initialisation timeout. Set to K_FOREVER for no timeout.
*
* @returns 0 for success or negative errno in case of error
*/
int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can_dev,
uint8_t bus_number);
uint8_t bus_number, k_timeout_t timeout);

#else /* !CONFIG_THINGSET_CAN_MULTIPLE_INSTANCES */

Expand Down
57 changes: 46 additions & 11 deletions src/can.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ LOG_MODULE_REGISTER(thingset_can, CONFIG_THINGSET_SDK_LOG_LEVEL);

extern uint8_t eui64[8];

#define EVENT_ADDRESS_CLAIM_MSG_SENT 0x01
#define EVENT_ADDRESS_CLAIMING_FINISHED 0x02
#define EVENT_ADDRESS_ALREADY_USED 0x03
#define EVENT_ADDRESS_CLAIM_MSG_SENT BIT(1)
#define EVENT_ADDRESS_CLAIMING_FINISHED BIT(2)
#define EVENT_ADDRESS_ALREADY_USED BIT(3)
#define EVENT_ADDRESS_CLAIM_TIMED_OUT BIT(4)

#ifdef CONFIG_THINGSET_CAN_ITEM_RX
static const struct can_filter sf_report_filter = {
Expand Down Expand Up @@ -120,6 +121,13 @@ static void thingset_can_addr_claim_tx_cb(const struct device *dev, int error, v
}
}

static void thingset_can_addr_discovery_tx_cb(const struct device *dev, int error, void *user_data)
{
if (error != 0) {
LOG_ERR("Address discovery failed with %d", error);
}
}

static void thingset_can_addr_claim_tx_handler(struct k_work *work)
{
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
Expand Down Expand Up @@ -565,8 +573,14 @@ static void thingset_can_reqresp_sent_callback(int result, void *arg)
}
}

static void thingset_can_timeout_timer_expired(struct k_timer *timer)
{
struct thingset_can *ts_can = CONTAINER_OF(timer, struct thingset_can, timeout_timer);
k_event_set(&ts_can->events, EVENT_ADDRESS_CLAIM_TIMED_OUT);
}

int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can_dev,
uint8_t bus_number)
uint8_t bus_number, k_timeout_t timeout)
{
struct can_frame tx_frame = {
.flags = CAN_FRAME_IDE,
Expand All @@ -586,6 +600,7 @@ int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can
#endif
k_sem_init(&ts_can->request_response.sem, 1, 1);
k_sem_init(&ts_can->report_tx_sem, 0, 1);
k_timer_init(&ts_can->timeout_timer, thingset_can_timeout_timer_expired, NULL);

#ifdef CONFIG_THINGSET_SUBSET_LIVE_METRICS
k_work_init_delayable(&ts_can->live_reporting_work, thingset_can_live_reporting_handler);
Expand All @@ -604,6 +619,7 @@ int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can
}

k_event_init(&ts_can->events);
k_timer_start(&ts_can->timeout_timer, timeout, K_NO_WAIT);

#ifdef CONFIG_CAN_FD_MODE
can_mode_t supported_modes;
Expand Down Expand Up @@ -646,42 +662,59 @@ int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can
can_add_rx_filter(ts_can->dev, thingset_can_addr_claim_rx_cb, ts_can, &addr_claim_filter);
if (filter_id < 0) {
LOG_ERR("Unable to add addr_claim filter: %d", filter_id);
k_timer_stop(&ts_can->timeout_timer);
return filter_id;
}

while (1) {
k_event_clear(&ts_can->events, EVENT_ADDRESS_ALREADY_USED);
k_event_clear(&ts_can->events, EVENT_ADDRESS_CLAIM_MSG_SENT
| EVENT_ADDRESS_CLAIMING_FINISHED
| EVENT_ADDRESS_ALREADY_USED);

/* send out address discovery frame */
uint8_t rand = sys_rand32_get() & 0xFF;
tx_frame.id = THINGSET_CAN_PRIO_NETWORK_MGMT | THINGSET_CAN_TYPE_NETWORK
| THINGSET_CAN_RAND_SET(rand) | THINGSET_CAN_TARGET_SET(ts_can->node_addr)
| THINGSET_CAN_SOURCE_SET(THINGSET_CAN_ADDR_ANONYMOUS);
tx_frame.dlc = 0;
err = can_send(ts_can->dev, &tx_frame, K_MSEC(10), NULL, NULL);
err =
can_send(ts_can->dev, &tx_frame, K_MSEC(10), thingset_can_addr_discovery_tx_cb, ts_can);
if (err != 0) {
k_sleep(K_MSEC(100));
continue;
}

/* wait 500 ms for address claim message from other node */
uint32_t event =
k_event_wait(&ts_can->events, EVENT_ADDRESS_ALREADY_USED, false, K_MSEC(500));
uint32_t event = k_event_wait(&ts_can->events,
EVENT_ADDRESS_ALREADY_USED | EVENT_ADDRESS_CLAIM_TIMED_OUT,
false, K_MSEC(500));
if (event & EVENT_ADDRESS_ALREADY_USED) {
/* try again with new random node_addr between 0x01 and 0xFD */
ts_can->node_addr =
THINGSET_CAN_ADDR_MIN
+ sys_rand32_get() % (THINGSET_CAN_ADDR_MAX - THINGSET_CAN_ADDR_MIN);
LOG_WRN("Node addr already in use, trying 0x%.2X", ts_can->node_addr);
}
else if (event & EVENT_ADDRESS_CLAIM_TIMED_OUT) {
LOG_ERR("Address claim timed out");
k_timer_stop(&ts_can->timeout_timer);
return -ETIMEDOUT;
}
else {
struct can_bus_err_cnt err_cnt_before;
can_get_state(ts_can->dev, NULL, &err_cnt_before);

thingset_sdk_reschedule_work(&ts_can->addr_claim_work, K_NO_WAIT);

event = k_event_wait(&ts_can->events, EVENT_ADDRESS_CLAIM_MSG_SENT, false, K_MSEC(100));
if (!(event & EVENT_ADDRESS_CLAIM_MSG_SENT)) {
event = k_event_wait(&ts_can->events,
EVENT_ADDRESS_CLAIM_MSG_SENT | EVENT_ADDRESS_CLAIM_TIMED_OUT,
false, K_MSEC(100));
if (event & EVENT_ADDRESS_CLAIM_TIMED_OUT) {
LOG_ERR("Address claim timed out");
k_timer_stop(&ts_can->timeout_timer);
return -ETIMEDOUT;
}
else if (!(event & EVENT_ADDRESS_CLAIM_MSG_SENT)) {
k_sleep(K_MSEC(100));
continue;
}
Expand All @@ -692,6 +725,7 @@ int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can
if (err_cnt_after.tx_err_cnt <= err_cnt_before.tx_err_cnt) {
/* address claiming is finished */
k_event_post(&ts_can->events, EVENT_ADDRESS_CLAIMING_FINISHED);
k_timer_stop(&ts_can->timeout_timer);
LOG_INF("Using CAN node address 0x%.2X on %s", ts_can->node_addr,
ts_can->dev->name);
break;
Expand Down Expand Up @@ -851,7 +885,8 @@ static void thingset_can_thread()
int err;

LOG_DBG("Initialising ThingSet CAN");
err = thingset_can_init_inst(&ts_can_single, can_dev, CONFIG_THINGSET_CAN_DEFAULT_ROUTE);
err = thingset_can_init_inst(&ts_can_single, can_dev, CONFIG_THINGSET_CAN_DEFAULT_ROUTE,
K_FOREVER);
if (err != 0) {
LOG_ERR("Failed to init ThingSet CAN: %d", err);
return;
Expand Down
Loading