Skip to content

Commit e2078e6

Browse files
committed
Merge branch 'release/v17.6.0'
2 parents e4c0f8b + e437655 commit e2078e6

File tree

10 files changed

+434
-509
lines changed

10 files changed

+434
-509
lines changed
+86-256
Original file line numberDiff line numberDiff line change
@@ -1,309 +1,139 @@
11
/*
2-
* Copyright (c) 2018 Alexander Wachter
2+
* Copyright (c) 2021-2022 Henrik Brix Andersen <[email protected]>
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
#include <stdio.h>
8-
9-
#include <zephyr/kernel.h>
10-
#include <zephyr/sys/printk.h>
117
#include <zephyr/device.h>
8+
#include <zephyr/devicetree.h>
129
#include <zephyr/drivers/can.h>
1310
#include <zephyr/drivers/gpio.h>
14-
#include <zephyr/sys/byteorder.h>
15-
16-
#define RX_THREAD_STACK_SIZE 512
17-
#define RX_THREAD_PRIORITY 2
18-
#define STATE_POLL_THREAD_STACK_SIZE 512
19-
#define STATE_POLL_THREAD_PRIORITY 2
20-
#define LED_MSG_ID 0x10
21-
#define COUNTER_MSG_ID 0x12345
22-
#define SET_LED 1
23-
#define RESET_LED 0
24-
#define SLEEP_TIME K_MSEC(250)
25-
26-
K_THREAD_STACK_DEFINE(rx_thread_stack, RX_THREAD_STACK_SIZE);
27-
K_THREAD_STACK_DEFINE(poll_state_stack, STATE_POLL_THREAD_STACK_SIZE);
28-
29-
const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
30-
struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios, {0});
31-
32-
struct k_thread rx_thread_data;
33-
struct k_thread poll_state_thread_data;
34-
struct k_work_poll change_led_work;
35-
struct k_work state_change_work;
36-
enum can_state current_state;
37-
struct can_bus_err_cnt current_err_cnt;
11+
#include <zephyr/kernel.h>
3812

39-
CAN_MSGQ_DEFINE(change_led_msgq, 2);
40-
CAN_MSGQ_DEFINE(counter_msgq, 2);
13+
/* Devicetree */
14+
#define CANBUS_NODE DT_CHOSEN(zephyr_canbus)
15+
#define BUTTON_NODE DT_ALIAS(sw0)
16+
#define BUTTON_NAME DT_PROP_OR(BUTTON_NODE, label, "sw0")
4117

42-
static struct k_poll_event change_led_events[1] = {
43-
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
44-
K_POLL_MODE_NOTIFY_ONLY,
45-
&change_led_msgq, 0)
18+
#if DT_NODE_EXISTS(BUTTON_NODE)
19+
struct button_callback_context {
20+
struct gpio_callback callback;
21+
struct k_sem sem;
4622
};
4723

48-
void tx_irq_callback(const struct device *dev, int error, void *arg)
24+
static void button_callback(const struct device *port, struct gpio_callback *cb,
25+
gpio_port_pins_t pins)
4926
{
50-
char *sender = (char *)arg;
51-
52-
ARG_UNUSED(dev);
27+
struct button_callback_context *ctx =
28+
CONTAINER_OF(cb, struct button_callback_context, callback);
5329

54-
if (error != 0) {
55-
printf("Callback! error-code: %d\nSender: %s\n",
56-
error, sender);
57-
}
30+
k_sem_give(&ctx->sem);
5831
}
32+
#endif /* DT_NODE_EXISTS(BUTTON_NODE) */
5933

60-
void rx_thread(void *arg1, void *arg2, void *arg3)
34+
static void can_tx_callback(const struct device *dev, int error, void *user_data)
6135
{
62-
ARG_UNUSED(arg1);
63-
ARG_UNUSED(arg2);
64-
ARG_UNUSED(arg3);
65-
const struct can_filter filter = {
66-
.flags = CAN_FILTER_IDE,
67-
.id = COUNTER_MSG_ID,
68-
.mask = CAN_EXT_ID_MASK
69-
};
70-
struct can_frame frame;
71-
int filter_id;
72-
73-
filter_id = can_add_rx_filter_msgq(can_dev, &counter_msgq, &filter);
74-
printf("Counter filter id: %d\n", filter_id);
75-
76-
while (1) {
77-
k_msgq_get(&counter_msgq, &frame, K_FOREVER);
78-
79-
if (IS_ENABLED(CONFIG_CAN_ACCEPT_RTR) && (frame.flags & CAN_FRAME_RTR) != 0U) {
80-
continue;
81-
}
82-
83-
if (frame.dlc != 2U) {
84-
printf("Wrong data length: %u\n", frame.dlc);
85-
continue;
86-
}
36+
struct k_sem *tx_queue_sem = user_data;
8737

88-
printf("Counter received: %u\n",
89-
sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)&frame.data)));
90-
}
38+
k_sem_give(tx_queue_sem);
9139
}
9240

