Skip to content

Commit

Permalink
Initial slcan support
Browse files Browse the repository at this point in the history
  • Loading branch information
Baldanos committed Sep 9, 2017
1 parent df27df0 commit da84d50
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 20 deletions.
18 changes: 18 additions & 0 deletions drv/stm32cube/bsp_can.c
Expand Up @@ -328,6 +328,24 @@ bsp_status_t bsp_can_write(bsp_dev_can_t dev_num, CanTxMsgTypeDef* tx_msg)
return status;
}

/**
* @brief Sends a message in non blocking mode
* @param dev_num: CAN dev num.
* @param tx_msg: Message to send
* @retval status of the transfer. Always BSP_OK
*/
bsp_status_t bsp_can_put(bsp_dev_can_t dev_num, CanTxMsgTypeDef* tx_msg)
{
CAN_HandleTypeDef* hcan;

hcan = &can_handle[dev_num];

hcan->pTxMsg = tx_msg;

HAL_CAN_Transmit(hcan, 1);
return BSP_OK;
}

/**
* @brief Read a message in blocking mode and return the status.
* @param dev_num: CAN dev num.
Expand Down
5 changes: 5 additions & 0 deletions hydrabus/commands.c
Expand Up @@ -147,6 +147,7 @@ t_token_dict tl_dict[] = {
{ T_ONEWIRE, "1-wire" },
{ T_FLASH, "flash" },
{ T_TRIGGER, "trigger" },
{ T_SLCAN, "slcan" },
/* Developer warning add new command(s) here */

/* BP-compatible commands */
Expand Down Expand Up @@ -560,6 +561,10 @@ t_token tokens_mode_can[] = {
.flags = T_FLAG_SUFFIX_TOKEN_DELIM_INT,
.help = "Write a random byte (repeat with :<num>)"
},
{
T_SLCAN,
.help = "slcan (LAWICEL) mode"
},
{
T_EXIT,
.help = "Exit CAN mode"
Expand Down
1 change: 1 addition & 0 deletions hydrabus/commands.h
Expand Up @@ -139,6 +139,7 @@ enum {
T_ONEWIRE,
T_FLASH,
T_TRIGGER,
T_SLCAN,
/* Developer warning add new command(s) here */

/* BP-compatible commands */
Expand Down
1 change: 1 addition & 0 deletions hydrabus/hydrabus_bbio.h
Expand Up @@ -87,6 +87,7 @@
#define BBIO_CAN_FILTER 0b00000110
#define BBIO_CAN_WRITE 0b00001000
#define BBIO_CAN_SET_SPEED 0b01100000
#define BBIO_CAN_SLCAN 0b10100000

/*
* PIN control-specific commands
Expand Down
4 changes: 4 additions & 0 deletions hydrabus/hydrabus_bbio_can.c
Expand Up @@ -24,6 +24,7 @@
#include <string.h>
#include <ctype.h>

#include "hydrabus_mode_can.h"
#include "hydrabus_bbio.h"
#include "hydrabus_bbio_can.h"
#include "bsp_can.h"
Expand Down Expand Up @@ -113,6 +114,9 @@ void bbio_mode_can(t_hydra_console *con)
cprint(con, "\x00", 1);
}
break;
case BBIO_CAN_SLCAN:
slcan(con);
break;
default:
if ((bbio_subcommand & BBIO_CAN_WRITE) == BBIO_CAN_WRITE) {

Expand Down
286 changes: 266 additions & 20 deletions hydrabus/hydrabus_mode_can.c
Expand Up @@ -23,6 +23,7 @@
#include "hydrabus_mode_can.h"
#include "stm32f4xx_hal.h"
#include <string.h>
#include <stdio.h>

static int exec(t_hydra_console *con, t_tokenline_parsed *p, int token_pos);
static int show(t_hydra_console *con, t_tokenline_parsed *p);
Expand Down Expand Up @@ -59,6 +60,246 @@ static void show_params(t_hydra_console *con)
cprintf(con, "ID: 0x%0X\r\n", config[proto->dev_num].can_id);
}

static void can_slcan_out(t_hydra_console *con, CanRxMsgTypeDef *msg)
{
char outcode;
uint8_t i;

if (msg->RTR == CAN_RTR_DATA) {
outcode = 't';
} else {
outcode = 'r';
}
if (msg->IDE == CAN_ID_EXT) {
/*Extended frames have a capital letter */
outcode -= 32;
cprintf(con, "%c%08X%d",
outcode, msg->ExtId, msg->DLC);
} else {
cprintf(con, "%c%03X%d",
outcode, msg->StdId, msg->DLC);
}

for (i=0; i<msg->DLC; i++) {
cprintf(con, "%02X", msg->Data[i]);
}
cprint(con, "\r", 1);
}

