From f19dd97517bf2c4aba19f01cc2655ab0db6fbe8d Mon Sep 17 00:00:00 2001 From: Alexander Wachter Date: Wed, 7 Aug 2019 13:32:04 +0200 Subject: [PATCH] samples: drivers: CAN: reworked sample code The CAN sample is rewritten to be board independent. The CAN controller and LED is determined automatically and the button is removed. Signed-off-by: Alexander Wachter --- samples/drivers/CAN/Kconfig | 31 --- samples/drivers/CAN/README.rst | 30 +-- samples/drivers/CAN/boards/frdm_k64f.conf | 11 - samples/drivers/CAN/boards/twr_ke18f.conf | 11 - samples/drivers/CAN/prj.conf | 1 - samples/drivers/CAN/prj.conf.mcp2515 | 13 - samples/drivers/CAN/src/main.c | 309 ++++++++-------------- 7 files changed, 120 insertions(+), 286 deletions(-) delete mode 100644 samples/drivers/CAN/boards/frdm_k64f.conf delete mode 100644 samples/drivers/CAN/boards/twr_ke18f.conf delete mode 100644 samples/drivers/CAN/prj.conf.mcp2515 diff --git a/samples/drivers/CAN/Kconfig b/samples/drivers/CAN/Kconfig index f67ffa99447..922145b2213 100644 --- a/samples/drivers/CAN/Kconfig +++ b/samples/drivers/CAN/Kconfig @@ -8,36 +8,6 @@ mainmenu "Controller Area Network sample application" -config CAN_DEV - string "Name of the CAN device" - default "CAN_1" - help - Name of the can device used for send an receive. - -config GPIO_LED_DEV - string "Name of the LED GPIO port" - default "GPIOC" - help - Name of the LED port for signaling message reception. - -config GPIO_BUTTON_DEV - string "Name of the button GPIO port" - default "GPIOA" - help - Name of the button port for triggering messages. - -config PIN_USER_BUTTON - int "Pin User Button" - default 0 - help - Pin number of the user Button. - -config PIN_LED_1 - int "Pin LED 1" - default 6 - help - Pin number of the first LED. - config LOOPBACK_MODE bool "Loopback LOOPBACK_MODE" default y @@ -45,5 +15,4 @@ config LOOPBACK_MODE Set the controller to loopback mode. This allows testing without a second board. - source "Kconfig.zephyr" diff --git a/samples/drivers/CAN/README.rst b/samples/drivers/CAN/README.rst index 641d9fcf182..481760179af 100644 --- a/samples/drivers/CAN/README.rst +++ b/samples/drivers/CAN/README.rst @@ -7,10 +7,9 @@ Overview ******** This sample demonstrates how to use the Controller Area Network (CAN) API. -Messages with standard and extended identifiers are sent over the bus, triggered -by a button event. -Messages are received using message queues and ISRs. -Reception is indicated by blink LEDs and output to the console. +Messages with standard and extended identifiers are sent over the bus. +Messages are received using message-queues and work-queues. +Reception is indicated by blinking the LED (if present) and output to the console. Building and Running ******************** @@ -19,25 +18,20 @@ In loopback mode, the board receives its own messages. This could be used for standalone testing. The sample can be built and executed on boards supporting CAN. -The output ports and pins of the LEDs can be configured by Kconfig. +The LED output pin is defined in the board's device tre. Sample output ============= .. code-block:: console - Finished init. waiting for Interrupts - TX thread is running. - filter id: 1 - Button pressed! Send message 1 - Button pressed 1 times - Button pressed! Send message 0 - Button pressed 2 times - String sent over CAN - Button pressed! Send message 1 - Button pressed 3 times - Button pressed! Send message 0 - Button pressed 4 times - String sent over CAN + Change LED filter ID: 0 + Finished init. + Counter filter id: 4 + + uart:~$ Counter received: 0 + Counter received: 1 + Counter received: 2 + Counter received: 3 .. note:: The values shown above might differ. diff --git a/samples/drivers/CAN/boards/frdm_k64f.conf b/samples/drivers/CAN/boards/frdm_k64f.conf deleted file mode 100644 index c8d22670bf1..00000000000 --- a/samples/drivers/CAN/boards/frdm_k64f.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_CAN_DEV="CAN_0" -CONFIG_GPIO_LED_DEV="GPIO_4" -CONFIG_GPIO_BUTTON_DEV="GPIO_2" -CONFIG_PIN_USER_BUTTON=6 -CONFIG_PIN_LED_1=26 - -CONFIG_LOG=y -CONFIG_LOG_BUFFER_SIZE=2048 - -CONFIG_CAN_0=y -CONFIG_CAN_1=n diff --git a/samples/drivers/CAN/boards/twr_ke18f.conf b/samples/drivers/CAN/boards/twr_ke18f.conf deleted file mode 100644 index 66fe4e86237..00000000000 --- a/samples/drivers/CAN/boards/twr_ke18f.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_CAN_DEV="CAN_0" -CONFIG_GPIO_LED_DEV="GPIO_2" -CONFIG_GPIO_BUTTON_DEV="GPIO_3" -CONFIG_PIN_USER_BUTTON=3 -CONFIG_PIN_LED_1=13 - -CONFIG_LOG=y -CONFIG_LOG_BUFFER_SIZE=2048 - -CONFIG_CAN_0=y -CONFIG_CAN_1=n diff --git a/samples/drivers/CAN/prj.conf b/samples/drivers/CAN/prj.conf index 181f177f5ed..448dfc2c010 100644 --- a/samples/drivers/CAN/prj.conf +++ b/samples/drivers/CAN/prj.conf @@ -1,6 +1,5 @@ CONFIG_CAN=y CONFIG_CAN_INIT_PRIORITY=80 -CONFIG_CAN_1=y CONFIG_CAN_MAX_FILTER=5 CONFIG_SHELL=y diff --git a/samples/drivers/CAN/prj.conf.mcp2515 b/samples/drivers/CAN/prj.conf.mcp2515 deleted file mode 100644 index 1305831c893..00000000000 --- a/samples/drivers/CAN/prj.conf.mcp2515 +++ /dev/null @@ -1,13 +0,0 @@ -# CAN + MCP2515 config -CONFIG_SPI=y -CONFIG_CAN=y -CONFIG_CAN_INIT_PRIORITY=80 -CONFIG_CAN_1=y -CONFIG_CAN_STM32=n -CONFIG_CAN_MCP2515=y -CONFIG_GPIO_LED_DEV="GPIOB" -CONFIG_PIN_LED_1=3 -CONFIG_GPIO_BUTTON_DEV="GPIOB" -CONFIG_PIN_USER_BUTTON=4 -CONFIG_LOG=y -CONFIG_CAN_LOG_LEVEL=4 \ No newline at end of file diff --git a/samples/drivers/CAN/src/main.c b/samples/drivers/CAN/src/main.c index 956d4bcf162..ab3efb15b2b 100644 --- a/samples/drivers/CAN/src/main.c +++ b/samples/drivers/CAN/src/main.c @@ -10,195 +10,124 @@ #include #include #include +#include -#define TX_THREAD_STACK_SIZE 512 -#define LED_THREAD_STACK_SIZE 512 -#define RX_STR_THREAD_STACK_SIZE 512 -#define TX_THREAD_PRIORITY 2 -#define LED_MSG_ID (0x10) -#define BUTTON_MSG_ID (0x01) -#define STR_MSG_ID (0x12345) +#define RX_THREAD_STACK_SIZE 512 +#define RX_THREAD_PRIORITY 2 +#define LED_MSG_ID 0x10 +#define COUNTER_MSG_ID 0x12345 +#define SET_LED 1 +#define RESET_LED 0 +#define SLEEP_TIME K_MSEC(250) -#define SET_LED 0 -#define RESET_LED 1 +K_THREAD_STACK_DEFINE(rx_thread_stack, RX_THREAD_STACK_SIZE); +struct k_thread rx_thread_data; +struct zcan_work rx_work; -#define NUM_LEDS_STR STRINGIFY(NUM_LEDS) - -K_THREAD_STACK_DEFINE(tx_thread_stack, TX_THREAD_STACK_SIZE); -K_THREAD_STACK_DEFINE(led_thread_stack, LED_THREAD_STACK_SIZE); -K_THREAD_STACK_DEFINE(rx_str_thread_stack, RX_STR_THREAD_STACK_SIZE); -struct k_thread tx_thread_data; -struct k_thread led_thread_data; -struct k_thread rx_str_thread_data; -struct k_sem tx_sem; -static struct gpio_callback gpio_cb; -CAN_DEFINE_MSGQ(led_msgq, 2); -CAN_DEFINE_MSGQ(str_msgq, 5); +CAN_DEFINE_MSGQ(counter_msgq, 2); void tx_irq_callback(u32_t error_flags, void *arg) { char *sender = (char *)arg; + if (error_flags) { printk("Callback! error-code: %d\nSender: %s\n", error_flags, sender); } } -void button_callback(struct device *port, - struct gpio_callback *cb, u32_t pins) +void rx_thread(void *can_dev_param, void *arg1, void *arg2) { - k_sem_give(&tx_sem); -} - -void send_string(char *string, struct device *can_dev) -{ - struct zcan_frame msg; - int str_len; - - msg.ext_id = STR_MSG_ID; - msg.id_type = CAN_EXTENDED_IDENTIFIER; - msg.dlc = 0U; - msg.rtr = CAN_DATAFRAME; - - for (str_len = strlen(string); str_len; ) { - msg.dlc = str_len >= 8 ? 8 : str_len; - str_len -= msg.dlc; - memcpy(msg.data, string, msg.dlc); - string += msg.dlc; - can_send(can_dev, &msg, 10, tx_irq_callback, "send_string"); - } -} - -void tx_thread(void *can_dev_param, void *unused2, void *unused3) -{ - u8_t toggle = SET_LED; - u16_t button_press_cnt = 0U; - struct zcan_frame msg; - struct zcan_frame msg_button_cnt; - struct device *can_dev = can_dev_param; - - msg.std_id = LED_MSG_ID; - msg.id_type = CAN_STANDARD_IDENTIFIER; - msg.dlc = 1U; - msg.rtr = CAN_DATAFRAME; - msg.data[0] = 0U; - - msg_button_cnt.std_id = BUTTON_MSG_ID; - msg_button_cnt.id_type = CAN_STANDARD_IDENTIFIER; - msg_button_cnt.dlc = 2U; - msg_button_cnt.rtr = CAN_DATAFRAME; - msg_button_cnt.data[0] = 0U; - msg_button_cnt.data[1] = 0U; - - printk("TX thread is running.\n"); - while (1) { - k_sem_take(&tx_sem, K_FOREVER); - button_press_cnt++; - toggle = (toggle == SET_LED) ? RESET_LED : SET_LED; - printk("Button pressed! Send message %u\n", toggle); - msg.data[0] = toggle; - msg_button_cnt.data[0] = button_press_cnt & 0xFF; - msg_button_cnt.data[1] = (button_press_cnt >> 8) & 0xFF; - can_send(can_dev, &msg, 10, tx_irq_callback, "LED msg"); - can_send(can_dev, &msg_button_cnt, 10, NULL, "Button count"); - if (toggle == SET_LED) { - send_string("String sent over CAN\n", can_dev); - } - } -} - -void rx_str_thread(void *msgq, void *can_dev_param, void *unused) -{ - struct zcan_frame msg; - int filter_id; + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); const struct zcan_filter filter = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, - .ext_id = STR_MSG_ID, + .ext_id = COUNTER_MSG_ID, .rtr_mask = 1, .ext_id_mask = CAN_EXT_ID_MASK }; struct device *can_dev = can_dev_param; + struct zcan_frame msg; + int filter_id; - filter_id = can_attach_msgq(can_dev, msgq, &filter); - printk("filter id: %d\n", filter_id); + filter_id = can_attach_msgq(can_dev, &counter_msgq, &filter); + printk("Counter filter id: %d\n", filter_id); while (1) { - k_msgq_get((struct k_msgq *)msgq, &msg, K_FOREVER); - for (int i = 0; i < msg.dlc; i++) { - printk("%c", msg.data[i]); + k_msgq_get(&counter_msgq, &msg, K_FOREVER); + + if (msg.dlc != 2U) { + printk("Wrong data length: %u\n", msg.dlc); + continue; } + + printk("Counter received: %u\n", + sys_be16_to_cpu(UNALIGNED_GET((u16_t *)&msg.data))); } } -void led_thread(void *msgq, void *can_dev_param, void *gpio_dev_param) +void change_led(struct zcan_frame *msg, void *led_dev_param) { - const struct zcan_filter filter = { + struct device *led_dev = (struct device *)led_dev_param; + +#if defined(DT_ALIAS_LED0_GPIOS_PIN) && defined(DT_ALIAS_LED0_GPIOS_CONTROLLER) + + if (!led_dev_param) { + printk("No LED GPIO device\n"); + return; + } + + switch (msg->data[0]) { + case SET_LED: + gpio_pin_write(led_dev, DT_ALIAS_LED0_GPIOS_PIN, 1); + break; + case RESET_LED: + gpio_pin_write(led_dev, DT_ALIAS_LED0_GPIOS_PIN, 0); + break; + } +#else + printk("LED %s\n", msg->data[0] == SET_LED ? "ON" : "OFF"); +#endif +} + +void main(void) +{ + const struct zcan_filter change_led_filter = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, .std_id = LED_MSG_ID, .rtr_mask = 1, .std_id_mask = CAN_STD_ID_MASK }; - struct device *can_dev = can_dev_param; - struct device *gpio_dev = gpio_dev_param; - struct zcan_frame msg; - int ret; - int filter_id; - - ret = gpio_pin_configure(gpio_dev, CONFIG_PIN_LED_1, GPIO_DIR_OUT); - gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 0); - - if (ret) { - printk("ERROR configure pins\n"); - return; - } - - filter_id = can_attach_msgq(can_dev, msgq, &filter); - printk("filter id: %d\n", filter_id); - - while (1) { - k_msgq_get((struct k_msgq *)msgq, &msg, K_FOREVER); - - if (msg.dlc != 1U) { - continue; - } - - switch (msg.data[0]) { - case SET_LED: - gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 1); - - break; - case RESET_LED: - gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 0); - break; - } - } -} - -void rx_button_isr(struct zcan_frame *msg, void *arg) -{ - u16_t cnt = msg->data[0] | (msg->data[1] << 8); - - ARG_UNUSED(arg); - - printk("Button pressed %d times\n", cnt); -} - -void main(void) -{ - const struct zcan_filter filter = { + struct zcan_frame change_led_frame = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, - .std_id = BUTTON_MSG_ID, - .rtr_mask = 1, - .std_id_mask = CAN_STD_ID_MASK + .std_id = LED_MSG_ID, + .dlc = 1 }; - struct device *can_dev, *led_gpio_dev, *button_gpio_dev; + struct zcan_frame counter_frame = { + .id_type = CAN_EXTENDED_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .ext_id = COUNTER_MSG_ID, + .dlc = 2 + }; + u8_t toggle = 1; + u16_t counter = 0; + struct device *led_gpio_dev = NULL; + struct device *can_dev; + k_tid_t rx_tid; int ret; - can_dev = device_get_binding(CONFIG_CAN_DEV); + /* Usually the CAN device is either called CAN_0 or CAN_1, depending + * on the SOC. Let's check both and take the first valid one. + */ + can_dev = device_get_binding("CAN_0"); + if (!can_dev) { + can_dev = device_get_binding("CAN_1"); + } + if (!can_dev) { printk("CAN: Device driver not found.\n"); return; @@ -208,73 +137,51 @@ void main(void) can_configure(can_dev, CAN_LOOPBACK_MODE, 250000); #endif - led_gpio_dev = device_get_binding(CONFIG_GPIO_LED_DEV); +#if defined(DT_ALIAS_LED0_GPIOS_PIN) && defined(DT_ALIAS_LED0_GPIOS_CONTROLLER) + led_gpio_dev = device_get_binding(DT_ALIAS_LED0_GPIOS_CONTROLLER); if (!led_gpio_dev) { printk("LED: Device driver not found.\n"); return; } - k_sem_init(&tx_sem, 0, INT_MAX); - - button_gpio_dev = device_get_binding(CONFIG_GPIO_BUTTON_DEV); - if (!button_gpio_dev) { - printk("Button: Device driver not found.\n"); - return; + ret = gpio_pin_configure(led_gpio_dev, DT_ALIAS_LED0_GPIOS_PIN, + GPIO_DIR_OUT); + if (ret < 0) { + printk("Error setting LED pin to output mode [%d]", ret); } +#endif - ret = gpio_pin_configure(button_gpio_dev, CONFIG_PIN_USER_BUTTON, - (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | - GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE)); - if (ret) { - printk("Error configuring button pin\n"); - } - - gpio_init_callback(&gpio_cb, button_callback, - BIT(CONFIG_PIN_USER_BUTTON)); - - ret = gpio_add_callback(button_gpio_dev, &gpio_cb); - if (ret) { - printk("Cannot setup callback!\n"); - } - - ret = gpio_pin_enable_callback(button_gpio_dev, CONFIG_PIN_USER_BUTTON); - if (ret) { - printk("Error enabling callback!\n"); - } - - ret = can_attach_isr(can_dev, rx_button_isr, 0, &filter); + ret = can_attach_workq(can_dev, &k_sys_work_q, &rx_work, change_led, + led_gpio_dev, &change_led_filter); if (ret == CAN_NO_FREE_FILTER) { printk("Error, no filter available!\n"); return; } - k_tid_t tx_tid = k_thread_create(&tx_thread_data, tx_thread_stack, - K_THREAD_STACK_SIZEOF(tx_thread_stack), - tx_thread, - can_dev, NULL, NULL, - TX_THREAD_PRIORITY, 0, K_NO_WAIT); - if (!tx_tid) { - printk("ERROR spawning tx_thread\n"); + printk("Change LED filter ID: %d\n", ret); + + rx_tid = k_thread_create(&rx_thread_data, rx_thread_stack, + K_THREAD_STACK_SIZEOF(rx_thread_stack), + rx_thread, can_dev, NULL, NULL, + RX_THREAD_PRIORITY, 0, K_NO_WAIT); + if (!rx_tid) { + printk("ERROR spawning rx thread\n"); } - k_tid_t led_tid = k_thread_create(&led_thread_data, led_thread_stack, - K_THREAD_STACK_SIZEOF(led_thread_stack), - led_thread, - &led_msgq, can_dev, led_gpio_dev, - TX_THREAD_PRIORITY, 0, K_NO_WAIT); - if (!led_tid) { - printk("ERROR spawning led_thread\n"); - } + printk("Finished init.\n"); - k_tid_t str_tid = k_thread_create(&rx_str_thread_data, - rx_str_thread_stack, - K_THREAD_STACK_SIZEOF(rx_str_thread_stack), - rx_str_thread, - &str_msgq, can_dev, NULL, - TX_THREAD_PRIORITY, 0, K_NO_WAIT); - if (!str_tid) { - printk("ERROR spawning str_thread\n"); - } + while (1) { + change_led_frame.data[0] = toggle++ & 0x01 ? SET_LED : RESET_LED; + /* This sending call is none blocking. */ + can_send(can_dev, &change_led_frame, K_FOREVER, tx_irq_callback, + "LED change"); + k_sleep(SLEEP_TIME); - printk("Finished init. waiting for Interrupts\n"); + UNALIGNED_PUT(sys_cpu_to_be16(counter), + (u16_t *)&counter_frame.data[0]); + counter++; + /* This sending call is blocking until the message is sent. */ + can_send(can_dev, &counter_frame, K_MSEC(100), NULL, NULL); + k_sleep(SLEEP_TIME); + } }