Skip to content

Commit

Permalink
CAN: init timeout; fix events
Browse files Browse the repository at this point in the history
CAN: correct callback

CAN: move timer to context
  • Loading branch information
garethpotter committed Aug 14, 2024
1 parent da089bd commit 9623764
Show file tree
Hide file tree
Showing 2 changed files with 44 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
52 changes: 41 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 @@ -565,8 +566,19 @@ 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);
}

static void thingset_can_timeout_timer_stopped(struct k_timer *timer)
{
ARG_UNUSED(timer);
}

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 +598,8 @@ 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,
thingset_can_timeout_timer_stopped);

#ifdef CONFIG_THINGSET_SUBSET_LIVE_METRICS
k_work_init_delayable(&ts_can->live_reporting_work, thingset_can_live_reporting_handler);
Expand All @@ -604,6 +618,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 @@ -650,38 +665,51 @@ int thingset_can_init_inst(struct thingset_can *ts_can, const struct device *can
}

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_claim_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");
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");
return -ETIMEDOUT;
}
else if (!(event & EVENT_ADDRESS_CLAIM_MSG_SENT)) {
k_sleep(K_MSEC(100));
continue;
}
Expand All @@ -692,6 +720,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 +880,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 9623764

Please sign in to comment.