static bsp_status_t can_slcan_in(uint8_t *slcanmsg, CanTxMsgTypeDef *msg)
{
uint8_t result = 0;
switch(slcanmsg[0]) {
case 't':
msg->RTR = CAN_RTR_DATA;
msg->IDE = CAN_ID_STD;
break;
case 'r':
msg->RTR = CAN_RTR_REMOTE;
msg->IDE = CAN_ID_STD;
break;
case 'T':
msg->RTR = CAN_RTR_DATA;
msg->IDE = CAN_ID_EXT;
break;
case 'R':
msg->RTR = CAN_RTR_REMOTE;
msg->IDE = CAN_ID_EXT;
break;
default:
return BSP_ERROR;
}

if (msg->IDE == CAN_ID_STD) {
result = sscanf((char *)slcanmsg, "%*[tr]%3X%1d%02X%02X%02X%02X%02X%02X%02X%02X",
(unsigned int *) &msg->StdId,
(unsigned int *) &msg->DLC,
(unsigned int *) &msg->Data[0],
(unsigned int *) &msg->Data[1],
(unsigned int *) &msg->Data[2],
(unsigned int *) &msg->Data[3],
(unsigned int *) &msg->Data[4],
(unsigned int *) &msg->Data[5],
(unsigned int *) &msg->Data[6],
(unsigned int *) &msg->Data[7]);
} else {
result = sscanf((char *)slcanmsg, "%*[TR]%8X%1d%02X%02X%02X%02X%02X%02X%02X%02X",
(unsigned int *) &msg->ExtId,
(unsigned int *) &msg->DLC,
(unsigned int *) &msg->Data[0],
(unsigned int *) &msg->Data[1],
(unsigned int *) &msg->Data[2],
(unsigned int *) &msg->Data[3],
(unsigned int *) &msg->Data[4],
(unsigned int *) &msg->Data[5],
(unsigned int *) &msg->Data[6],
(unsigned int *) &msg->Data[7]);
}
if(result >= (msg->DLC+2)) {
return BSP_OK;
} else {
return BSP_ERROR;
}
}

static void slcan_read_command(t_hydra_console *con, uint8_t *buff){
uint8_t i=0;
uint8_t input = 0;
while(!USER_BUTTON && input!='\r' && i<SLCAN_BUFF_LEN){
chnRead(con->sdu, &input, 1);
buff[i++] = input;
}
}

msg_t can_reader_thread (void *arg)
{
t_hydra_console *con;
con = arg;
chRegSetThreadName("CAN reader");
chThdSleepMilliseconds(10);
CanRxMsgTypeDef rx_msg;
mode_config_proto_t* proto = &con->mode->proto;

while (!USER_BUTTON && !chThdShouldTerminateX()) {
if(bsp_can_rxne(proto->dev_num)) {
bsp_can_read(proto->dev_num, &rx_msg);
can_slcan_out(con, &rx_msg);
} else {
chThdYield();
}
}
chThdExit((msg_t)1);
return (msg_t)1;
}