93-
void change_led_work_handler(struct k_work *work)
41+
int main(void)
9442
{
95-
struct can_frame frame;
96-
int ret;
97-
98-
while (k_msgq_get(&change_led_msgq, &frame, K_NO_WAIT) == 0) {
99-
if (IS_ENABLED(CONFIG_CAN_ACCEPT_RTR) && (frame.flags & CAN_FRAME_RTR) != 0U) {
100-
continue;
101-
}
43+
#if DT_NODE_EXISTS(BUTTON_NODE)
44+
const struct gpio_dt_spec btn = GPIO_DT_SPEC_GET(BUTTON_NODE, gpios);
45+
struct button_callback_context btn_cb_ctx;
46+
#endif /* DT_NODE_EXISTS(BUTTON_NODE) */
47+
const struct device *dev = DEVICE_DT_GET(CANBUS_NODE);
48+
struct k_sem tx_queue_sem;
49+
struct can_frame frame = {0};
50+
int err;
10251

103-
if (led.port == NULL) {
104-
printf("LED %s\n", frame.data[0] == SET_LED ? "ON" : "OFF");
105-
} else {
106-
gpio_pin_set(led.port, led.pin, frame.data[0] == SET_LED ? 1 : 0);
107-
}
108-
}
52+
k_sem_init(&tx_queue_sem, CONFIG_SAMPLE_CAN_BABBLING_TX_QUEUE_SIZE,
53+
CONFIG_SAMPLE_CAN_BABBLING_TX_QUEUE_SIZE);
10954

110-
ret = k_work_poll_submit(&change_led_work, change_led_events,
111-
ARRAY_SIZE(change_led_events), K_FOREVER);
112-
if (ret != 0) {
113-
printf("Failed to resubmit msgq polling: %d", ret);
114-
}
115-
}
116-
117-
char *state_to_str(enum can_state state)
118-
{
119-
switch (state) {
120-
case CAN_STATE_ERROR_ACTIVE:
121-
return "error-active";
122-
case CAN_STATE_ERROR_WARNING:
123-
return "error-warning";
124-
case CAN_STATE_ERROR_PASSIVE:
125-
return "error-passive";
126-
case CAN_STATE_BUS_OFF:
127-
return "bus-off";
128-
case CAN_STATE_STOPPED:
129-
return "stopped";
130-
default:
131-
return "unknown";
55+
if (!device_is_ready(dev)) {
56+
printk("CAN device not ready");
57+
return 0;
13258
}
133-
}
134-
135-
void poll_state_thread(void *unused1, void *unused2, void *unused3)
136-
{
137-
struct can_bus_err_cnt err_cnt = {0, 0};
138-
struct can_bus_err_cnt err_cnt_prev = {0, 0};
139-
enum can_state state_prev = CAN_STATE_ERROR_ACTIVE;
140-
enum can_state state;
141-
int err;
14259

143-
while (1) {
144-
err = can_get_state(can_dev, &state, &err_cnt);
60+
if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_FD_MODE)) {
61+
err = can_set_mode(dev, CAN_MODE_FD);
14562
if (err != 0) {
146-
printf("Failed to get CAN controller state: %d", err);
147-
k_sleep(K_MSEC(100));
148-
continue;
149-
}
150-
151-
if (err_cnt.tx_err_cnt != err_cnt_prev.tx_err_cnt ||
152-
err_cnt.rx_err_cnt != err_cnt_prev.rx_err_cnt ||
153-
state_prev != state) {
154-
155-
err_cnt_prev.tx_err_cnt = err_cnt.tx_err_cnt;
156-
err_cnt_prev.rx_err_cnt = err_cnt.rx_err_cnt;
157-
state_prev = state;
158-
printf("state: %s\n"
159-
"rx error count: %d\n"
160-
"tx error count: %d\n",
161-
state_to_str(state),
162-
err_cnt.rx_err_cnt, err_cnt.tx_err_cnt);
163-
} else {
164-
k_sleep(K_MSEC(100));
63+
printk("Error setting CAN FD mode (err %d)", err);
64+
return 0;
16565
}
16666
}
167-
}
168-
169-
void state_change_work_handler(struct k_work *work)
170-
{
171-
printf("State Change ISR\nstate: %s\n"
172-
"rx error count: %d\n"
173-
"tx error count: %d\n",
174-
state_to_str(current_state),
175-
current_err_cnt.rx_err_cnt, current_err_cnt.tx_err_cnt);
176-
177-
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
178-
if (current_state == CAN_STATE_BUS_OFF) {
179-
printf("Recover from bus-off\n");
18067

181-
if (can_recover(can_dev, K_MSEC(100)) != 0) {
182-
printf("Recovery timed out\n");
183-
}
68+
err = can_start(dev);
69+
if (err != 0) {
70+
printk("Error starting CAN controller (err %d)", err);
71+
return 0;
18472
}
185-
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
186-
}
187-
188-
void state_change_callback(const struct device *dev, enum can_state state,
189-
struct can_bus_err_cnt err_cnt, void *user_data)
190-
{
191-
struct k_work *work = (struct k_work *)user_data;
192-
193-
ARG_UNUSED(dev);
19473

195-
current_state = state;
196-
current_err_cnt = err_cnt;
197-
k_work_submit(work);
198-
}
74+
#if DT_NODE_EXISTS(BUTTON_NODE)
75+
k_sem_init(&btn_cb_ctx.sem, 0, 1);
19976

200-
int main(void)
201-
{
202-
const struct can_filter change_led_filter = {
203-
.flags = 0U,
204-
.id = LED_MSG_ID,
205-
.mask = CAN_STD_ID_MASK
206-
};
207-
struct can_frame change_led_frame = {
208-
.flags = 0,
209-
.id = LED_MSG_ID,
210-
.dlc = 1
211-
};
212-
struct can_frame counter_frame = {
213-
.flags = CAN_FRAME_IDE,
214-
.id = COUNTER_MSG_ID,
215-
.dlc = 2
216-
};
217-
uint8_t toggle = 1;
218-
uint16_t counter = 0;
219-
k_tid_t rx_tid, get_state_tid;
220-
int ret;
221-
222-
if (!device_is_ready(can_dev)) {
223-
printf("CAN: Device %s not ready.\n", can_dev->name);
77+
if (!gpio_is_ready_dt(&btn)) {
78+
printk("button device not ready\n");
22479
return 0;
22580
}
22681

227-
#ifdef CONFIG_LOOPBACK_MODE
228-
ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK);
229-
if (ret != 0) {
230-
printf("Error setting CAN mode [%d]", ret);
231-
return 0;
232-
}
233-
#endif
234-
ret = can_start(can_dev);
235-
if (ret != 0) {
236-
printf("Error starting CAN controller [%d]", ret);
82+
err = gpio_pin_configure_dt(&btn, GPIO_INPUT);
83+
if (err != 0) {
84+
printk("failed to configure button GPIO (err %d)\n", err);
23785
return 0;
23886
}
23987

240-
if (led.port != NULL) {
241-
if (!gpio_is_ready_dt(&led)) {
242-
printf("LED: Device %s not ready.\n",
243-
led.port->name);
244-
return 0;
245-
}
246-
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_HIGH);
247-
if (ret < 0) {
248-
printf("Error setting LED pin to output mode [%d]",
249-
ret);
250-
led.port = NULL;
251-
}
252-
}
253-
254-
k_work_init(&state_change_work, state_change_work_handler);
255-
k_work_poll_init(&change_led_work, change_led_work_handler);
256-
257-
ret = can_add_rx_filter_msgq(can_dev, &change_led_msgq, &change_led_filter);
258-
if (ret == -ENOSPC) {
259-
printf("Error, no filter available!\n");
88+
err = gpio_pin_interrupt_configure_dt(&btn, GPIO_INT_EDGE_TO_ACTIVE);
89+
if (err != 0) {
90+
printk("failed to configure button interrupt (err %d)\n", err);
26091
return 0;
26192
}
26293

263-
printf("Change LED filter ID: %d\n", ret);
94+
gpio_init_callback(&btn_cb_ctx.callback, button_callback, BIT(btn.pin));
95+
gpio_add_callback(btn.port, &btn_cb_ctx.callback);
96+
#endif /* DT_NODE_EXISTS(BUTTON_NODE) */
26497

265-
ret = k_work_poll_submit(&change_led_work, change_led_events,
266-
ARRAY_SIZE(change_led_events), K_FOREVER);
267-
if (ret != 0) {
268-
printf("Failed to submit msgq polling: %d", ret);
269-
return 0;
98+
if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_EXT_ID)) {
99+
frame.flags |= CAN_FRAME_IDE;
270100
}
271101

272-
rx_tid = k_thread_create(&rx_thread_data, rx_thread_stack,
273-
K_THREAD_STACK_SIZEOF(rx_thread_stack),
274-
rx_thread, NULL, NULL, NULL,
275-
RX_THREAD_PRIORITY, 0, K_NO_WAIT);
276-
if (!rx_tid) {
277-
printf("ERROR spawning rx thread\n");
102+
if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_RTR)) {
103+
frame.flags |= CAN_FRAME_RTR;
278104
}
279105

280-
get_state_tid = k_thread_create(&poll_state_thread_data,
281-
poll_state_stack,
282-
K_THREAD_STACK_SIZEOF(poll_state_stack),
283-
poll_state_thread, NULL, NULL, NULL,
284-
STATE_POLL_THREAD_PRIORITY, 0,
285-
K_NO_WAIT);
286-
if (!get_state_tid) {
287-
printf("ERROR spawning poll_state_thread\n");
106+
if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_FD_MODE)) {
107+
frame.flags |= CAN_FRAME_FDF;
288108
}
289109

