Skip to content

Commit

Permalink
CAN: Initialisation Timeout (#47)
Browse files Browse the repository at this point in the history
* CAN: init timeout; fix events

CAN: correct callback

CAN: move timer to context

* initial discovery frame should not set claim flag

* unused var

* code review fix

* cleanup
  • Loading branch information
garethpotter authored Sep 19, 2024
1 parent da089bd commit 425cfce
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
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

0 comments on commit 425cfce

Please sign in to comment.