void slcan(t_hydra_console *con) {
uint8_t buff[SLCAN_BUFF_LEN];
CanTxMsgTypeDef tx_msg;
mode_config_proto_t* proto = &con->mode->proto;
thread_t *rthread = NULL;

init_proto_default(con);

while (!USER_BUTTON) {
slcan_read_command(con, buff);
switch (buff[0]) {
case 'S':
/*CAN speed*/
switch(buff[1]) {
case '0':
proto->dev_speed = 10000;
break;
case '1':
proto->dev_speed = 20000;
break;
case '2':
proto->dev_speed = 50000;
break;
case '3':
proto->dev_speed = 100000;
break;
case '4':
proto->dev_speed = 125000;
break;
case '5':
proto->dev_speed = 250000;
break;
case '6':
proto->dev_speed = 500000;
break;
case '7':
proto->dev_speed = 800000;
break;
case '8':
proto->dev_speed = 1000000;
break;
case '9':
proto->dev_speed = 2000000;
break;
}

if(bsp_can_set_speed(proto->dev_num, proto->dev_speed) == BSP_OK) {
cprint(con, "\n", 1);
}else {
cprint(con, "\x07", 1);
}
break;
case 's':
/*BTR value*/
/*Not implemented*/
cprint(con, "\x07", 1);
break;
case 'O':
/*Open channel*/
if(bsp_can_init(proto->dev_num, proto) == BSP_OK) {
rthread = chThdCreateFromHeap(NULL,
CONSOLE_WA_SIZE,
"SLCAN reader",
LOWPRIO,
(tfunc_t)can_reader_thread,
con);
cprint(con, "\r", 1);
}else {
cprint(con, "\x07", 1);
}
break;
case 'C':
/*Close channel*/
if(rthread != NULL) {
chThdTerminate(rthread);
chThdWait(rthread);
}
if(bsp_can_deinit(proto->dev_num) == BSP_OK) {
cprint(con, "\r", 1);
}else {
cprint(con, "\x07", 1);
}
break;
case 't':
case 'T':
case 'r':
case 'R':
/*Transmit*/
if(can_slcan_in(buff, &tx_msg) == BSP_OK) {
chSysLock();
if(bsp_can_write(proto->dev_num, &tx_msg) == BSP_OK) {
cprint(con, "\r", 1);
}else {
cprint(con, "\x07", 1);
}
chSysUnlock();
} else {
cprint(con, "\x07", 1);
}

break;
case 'F':
/*status*/
break;
case 'M':
case 'm':
/*Filter*/
bsp_can_init_filter(proto->dev_num, proto);
break;
case 'V':
/*Version*/
cprint(con, "V0101\n", 6);
break;
case 'N':
/*Serial*/
cprint(con, "NHYDR\n", 6);
break;
case 'Z':
/*Timestamp*/
/*Not implemented*/
cprint(con, "\x07", 1);
break;
}
}
chThdTerminate(rthread);
chThdWait(rthread);
}

static int init(t_hydra_console *con, t_tokenline_parsed *p)
{
mode_config_proto_t* proto = &con->mode->proto;
Expand Down Expand Up @@ -170,6 +411,9 @@ static int exec(t_hydra_console *con, t_tokenline_parsed *p, int token_pos)
while(!USER_BUTTON) {
read(con, NULL, 0);
}
case T_SLCAN:
slcan(con);
break;
default:
return t - token_pos;
}
Expand Down Expand Up @@ -216,31 +460,33 @@ static uint32_t write(t_hydra_console *con, uint8_t *tx_data, uint8_t nb_data)

status = BSP_ERROR;

/* Is ID an extended one ? */
if (config[proto->dev_num].can_id < 0b11111111111) {
tx_msg.StdId = config[proto->dev_num].can_id;
tx_msg.IDE = CAN_ID_STD;
} else {
tx_msg.ExtId = config[proto->dev_num].can_id;
tx_msg.IDE = CAN_ID_EXT;
}
if(can_slcan_in(tx_data, &tx_msg) != BSP_OK) {

/* Is ID an extended one ? */
if (config[proto->dev_num].can_id < 0b11111111111) {
tx_msg.StdId = config[proto->dev_num].can_id;
tx_msg.IDE = CAN_ID_STD;
} else {
tx_msg.ExtId = config[proto->dev_num].can_id;
tx_msg.IDE = CAN_ID_EXT;
}

tx_msg.RTR = CAN_RTR_DATA;
tx_msg.DLC = 0;
while(nb_data > i) {
tx_msg.Data[tx_msg.DLC] = tx_data[i];
tx_msg.DLC++;
tx_msg.RTR = CAN_RTR_DATA;
tx_msg.DLC = 0;
while(nb_data > i) {
tx_msg.Data[tx_msg.DLC] = tx_data[i];
tx_msg.DLC++;

if(tx_msg.DLC == 8) {
status = can_send_msg(con, &tx_msg);
tx_msg.DLC = 0;
if(tx_msg.DLC == 8) {
status = can_send_msg(con, &tx_msg);
tx_msg.DLC = 0;
}
i++;
}
i++;
}
if (tx_msg.DLC > 0) {
status = can_send_msg(con, &tx_msg);
}

status = can_send_msg(con, &tx_msg);

return status;
}

Expand Down

0 comments on commit da84d50

Please sign in to comment.