290-
can_set_state_change_callback(can_dev, state_change_callback, &state_change_work);
110+
frame.id = CONFIG_SAMPLE_CAN_BABBLING_CAN_ID;
291111

292-
printf("Finished init.\n");
112+
printk("babbling on %s with %s (%d-bit) CAN ID 0x%0*x, RTR %d, CAN FD %d\n",
113+
dev->name,
114+
(frame.flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
115+
(frame.flags & CAN_FRAME_IDE) != 0 ? 29 : 11,
116+
(frame.flags & CAN_FRAME_IDE) != 0 ? 8 : 3, frame.id,
117+
(frame.flags & CAN_FRAME_RTR) != 0 ? 1 : 0,
118+
(frame.flags & CAN_FRAME_FDF) != 0 ? 1 : 0);
293119

294-
while (1) {
295-
change_led_frame.data[0] = toggle++ & 0x01 ? SET_LED : RESET_LED;
296-
/* This sending call is none blocking. */
297-
can_send(can_dev, &change_led_frame, K_FOREVER,
298-
tx_irq_callback,
299-
"LED change");
300-
k_sleep(SLEEP_TIME);
120+
#if DT_NODE_EXISTS(BUTTON_NODE)
121+
printk("abort by pressing %s button\n", BUTTON_NAME);
122+
#endif /* DT_NODE_EXISTS(BUTTON_NODE) */
301123

302-
UNALIGNED_PUT(sys_cpu_to_be16(counter),
303-
(uint16_t *)&counter_frame.data[0]);
304-
counter++;
305-
/* This sending call is blocking until the message is sent. */
306-
can_send(can_dev, &counter_frame, K_MSEC(100), NULL, NULL);
307-
k_sleep(SLEEP_TIME);
124+
while (true) {
125+
if (k_sem_take(&tx_queue_sem, K_MSEC(100)) == 0) {
126+
err = can_send(dev, &frame, K_NO_WAIT, can_tx_callback, &tx_queue_sem);
127+
if (err != 0) {
128+
printk("failed to enqueue CAN frame (err %d)\n", err);
129+
}
130+
}
131+
132+
#if DT_NODE_EXISTS(BUTTON_NODE)
133+
if (k_sem_take(&btn_cb_ctx.sem, K_NO_WAIT) == 0) {
134+
printk("button press detected, babbling stopped\n");
135+
return 0;
136+
}
137+
#endif /* DT_NODE_EXISTS(BUTTON_NODE) */
308138
}
309139
}

0 commit comments

Comments
 (0)