canbus: canopen: add LED indicator support
Add support for CANopen LED indicators according to the CAN in Automation (CiA) 303-3 specification. This fixes #15278. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
2dcbd8bbc1
commit
308f204952
4 changed files with 133 additions and 0 deletions
|
@ -86,6 +86,32 @@ int canopen_storage_save(enum canopen_storage storage);
|
||||||
*/
|
*/
|
||||||
int canopen_storage_erase(enum canopen_storage storage);
|
int canopen_storage_erase(enum canopen_storage storage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef canopen_led_callback_t
|
||||||
|
* @brief CANopen LED indicator callback function signature.
|
||||||
|
*
|
||||||
|
* @param value true if the LED indicator shall be turned on, false otherwise.
|
||||||
|
* @param arg argument that was passed when LEDs were initialized.
|
||||||
|
*/
|
||||||
|
typedef void (*canopen_led_callback_t)(bool value, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize CANopen LED indicators.
|
||||||
|
*
|
||||||
|
* Initialize CANopen LED indicators and attach callbacks for setting
|
||||||
|
* their state. Two LED indicators, a red and a green, are supported
|
||||||
|
* according to CiA 303-3.
|
||||||
|
*
|
||||||
|
* @param nmt CANopenNode NMT object.
|
||||||
|
* @param green_cb callback for changing state on the green LED indicator.
|
||||||
|
* @param green_arg argument to pass to the green LED indicator callback.
|
||||||
|
* @param red_cb callback for changing state on the red LED indicator.
|
||||||
|
* @param red_arg argument to pass to the red LED indicator callback.
|
||||||
|
*/
|
||||||
|
void canopen_leds_init(CO_NMT_t *nmt,
|
||||||
|
canopen_led_callback_t green_cb, void *green_arg,
|
||||||
|
canopen_led_callback_t red_cb, void *red_arg);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,4 +4,5 @@ zephyr_library()
|
||||||
zephyr_library_sources_ifdef(CONFIG_CANOPEN CO_driver.c)
|
zephyr_library_sources_ifdef(CONFIG_CANOPEN CO_driver.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_CANOPEN_SYNC_THREAD canopen_sync.c)
|
zephyr_library_sources_ifdef(CONFIG_CANOPEN_SYNC_THREAD canopen_sync.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_CANOPEN_STORAGE canopen_storage.c)
|
zephyr_library_sources_ifdef(CONFIG_CANOPEN_STORAGE canopen_storage.c)
|
||||||
|
zephyr_library_sources_if_kconfig(canopen_leds.c)
|
||||||
zephyr_include_directories(.)
|
zephyr_include_directories(.)
|
||||||
|
|
|
@ -65,6 +65,21 @@ config CANOPEN_STORAGE_HANDLER_ERASES_EEPROM
|
||||||
Erase CANopen object dictionary EEPROM entries upon write to
|
Erase CANopen object dictionary EEPROM entries upon write to
|
||||||
object dictionary index 0x1011 subindex 1.
|
object dictionary index 0x1011 subindex 1.
|
||||||
|
|
||||||
|
config CANOPEN_LEDS
|
||||||
|
bool "CANopen LED indicators"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable support for CANopen LED indicators according to the CiA
|
||||||
|
303-3 specification.
|
||||||
|
|
||||||
|
config CANOPEN_LEDS_BICOLOR
|
||||||
|
bool "CANopen bicolor LED indicator"
|
||||||
|
depends on CANOPEN_LEDS
|
||||||
|
help
|
||||||
|
Handle CANopen LEDs as one bicolor LED, favoring the red LED
|
||||||
|
over the green LED in accordance with the CiA 303-3
|
||||||
|
specification.
|
||||||
|
|
||||||
config CANOPEN_SYNC_THREAD
|
config CANOPEN_SYNC_THREAD
|
||||||
bool "CANopen SYNC thread"
|
bool "CANopen SYNC thread"
|
||||||
default y
|
default y
|
||||||
|
|
91
subsys/canbus/canopen/canopen_leds.c
Normal file
91
subsys/canbus/canopen/canopen_leds.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Vestas Wind Systems A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <CANopen.h>
|
||||||
|
#include <canbus/canopen.h>
|
||||||
|
|
||||||
|
struct canopen_leds_state {
|
||||||
|
CO_NMT_t *nmt;
|
||||||
|
canopen_led_callback_t green_cb;
|
||||||
|
void *green_arg;
|
||||||
|
canopen_led_callback_t red_cb;
|
||||||
|
void *red_arg;
|
||||||
|
bool green : 1;
|
||||||
|
bool red : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct canopen_leds_state canopen_leds;
|
||||||
|
|
||||||
|
static void canopen_leds_update(struct k_timer *timer_id)
|
||||||
|
{
|
||||||
|
bool green = false;
|
||||||
|
bool red = false;
|
||||||
|
|
||||||
|
ARG_UNUSED(timer_id);
|
||||||
|
|
||||||
|
CO_NMT_blinkingProcess50ms(canopen_leds.nmt);
|
||||||
|
|
||||||
|
green = LED_GREEN_RUN(canopen_leds.nmt);
|
||||||
|
red = LED_RED_ERROR(canopen_leds.nmt);
|
||||||
|
|
||||||
|
#ifdef CONFIG_CANOPEN_LEDS_BICOLOR
|
||||||
|
if (red && canopen_leds.red_cb) {
|
||||||
|
green = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (canopen_leds.green_cb) {
|
||||||
|
if (green != canopen_leds.green) {
|
||||||
|
canopen_leds.green_cb(green, canopen_leds.green_arg);
|
||||||
|
canopen_leds.green = green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canopen_leds.red_cb) {
|
||||||
|
if (red != canopen_leds.red) {
|
||||||
|
canopen_leds.red_cb(red, canopen_leds.red_arg);
|
||||||
|
canopen_leds.red = red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
K_TIMER_DEFINE(canopen_leds_timer, canopen_leds_update, NULL);
|
||||||
|
|
||||||
|
void canopen_leds_init(CO_NMT_t *nmt,
|
||||||
|
canopen_led_callback_t green_cb, void *green_arg,
|
||||||
|
canopen_led_callback_t red_cb, void *red_arg)
|
||||||
|
{
|
||||||
|
k_timer_stop(&canopen_leds_timer);
|
||||||
|
|
||||||
|
canopen_leds.nmt = nmt;
|
||||||
|
|
||||||
|
/* Call existing callbacks to turn off LEDs */
|
||||||
|
if (canopen_leds.green_cb) {
|
||||||
|
canopen_leds.green_cb(false, canopen_leds.green_arg);
|
||||||
|
}
|
||||||
|
if (canopen_leds.red_cb) {
|
||||||
|
canopen_leds.red_cb(false, canopen_leds.red_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
canopen_leds.green_cb = green_cb;
|
||||||
|
canopen_leds.green_arg = green_arg;
|
||||||
|
canopen_leds.green = false;
|
||||||
|
canopen_leds.red_cb = red_cb;
|
||||||
|
canopen_leds.red_arg = red_arg;
|
||||||
|
canopen_leds.red = false;
|
||||||
|
|
||||||
|
/* Call new callbacks to turn off LEDs */
|
||||||
|
if (canopen_leds.green_cb) {
|
||||||
|
canopen_leds.green_cb(false, canopen_leds.green_arg);
|
||||||
|
}
|
||||||
|
if (canopen_leds.red_cb) {
|
||||||
|
canopen_leds.red_cb(false, canopen_leds.red_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nmt && (green_cb || red_cb)) {
|
||||||
|
k_timer_start(&canopen_leds_timer, K_MSEC(50), K_MSEC(50));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue