forked from test34/can_wizard
added linked list and control of adv filters + some fixes + finished
simple filtering
This commit is contained in:
parent
a841d5c44b
commit
c86191a104
6 changed files with 210 additions and 18 deletions
4
components/C-Linked-List/CMakeLists.txt
Normal file
4
components/C-Linked-List/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
idf_component_register(
|
||||||
|
INCLUDE_DIRS .
|
||||||
|
SRCS list.c
|
||||||
|
)
|
111
components/C-Linked-List/list.c
Normal file
111
components/C-Linked-List/list.c
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#ifndef LIST_DEF
|
||||||
|
#define LIST_DEF 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
File: list.c
|
||||||
|
Description: Implementation of linked list object functionality.
|
||||||
|
Created: March 21, 2017
|
||||||
|
Author: Matt Mumau
|
||||||
|
*/
|
||||||
|
|
||||||
|
// System dependencies
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Header
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
void list_push(List** head, void* data) {
|
||||||
|
List* node = malloc(sizeof(List));
|
||||||
|
if (node == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->data = data;
|
||||||
|
node->next = NULL;
|
||||||
|
|
||||||
|
if (*head == NULL) {
|
||||||
|
*head = node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((*head)->next != NULL) {
|
||||||
|
head = &(*head)->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*head)->next = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* list_pop(List** head) {
|
||||||
|
void* data = NULL;
|
||||||
|
|
||||||
|
if (*head == NULL) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
List** last = head;
|
||||||
|
while ((*head)->next != NULL) {
|
||||||
|
last = head;
|
||||||
|
head = &(*head)->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (void*) (*head)->data;
|
||||||
|
|
||||||
|
(*last)->next = NULL;
|
||||||
|
|
||||||
|
free(*head);
|
||||||
|
*head = NULL;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_insert(List** head, void* data) {
|
||||||
|
List* node = malloc(sizeof(List));
|
||||||
|
node->data = data;
|
||||||
|
node->next = *head;
|
||||||
|
|
||||||
|
*head = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int list_sizeof(List* head) {
|
||||||
|
if (head == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int size = 1;
|
||||||
|
|
||||||
|
while (head->next != NULL) {
|
||||||
|
size++;
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
List* list_get(List* head, unsigned int index) {
|
||||||
|
for (unsigned int i = 0; i < index; i++) {
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_remove(List** head, unsigned int index) {
|
||||||
|
if (!head || !*head || index >= list_sizeof(*head)) return;
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
List* prev_head = (*head);
|
||||||
|
(*head) = (*head)->next;
|
||||||
|
free(prev_head);
|
||||||
|
} else {
|
||||||
|
List* a_cursor = (*head);
|
||||||
|
for (unsigned int i = 1; i < index; i++) {
|
||||||
|
a_cursor = a_cursor->next;
|
||||||
|
}
|
||||||
|
List* tmp_cursor = a_cursor->next;
|
||||||
|
tmp_cursor = tmp_cursor->next;
|
||||||
|
free(a_cursor->next);
|
||||||
|
a_cursor->next = tmp_cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
46
components/C-Linked-List/list.h
Normal file
46
components/C-Linked-List/list.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef LIST_H_DEF
|
||||||
|
#define LIST_H_DEF 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
File: list.h
|
||||||
|
Description: Linked list library definition
|
||||||
|
Created: March 21, 2017
|
||||||
|
Author: Matt Mumau
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct List {
|
||||||
|
void* data;
|
||||||
|
struct List* next;
|
||||||
|
} List;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Push data to the end of the list.
|
||||||
|
*/
|
||||||
|
void list_push(List** head, void* data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove the final element of the list and return its data.
|
||||||
|
*/
|
||||||
|
void* list_pop(List** head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Insert the data object to the beginning of the list.
|
||||||
|
*/
|
||||||
|
void list_insert(List** head, void* data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the size of the list.
|
||||||
|
*/
|
||||||
|
unsigned int list_sizeof(List* head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the data of the node at the given ordinal number in the list.
|
||||||
|
*/
|
||||||
|
List* list_get(List* head, unsigned int index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete the item in the list at the given ordinal location (1 is the first).
|
||||||
|
*/
|
||||||
|
void list_remove(List** head, unsigned int index);
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,7 +13,11 @@
|
||||||
|
|
||||||
bool is_error_passive = false;
|
bool is_error_passive = false;
|
||||||
bool auto_recovery = false;
|
bool auto_recovery = false;
|
||||||
bool advanced_filtering = false;
|
adv_filt_t adv_filters = {
|
||||||
|
.filters = NULL,
|
||||||
|
.enabled = false,
|
||||||
|
.sw_filtering = false,
|
||||||
|
};
|
||||||
|
|
||||||
SemaphoreHandle_t can_mutex;
|
SemaphoreHandle_t can_mutex;
|
||||||
volatile can_status_t curr_can_state = { 0 };
|
volatile can_status_t curr_can_state = { 0 };
|
||||||
|
@ -112,7 +116,7 @@ void can_task(void* arg) {
|
||||||
sem_res = xSemaphoreTake(can_mutex, 0);
|
sem_res = xSemaphoreTake(can_mutex, 0);
|
||||||
if (sem_res == pdTRUE) {
|
if (sem_res == pdTRUE) {
|
||||||
while ((ret = twai_receive(&rx_msg, can_task_timeout)) == ESP_OK) {
|
while ((ret = twai_receive(&rx_msg, can_task_timeout)) == ESP_OK) {
|
||||||
if (advanced_filtering) {
|
if (adv_filters.sw_filtering) {
|
||||||
if (!matches_filters(&rx_msg)) continue;
|
if (!matches_filters(&rx_msg)) continue;
|
||||||
}
|
}
|
||||||
can_msg_to_str(&rx_msg, "recv ", data_bytes_str);
|
can_msg_to_str(&rx_msg, "recv ", data_bytes_str);
|
||||||
|
|
10
main/can.h
10
main/can.h
|
@ -6,6 +6,7 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <list.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char status[30];
|
char status[30];
|
||||||
|
@ -24,6 +25,12 @@ typedef enum {
|
||||||
CAN_RECOVERING = 5,
|
CAN_RECOVERING = 5,
|
||||||
} can_state_e;
|
} can_state_e;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool enabled;
|
||||||
|
List* filters;
|
||||||
|
bool sw_filtering;
|
||||||
|
} adv_filt_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
can_state_e state;
|
can_state_e state;
|
||||||
uint32_t msgs_to_tx; /**< Number of messages queued for transmission or awaiting transmission completion */
|
uint32_t msgs_to_tx; /**< Number of messages queued for transmission or awaiting transmission completion */
|
||||||
|
@ -39,10 +46,9 @@ typedef struct {
|
||||||
|
|
||||||
extern SemaphoreHandle_t can_mutex;
|
extern SemaphoreHandle_t can_mutex;
|
||||||
extern volatile can_status_t curr_can_state;
|
extern volatile can_status_t curr_can_state;
|
||||||
extern bool timestamp_enabled;
|
|
||||||
extern bool auto_recovery;
|
extern bool auto_recovery;
|
||||||
extern bool is_error_passive;
|
extern bool is_error_passive;
|
||||||
extern bool advanced_filtering;
|
extern adv_filt_t adv_filters;
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ static struct {
|
||||||
} cansend_args;
|
} cansend_args;
|
||||||
|
|
||||||
static int send_can_frame(int argc, char **argv) {
|
static int send_can_frame(int argc, char **argv) {
|
||||||
twai_message_t msg = {.extd = 1};
|
twai_message_t msg = { 0 };
|
||||||
char printf_str[70];
|
char printf_str[70];
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &cansend_args);
|
int nerrors = arg_parse(argc, argv, (void **) &cansend_args);
|
||||||
if (nerrors != 0) {
|
if (nerrors != 0) {
|
||||||
|
@ -56,7 +56,7 @@ static int send_can_frame(int argc, char **argv) {
|
||||||
if ((id_substr == NULL) || (strtok(NULL, "#") != NULL)) goto invalid_args;
|
if ((id_substr == NULL) || (strtok(NULL, "#") != NULL)) goto invalid_args;
|
||||||
int id_l = strlen(id_substr);
|
int id_l = strlen(id_substr);
|
||||||
int dt_l = data_substr == NULL ? 0 : strlen(data_substr);
|
int dt_l = data_substr == NULL ? 0 : strlen(data_substr);
|
||||||
if ((id_l > 8) || (dt_l > 16) || (id_l % 2) || (dt_l % 2)) goto invalid_args;
|
if ((id_l > 8) || (dt_l > 16) || (dt_l % 2)) goto invalid_args;
|
||||||
for (int i = 0; i < id_l; i++) if(!isxdigit((int) id_substr[i])) goto invalid_args;
|
for (int i = 0; i < id_l; i++) if(!isxdigit((int) id_substr[i])) goto invalid_args;
|
||||||
for (int i = 0; i < dt_l; i++) if(!isxdigit((int) data_substr[i])) goto invalid_args;
|
for (int i = 0; i < dt_l; i++) if(!isxdigit((int) data_substr[i])) goto invalid_args;
|
||||||
int msg_id;
|
int msg_id;
|
||||||
|
@ -72,6 +72,7 @@ static int send_can_frame(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
msg.data_length_code = dt_l / 2;
|
msg.data_length_code = dt_l / 2;
|
||||||
msg.identifier = msg_id;
|
msg.identifier = msg_id;
|
||||||
|
msg.extd = (id_l > 3);
|
||||||
esp_err_t res = twai_transmit(&msg, pdMS_TO_TICKS(1000));
|
esp_err_t res = twai_transmit(&msg, pdMS_TO_TICKS(1000));
|
||||||
switch(res) {
|
switch(res) {
|
||||||
case ESP_OK:
|
case ESP_OK:
|
||||||
|
@ -91,7 +92,7 @@ static int send_can_frame(int argc, char **argv) {
|
||||||
free(can_msg_str_buf);
|
free(can_msg_str_buf);
|
||||||
return 0;
|
return 0;
|
||||||
invalid_args:
|
invalid_args:
|
||||||
printf("Invalid arguments!\n");
|
print_w_clr_time("Invalid arguments!", LOG_COLOR_RED, true);
|
||||||
free(can_msg_str_buf);
|
free(can_msg_str_buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +116,7 @@ static const char* can_states_str[] = {
|
||||||
|
|
||||||
static int canstats(int argc, char **argv) {
|
static int canstats(int argc, char **argv) {
|
||||||
if (curr_can_state.state == CAN_NOT_INSTALLED) {
|
if (curr_can_state.state == CAN_NOT_INSTALLED) {
|
||||||
printf("CAN driver is not installed!\n");
|
print_w_clr_time("CAN driver is not installed!", LOG_COLOR_RED, true);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
const char *state_str = can_states_str[curr_can_state.state];
|
const char *state_str = can_states_str[curr_can_state.state];
|
||||||
|
@ -156,10 +157,10 @@ static int canup(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
if (canup_args.filters->count) {
|
if (canup_args.filters->count) {
|
||||||
f_config = my_filters;
|
f_config = my_filters;
|
||||||
print_w_clr_time("Using predefined filters.", LOG_COLOR_GREEN, true);
|
printf("Using %s filters.\n", adv_filters.enabled ? "smart" : "basic hw");
|
||||||
} else {
|
} else {
|
||||||
f_config = (twai_filter_config_t) TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
f_config = (twai_filter_config_t) TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||||||
print_w_clr_time("Using accept all filters.", LOG_COLOR_GREEN, true);
|
printf("Using accept all filters.\n");
|
||||||
}
|
}
|
||||||
esp_log_level_t prev_gpio_lvl = esp_log_level_get("gpio");
|
esp_log_level_t prev_gpio_lvl = esp_log_level_get("gpio");
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
|
@ -360,9 +361,9 @@ static void register_canrecover(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct arg_lit *dual;
|
struct arg_lit *dual_arg;
|
||||||
struct arg_str *code;
|
struct arg_str *code_arg;
|
||||||
struct arg_str *mask;
|
struct arg_str *mask_arg;
|
||||||
struct arg_end *end;
|
struct arg_end *end;
|
||||||
} canfilter_args;
|
} canfilter_args;
|
||||||
|
|
||||||
|
@ -372,20 +373,40 @@ static int canfilter(int argc, char **argv) {
|
||||||
arg_print_errors(stderr, canfilter_args.end, argv[0]);
|
arg_print_errors(stderr, canfilter_args.end, argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (canfilter_args.dual->count) {
|
const char* mask_s = canfilter_args.mask_arg->sval[0];
|
||||||
|
const char* code_s = canfilter_args.code_arg->sval[0];
|
||||||
|
int m_l = strlen(mask_s);
|
||||||
|
int c_l = strlen(code_s);
|
||||||
|
if (m_l != 8 || c_l != 8) goto invalid_args;
|
||||||
|
for (int i = 0; i < m_l; i++) if(!isxdigit((int) mask_s[i])) goto invalid_args;
|
||||||
|
for (int i = 0; i < c_l; i++) if(!isxdigit((int) code_s[i])) goto invalid_args;
|
||||||
|
uint32_t mask = 0;
|
||||||
|
uint32_t code = 0;
|
||||||
|
if (sscanf(mask_s, "%" PRIX32, &mask) < 1) goto invalid_args;
|
||||||
|
if (sscanf(code_s, "%" PRIX32, &code) < 1) goto invalid_args;
|
||||||
|
if (canfilter_args.dual_arg->count) {
|
||||||
my_filters.single_filter = false;
|
my_filters.single_filter = false;
|
||||||
|
print_w_clr_time("Setting hw filters in dual mode.", LOG_COLOR_GREEN, true);
|
||||||
} else {
|
} else {
|
||||||
my_filters.single_filter = true;
|
my_filters.single_filter = true;
|
||||||
|
print_w_clr_time("Setting hw filters in single mode.", LOG_COLOR_GREEN, true);
|
||||||
}
|
}
|
||||||
|
printf("mask: %" PRIX32 ", code: %" PRIX32 "\n", mask, code);
|
||||||
|
my_filters.acceptance_code = code;
|
||||||
|
my_filters.acceptance_mask = mask;
|
||||||
|
adv_filters.enabled = false;
|
||||||
|
adv_filters.sw_filtering = false;
|
||||||
return 0;
|
return 0;
|
||||||
|
invalid_args:
|
||||||
|
print_w_clr_time("Invalid arguments!", LOG_COLOR_RED, true);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_canfilter(void) {
|
static void register_canfilter(void) {
|
||||||
|
|
||||||
canfilter_args.mask = arg_str1("m", "mask", "<mask>", "Acceptance mask (as in esp-idf docs), uint32_t in hex form, 8 symbols.");
|
canfilter_args.mask_arg = arg_str1("m", "mask", "<mask>", "Acceptance mask (as in esp-idf docs), uint32_t in hex form, 8 symbols.");
|
||||||
canfilter_args.code = arg_str1("c", "code", "<code>", "Acceptance code (as in esp-idf docs), uint32_t in hex form, 8 symbols.");
|
canfilter_args.code_arg = arg_str1("c", "code", "<code>", "Acceptance code (as in esp-idf docs), uint32_t in hex form, 8 symbols.");
|
||||||
canfilter_args.dual = arg_lit0("d", NULL, "Use Dual Filter Mode.");
|
canfilter_args.dual_arg = arg_lit0("d", NULL, "Use Dual Filter Mode.");
|
||||||
|
|
||||||
const esp_console_cmd_t cmd = {
|
const esp_console_cmd_t cmd = {
|
||||||
.command = "canfilter",
|
.command = "canfilter",
|
||||||
|
|
Loading…
Reference in a new issue